<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Processes on Roberto Selbach</title><link>https://rselbach.com/tags/processes/</link><description>Recent content in Processes on Roberto Selbach</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Wed, 16 Oct 2002 06:38:21 +0000</lastBuildDate><atom:link href="https://rselbach.com/tags/processes/index.xml" rel="self" type="application/rss+xml"/><item><title>Waking a Process in Linux 2.4</title><link>https://rselbach.com/waking-a-process-in-linux-24/</link><pubDate>Wed, 16 Oct 2002 06:38:21 +0000</pubDate><guid>https://rselbach.com/waking-a-process-in-linux-24/</guid><description>&lt;p&gt;I had a character driver polling a flag in a loop. It worked, if one defines working as consuming a processor while waiting for a byte that might arrive next Tuesday. A wait queue is the proper mechanism.&lt;/p&gt;
&lt;p&gt;The process prepares to sleep on a queue, checks the condition, and asks the scheduler to run something else. The producer changes the condition and wakes sleepers. In 2.4 code, the shape can be written with the wait-event helpers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DECLARE_WAIT_QUEUE_HEAD&lt;/span&gt;(read_wait);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; data_ready;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;wait_event_interruptible&lt;/span&gt;(read_wait, data_ready))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;ERESTARTSYS;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When data becomes available:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;data_ready &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;wake_up_interruptible&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;read_wait);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The condition is the important part. Wakeups are hints to run and check state, not ownership of an event. A process may wake because of a signal, another reader may consume the data first, or the condition may change again before this process runs. The helper loops around the test, which avoids treating a wakeup as a guarantee.&lt;/p&gt;
&lt;p&gt;For interruptible sleep, a pending signal returns control to the caller. Driver code should propagate the interruption rather than quietly restarting a complicated operation itself. User space can then decide what to do.&lt;/p&gt;
&lt;p&gt;The producer and consumer still need proper locking around shared state. A wait queue arranges sleeping and waking; it does not make &lt;code&gt;data_ready&lt;/code&gt; and the associated buffer safe on a multiprocessor machine. I protect the state with the lock appropriate to all its callers, taking care not to sleep while holding a spinlock.&lt;/p&gt;
&lt;p&gt;Underneath, the scheduler tracks each process in a &lt;code&gt;task_struct&lt;/code&gt;, including its state. A sleeping task is not selected to run until it is made runnable again. This is why sleeping is so much cheaper than repeatedly checking a flag, and why calling a sleeping function from interrupt context is forbidden: there is no process context there to put to sleep.&lt;/p&gt;
&lt;p&gt;Nonblocking reads need a parallel path. If no data is ready and the file was opened with &lt;code&gt;O_NONBLOCK&lt;/code&gt;, I return &lt;code&gt;-EAGAIN&lt;/code&gt; instead of joining the wait queue. The same readiness condition should drive &lt;code&gt;poll&lt;/code&gt; so programs using &lt;code&gt;select&lt;/code&gt; or &lt;code&gt;poll&lt;/code&gt; observe exactly what a blocking read would observe. Three slightly different definitions of “ready” produce wonderfully intermittent programs.&lt;/p&gt;
&lt;p&gt;I prefer wait queues over homemade polling even when the first version seems simpler. The caveat is to make the condition explicit and recheck it under the same synchronization used by the producer. Otherwise the code gains a pleasant nap and an occasional missed wakeup, usually during demonstrations.&lt;/p&gt;</description></item></channel></rss>