Re: threads that won't yield

From: David Butenhof (David.Butenhof_at_hp.com)
Date: 06/18/03


Date: Wed, 18 Jun 2003 08:08:35 -0400

Frank Cusack wrote:

> On 17 Jun 2003 09:14:00 GMT Casper H.S. Dik <Casper.Dik@Sun.COM> wrote:
>> Frank Cusack <fcusack@fcusack.com> writes:
>>
>>>If the client thread starts running before accept() is called, won't
>>>the connect() fail? Even if not (ie, listen() is enough to allow
>>>connect() to succeed), I need a guarantee that the server thread runs
>>>whenever it is runnable, which doesn't seem to be happening.
>>
>> Do the system calls that set the scheduling policy succeed? (Using the
>> realtime class requires euid 0)
>
> I believe so.
>
> PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID
> 26734 root 2056K 1536K sleep 100 - 0:00:00 0.0% block/3
> 26734 root 2056K 1536K sleep 159 - 0:00:00 0.0% block/2
> 26734 root 2056K 1536K sleep 59 0 0:00:00 0.0% block/1
>
> This seems consistent with an initial thread in the TS class, and two
> spawned threads in the RT class at the min and max priorities. The
> lwpid's v. pri are consistent with the order of thread creation as well.
>
>>>And more basically, I explicitly call sched_yield() in the client, this
>>>does not start the server thread running. ugh.
>>
>> Any algorithm depending on sched_yield() to do something is broken.
>>
>> I'd make sure that the processes are indeed in the RT class.
>
> It's a single process. Why would depending on sched_yield() be broken?
> I know that the server thread is runnable: connect() returned in the
> client therefore accept() returned in the server. (Also, if I pause()
> instead of sched_yield() the server thread runs.) I know that the
> server thread has a higher priority. Doesn't sched_yield() guarantee
> that a higher priority runnable thread will run?
>
> SUSv3 says that
>
> A conforming implementation shall select the thread that is
> defined as being at the head of the highest priority non-empty
> thread list to become a running thread, ...
> ...
> When a running thread issues the sched_yield() function, the
> thread becomes the tail of the thread list for its priority.
>
> Now, granted, becoming "the tail of the thread list for its priority"
> does not mean it gives up the processor; but doesn't the first
> statement say that?
>
> The definition for sched_yield() does actually mention CPU:
>
> The sched_yield() function shall force the running thread to
> relinquish the processor until it again becomes the head of its
> thread list.

The POSIX standard defines the operation of sched_yield() only among
REALTIME (SCHED_FIFO, SCHED_RR, and now SCHED_SPORADIC) threads of equal
priority on a uniprocessor (technically "allocation domain of size 1").

That is, it's irrelevant when you have a timeshare thread, because it need
not follow the rules -- POSIX doesn't define the behavior of that
scheduling policy, much less how it relates to realtime scheduled threads.
It's irrelevant when you have a multiprocessor, because POSIX says so; you
may have both priority threads (even SCHED_FIFO) running simultaneously on
different processors. And it's irrelevant if you call sched_yield from a
low priority SCHED_FIFO thread while a higher priority SCHED_FIFO thread is
BLOCKED, because there's no thread to which it can yield. On the other
hand, if your higher priority thread isn't blocked, then it must be
RUNNING, because it cannot (on a uniprocessor with allocation domain 1) be
READY while the lower priority thread is RUNNING -- THAT is an absolute
violation of the standard.

So you see, any way you cut it, sched_yield is irrelevant in your situation.
Either it has nothing it CAN do, or it's not required by the standard to do
anything it might do.

-- 
/--------------------[ David.Butenhof@hp.com ]--------------------\
| Hewlett-Packard Company       Tru64 UNIX & VMS Thread Architect |
|     My book: http://www.awl.com/cseng/titles/0-201-63392-2/     |
\----[ http://homepage.mac.com/dbutenhof/Threads/Threads.html ]---/