2010.01.20 Looks like I should be using set_current_state code in the sched.h header instead of directly setting the task state as I do in this code. 2010.01.20 Whoa! This seems to work on a simple test case of calling wait in one virtual terminal and then calling signal in another virtual terminal. It also works with back to back wait or signal calls that exit without action as designed. Note - rather than using separate virtual terminals I can just run wait in the background (./wait&). 2010.01.20 This simplest of experiments is intended to demonstrate that a wait() and signal() system call can be coded as a kernel module. Assume that we have only one task that can be waiting and keep that task in a single variable initialized to NULL pointer. struct task_struct *my_wait_task = NULL The wait() call will assign the currently running task. The global task variable current can be found in sched.c probably. Actually it is defined as get_current in . my_wait_task = current and then change the current state call schedule(). Further wait() calls see that my_wait_task is not NULL, so they return with no action. Or maybe zero success and not zero error. A signal() call that sees my_wait_task is NULL will return with no action (or a non-zero error value). Otherwise the signal() will wake up the task in my_wait_task and set my_wait_task to NULL. There is a race condition in this around the critical section of testing and setting my_wait_task in both wait and signal so I'll have to figure out what locking to use. The locking used in the kernel sleep_on and wake_up should work. On the other hand, consider the worst that could happen. Will that crash the kernel? I could get the code to work without properly protecting critical sections and then add the mutual exclusion. I could also play with trying to break something by causing a race condition problem to occur. On the other hand, why not just use the kernel code sleep_on and wake_up (in wait.h or sched.h) that uses an event queue and has all the critical region protection built in? Well, that would be experiment 2. And by the way, that code is all inline #define macro code!