LWN.net Logo

Short sleeps suffering from slack

Short sleeps suffering from slack

Posted Feb 24, 2012 0:29 UTC (Fri) by cmccabe (guest, #60281)
Parent article: Short sleeps suffering from slack

Ideal glibc implementation of sched_yield / sleep(0):

void sched_yield(void) {
fprintf(stderr, "You are a bad developer. Go away.\n");
}


(Log in to post comments)

Short sleeps suffering from slack

Posted Feb 25, 2012 21:08 UTC (Sat) by nevets (subscriber, #11875) [Link]

I mostly agree with you but there are a small set of legitimate uses of sched_yield(). The only real use case I can think of is a set of real time threads that are simulating its own voluntary scheduler.

If you have a set of threads all at the same priority, running FIFO and pinned to the same CPU, you can use sched_yield() to put yourself behind the other threads with the same priority and let them work. I've been on one project that did this.

The kernel stop_machine mechanism use to do this. It used yield() to let its other threads get the scheduler (all running highest FIFO priority). It did this method up till v2.6.26, after that, the algorithm was changed.

Short sleeps suffering from slack

Posted Feb 26, 2012 22:48 UTC (Sun) by cmccabe (guest, #60281) [Link]

I'm not too familiar with SCHED_FIFO. But can't you use select(0, NULL, NULL, NULL, 0) to do the same thing? System calls are cancellation points, at least.

Incidentally, I was around for the cooperative multitasking days on Mac OS 6. It was not good. I'm sure there's some rationale for simulating that kind of thing in userspace, but a lot of times it smells like doing something in userspace that you ought to be doing in the kernel.

Short sleeps suffering from slack

Posted Feb 27, 2012 12:21 UTC (Mon) by jengelh (subscriber, #33263) [Link]

select(timeout=0)? That's just as bad as sleep(0). sched_yield() looks a lot better, and since it is also a system call, there is your cancellation point.

Short sleeps suffering from slack

Posted Mar 1, 2012 13:12 UTC (Thu) by farnz (guest, #17727) [Link]

There are two problem cases where that's a bad implementation:

  1. sleep(0) where the 0 is not a hard-coded constant, but the result of a time calculation. The application doesn't actually mind that the sleep takes extra time, as it's aiming to do things like "sleep until the next work item is due to start", and can cope if it's late (e.g. a task scheduler aiming to kick off work every 60 seconds - if the work takes more than 60 seconds unexpectedly, it has to cope anyway). Such an application is probably doing a calculation of the form "next start time - current time"[2] to get the sleep time.
  2. sched_yield in a SCHED_FIFO context. While the POSIX definition of sched_yield doesn't require it to be anything other than a no-op, for the specific case of SCHED_FIFO there's a good reason to implement it as "let any other runnable task of same priority as this task run"; absent such an implementation, there is no way for multiple co-operating SCHED_FIFO tasks to say "I still want the CPU, but if another task of equal priority wants the CPU, let it have it".

Note that the second case is specific to SCHED_FIFO - other scheduling algorithms will preempt a CPU-bound task if something else of same priority needs the CPU. SCHED_FIFO specifically does not allow that to happen, so you need some sensible mechanism for a task to say "I'm still CPU-bound, but this is an appropriate point to preempt me if another task needs to run".

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds