The only reason I do my own scheduling in user space is
because I need to control execution time slices. Thus, if
there was a way to set the time slice for a LinuxThread,
then I could just write a nice wrapper lib where MyThreads
would be mapped one-on-one to LinuxThreads. And ofcourse
figure out an efficient means to controll the slices with
respect to process nesting hierarchies.
However, setting time slices for processes/threads is not possible with Linux. The time slice "belonging" to a process is just the side effect of the priority based scheduling mecanism. Some other path has to be explored.
It is not currently possible for one thread to yield directly to another thread. I.e. a thread can only yield to the system, which will pick the next thread as it sees fit. However, yielding directly to another thread wouldn't really mess up anything if the scheduler was kept unaware of this "directed yield". Any time left of the slice would be used by the second thread, but the first one would still "pay" for it. Preemprion would work as if the first thread was still running. Such a yielding scheme could be used to do some really cool libs for process modelling :-)
Take a look at the report "CPU Inheritance Scheduling" released by the Fluke project. The idea is fleshed out pretty nicely there.
Making a forced context switch a la setcontext(ucontext_t*) must somehow make sure that not only the NPC and SP + registers are switched. Threads do afterall have individual signal masks and so on. There seems to be an inherent conflict in doing a directed yield without bringing in system scheduling and at the same time making sure all parts of the new thread are activated properly.
It shouldn't be too bloody difficult though. It's my wild guess that there is something in the kernel which could aptly be called a "context switching atom". The scheduler utilizes this atom to go from kernel space into user space when the next-to-run process is chosen. If this atom was made usable from user space via a system call then any process/thread could yield its time to anyone who is known to need it better than the yielder. One could think of it as a way to safely managing CPU resources "better" than the system already does.