<span class="Apple-style-span" style="font-family: Helvetica; font-size: medium; "><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>I&#39;ve been trying to get our sound framework going on linux and have got stuck.  I wondered whether anyone has any experience getting round this problem on linux.  It is complicated so excuse the lengthy explanation.</div>
<div><br></div><div>Our sound processing depends on a high-prirority thread running for a short time every 20 milliseconds to push data through the sound processing paths (microphone recording, OpenAL for spatialization, and so on).  On linux this approach is not immediately applicable because (*)</div>
<div><br></div><div>a) linux&#39;s pthreads implementation does not allow non-superuser programs to create threads with other than the SCHED_OTHER scheduler, and</div><div>b) linux&#39;s pthreads implementation does not support different priorities for the SCHED_OTHER scheduler</div>
<div><br></div><div>and so it is not possible for a non-superuser program to create a thread that runs at a higher priority than any other thread in the process.</div><div><br></div><div>The approach I&#39;ve explored so far has been to replace the high-pririty thread with an interval timer, where a timer interrupt is delivered via a signal handler.  This approach won&#39;t work because it can very easily deadlock. For example there are non-reentrant locks in functions such as tz_convert (used within both localtime and localtime_r) such that if the signal is delivered during a call to localtime, any nested call to localtime, as is made by our logging code, will deadlock.  I can avoid deadlock in code under our own control, but not in platform functions such as localtime upon which we depend.</div>
<div><br></div><div>Another approach would be (should be!) to still use two threads (which are unfortunately of the same priority because of the above thread priority restriction) but to cause the main VM thread to yield to the sound processing thread.  In this approach the timer interrupt would signal a posix semaphore (via pthread_cond_signal) and then call pthread_yield. The sound processing thread would loop blocking on the semaphore via pthread_cond_wait.  But...</div>
<div><br></div><div>On contemporary linux (including CERN&#39;s distro) pthread_yield is implemented as a straight call of the sched_yield(2) system call which does not yield to other threads within the process, but to other processes within the process&#39;s static priority.  I quote:</div>
<div><br></div><div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">NAME</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       sched_yield - yield the processor</span></font></div>
<div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; "><br></span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">SYNOPSIS</span></font></div>
<div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       #include &lt;sched.h&gt;</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; "><br>
</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       int sched_yield(void);</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; "><br>
</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">DESCRIPTION</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       A  process can relinquish the processor voluntarily without blocking by</span></font></div>
<div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       calling sched_yield().  The process will then be moved to  the  end  of</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       the queue for its static priority and a new process gets to run.</span></font></div>
<div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; "><br></span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       Note:  If the current process is the only process in the highest prior-</span></font></div>
<div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       ity list at that time, this process will continue to run after  a  call</span></font></div><div><font class="Apple-style-span" face="Monaco" size="3"><span class="Apple-style-span" style="font-size: 12px; ">       to sched_yield().</span></font></div>
<div><br></div><div>So, although I have yet to confirm this, it looks like pthread_yield will not yield to the other thread.  [I have confirmed that pthread_yield is a direct call of sched_yield(2) however].  The manual page could be incorrect, but my understanding is that on linux pthreads are a user-space implementation and therefore there isn&#39;t any way that a call to sched_yield is going to yield to another thread.</div>
<div><br></div><div><br></div><div>So my questions are</div><div>- is there any way I&#39;m missing to create different priority threads in a non-superuser process?</div><div>- is there an implementation of pthread_yield&#39;s intended functionality I&#39;m missing that will yield to other threads within the process?</div>
<div><br></div><div><br></div><div>best</div><div>Eliot</div><div><br></div><div>(*) see sched_setscheduler(2) and in particular that RLIMIT_RTPRIO for non-superuser programs is a maximum of 0, so one can&#39;t change the static priority of a non-superuser program either.</div>
</div></span>