<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Giorgio Ciotti - Blog</title>
    <subtitle>Systems engineer building in Rust: developer tooling, infrastructure, and applied cryptography.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://giorgiociotti.com/blog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://giorgiociotti.com/blog/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-09-29T00:00:00+00:00</updated>
    <id>https://giorgiociotti.com/blog/atom.xml</id>
    <entry xml:lang="en">
        <title>Random Number Generator PCG Period Collapse</title>
        <published>2026-09-29T00:00:00+00:00</published>
        <updated>2026-09-29T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://giorgiociotti.com/blog/pcg-period-collapse/"/>
        <id>https://giorgiociotti.com/blog/pcg-period-collapse/</id>
        
        <content type="html" xml:base="https://giorgiociotti.com/blog/pcg-period-collapse/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>Keeping an ESP32 with Embassy Responsive While Doing Cryptography</title>
        <published>2026-09-20T00:00:00+00:00</published>
        <updated>2026-09-20T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://giorgiociotti.com/blog/blocking-crypto-on-embassy/"/>
        <id>https://giorgiociotti.com/blog/blocking-crypto-on-embassy/</id>
        
        <content type="html" xml:base="https://giorgiociotti.com/blog/blocking-crypto-on-embassy/">&lt;p&gt;Recently, I built a randomness oracle for an ESP32 board using Embassy.
I already knew about the cryptography that makes a randomness oracle tick, but I wanted to experiment with embedded Rust.&lt;/p&gt;
&lt;p&gt;Embassy is an async runtime for the embedded Rust world.
It provides the environment in which tasks execute, synchronization primitives, collaboration with hardware drivers, and more.
Think of it as Tokio, but for embedded &lt;code&gt;no_std&lt;/code&gt; environments.&lt;/p&gt;
&lt;p&gt;Computing cryptography on an HTTP server can prove to be problematic because of how many CPU cycles it takes.
In an async context, tasks are most often waiting on new IO or other hardware interrupts to be handled quickly.
Introducing blocking synchronous code comes with its own challenges, especially in embedded.
My fix was to give the cryptography &lt;strong&gt;its own Embassy executor on the ESP32&#39;s second core&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;As soon as the first request comes in, everything grinds to a halt.
If you don&#39;t do anything special, the ESP32+Embassy template starts &lt;strong&gt;exactly one single-core executor&lt;/strong&gt;.
When the request reaches its handler, the cryptographic computation blocks cooperative execution.&lt;/p&gt;
&lt;p&gt;There are other IO-heavy tasks that need to do some time-sensitive work and then go back to sleep.
For instance, keeping the Wi-Fi alive, accepting network packets, handling peripheral interrupts, and so on.
For these tasks, we use the &lt;code&gt;await&lt;/code&gt; keyword and Embassy knows what each task is waiting on and can wake them up as things go along.&lt;/p&gt;
&lt;p&gt;We&#39;d usually hand this CPU-heavy part of the task to &lt;code&gt;tokio::spawn_blocking&lt;/code&gt; to be executed in a thread where it can&#39;t block cooperative code.
Here, though, there&#39;s no concept of threads because there&#39;s no OS.&lt;/p&gt;
&lt;h2 id=&quot;task-management-in-static-memory-with-worker-tasks&quot;&gt;Task Management in Static Memory with Worker Tasks&lt;/h2&gt;
&lt;p&gt;The solution I picked is to create a second instance of an Embassy thread-mode &lt;code&gt;Executor&lt;/code&gt; on a separate core and offload CPU-heavy code to it.
This second core will only run worker tasks with the job of doing cryptographic computation.
Blocking code will run from start to finish, preventing other blocking code from running, but that&#39;s fine because it only blocks other cryptographic workers.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;// Start Core 1 Executor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;esp_rtos&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;start_second_core&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu_ctrl,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    software_interrupt1,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app_core_stack,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    move ||&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; executor&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; EXECUTOR_CORE1&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;init&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;esp_rtos&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;embassy&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Executor&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        executor&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;|&lt;/span&gt;&lt;span&gt;spawner&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;|&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;            for&lt;/span&gt;&lt;span&gt; task_id&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;WEB_TASK_POOL_SIZE&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                spawner&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;spawn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;crypto_worker_task&lt;/span&gt;&lt;span&gt;(task_id,&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span&gt;app_states[task_id])&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/CiottiGiorgio/esp32-rs-vrf-draw/blob/996662be428a6697ecb6fbfc852ef8eba4f0785c/src/web.rs#L202-L215&quot;&gt;&lt;code&gt;src/web.rs&lt;/code&gt;, lines 202–215&lt;/a&gt;)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;esp_rtos&lt;/code&gt; is the package that contains both the RTOS and an integration with Embassy.
Here, we only use the Embassy integration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another wrinkle is that Embassy works without a memory allocator.
The runtime memory for running a task needs to be static and defined at compile time.
We can&#39;t run these workers in a dynamically sized pool; we need to define how many workers (at least an upper bound) will be instantiated.&lt;/p&gt;
&lt;p&gt;This lets us &lt;strong&gt;map request handler workers to cryptographic workers 1:1&lt;/strong&gt;.
Each request worker is assigned an ID, and uses it to offload blocking work to its related cryptographic worker.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; WEB_TASK_POOL_SIZE&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 4&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; CRYPTO_REQUESTS&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Signal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CriticalSectionRawMutex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; RandomnessQuery&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; WEB_TASK_POOL_SIZE&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; CRYPTO_RESPONSES&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Signal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CriticalSectionRawMutex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; RandomnessResponse&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; WEB_TASK_POOL_SIZE&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Signal&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;new&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/CiottiGiorgio/esp32-rs-vrf-draw/blob/996662be428a6697ecb6fbfc852ef8eba4f0785c/src/web.rs#L43-L57&quot;&gt;&lt;code&gt;src/web.rs&lt;/code&gt;, lines 43–57&lt;/a&gt;)&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;async fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; serve_randomness&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    State&lt;/span&gt;&lt;span&gt;(state)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; State&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;static AppState&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Query&lt;/span&gt;&lt;span&gt;(query)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Query&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;RandomnessQuery&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Json&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;RandomnessResponse&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    CRYPTO_REQUESTS&lt;/span&gt;&lt;span&gt;[state&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span&gt;task_id]&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;signal&lt;/span&gt;&lt;span&gt;(query);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; res&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; CRYPTO_RESPONSES&lt;/span&gt;&lt;span&gt;[state&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span&gt;task_id]&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;wait&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Json&lt;/span&gt;&lt;span&gt;(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/CiottiGiorgio/esp32-rs-vrf-draw/blob/996662be428a6697ecb6fbfc852ef8eba4f0785c/src/web.rs#L94-L101&quot;&gt;&lt;code&gt;src/web.rs&lt;/code&gt;, lines 94–101&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A system with a queue could have been designed, but it would still have to be bounded because of the static memory constraint.
Also, it would make matching cryptographic requests with responses harder since everything goes through a single queue.&lt;/p&gt;
&lt;p&gt;Here&#39;s the code that computes the CPU-heavy part of the response:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[embassy_executor&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span&gt;task(pool_size &lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; WEB_TASK_POOL_SIZE&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;async fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; crypto_worker_task&lt;/span&gt;&lt;span&gt;(task_id&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; usize&lt;/span&gt;&lt;span&gt;, state&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;static AppState&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    loop&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; req&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; CRYPTO_REQUESTS&lt;/span&gt;&lt;span&gt;[task_id]&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;wait&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; signing_context&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;b&amp;quot;coin-toss-vrf&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; transcript&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;bytes&lt;/span&gt;&lt;span&gt;(req&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; (inout, proof, _)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; state&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span&gt;keypair&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;vrf_sign&lt;/span&gt;&lt;span&gt;(transcript);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; output&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; inout&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;to_preout&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;to_bytes&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; proof&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; proof&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;to_bytes&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        CRYPTO_RESPONSES&lt;/span&gt;&lt;span&gt;[task_id]&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;signal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;RandomnessResponse&lt;/span&gt;&lt;span&gt; { output, proof });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/CiottiGiorgio/esp32-rs-vrf-draw/blob/996662be428a6697ecb6fbfc852ef8eba4f0785c/src/web.rs#L135-L149&quot;&gt;&lt;code&gt;src/web.rs&lt;/code&gt;, lines 135–149&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&quot;alternative-solutions&quot;&gt;Alternative Solutions&lt;/h2&gt;
&lt;p&gt;There are a few other solutions to this very general problem.
I&#39;ll list the ones I didn&#39;t pick:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ESP32 Real-Time Operating System (RTOS) preempts blocking computation the usual way and also provides utilities for time-sensitive work.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InterruptExecutor&lt;/code&gt; in Embassy is a task executor that uses hardware interrupts to preempt lower-priority executors.&lt;/li&gt;
&lt;li&gt;Offloading computation to a dedicated peripheral while we &lt;code&gt;.await&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I tested the fix by sending concurrent requests to the ESP32.
Before, with everything on a single core, the network stack froze as soon as the cryptography started, and the board couldn&#39;t even accept incoming packets.
Now it accepts exactly 4 requests concurrently, one per worker.
The client receives the ACK for its request immediately, while the response takes as long as the cryptography needs.
There&#39;s still latency whenever all the workers are busy, but &lt;strong&gt;the Wi-Fi no longer drops&lt;/strong&gt;, so new requests can still come in and be served or rejected.&lt;/p&gt;
&lt;p&gt;Each platform handles concurrency and parallelism differently.
We&#39;re usually taught concurrency through OS threads, processes, preemptive scheduling, and synchronization primitives.
However, it&#39;s important to understand the architecture running the code because the ideas carry over, but the tools don&#39;t.&lt;/p&gt;
&lt;p&gt;On an ESP32, the primitives are purpose-built.
It&#39;s all statically allocated in the program memory at compile time, but in return we get new idioms such as executors on multiple cores and fine-grained concurrency control.&lt;/p&gt;
</content>
        
    </entry>
</feed>
