Monday, April 4, 2016

Sleeping in the Kernel - Part 1

We will discuss here a simple way of sleeping and waking up a thread in there Kernel.

In Linux kernel, there are scenarios where a thread might be suspended/ or waiting for something else to happen voluntarily. In such a case, the thread should be allowed to sleep as much as possible and not scheduled unnecessary. Hence the thread will be Sleeping and waiting for events(Async or Sync). In other word, a process/thread is allowed to voluntarily relinquish the CPU.

One classic scenario could be that a thread is in sleep waiting for the Interrupt to occur and then goes to the scheduler queue and does it works. 

In Linux, the ready-to-run processes are maintained on a run queue.A ready-to-run process has the state TASK_RUNNING.Once the time-slice of a running process is over, the Linux scheduler picks up another appropriate process from the run queue and allocates CPU power to that process.

Two important process or task states which is important to discuss sleep :-

TASK_RUNNING A ready-to-run or running process/thread in the queue.

TASK_INTERRUPTIBLE  - The process/task is suspended and waiting for some event to occur - Interrupts or Signals, though need not be explicitly woken up by the code.

For all other task states, please refer the click here.

Sleep scenario with kernel code

At times, threads want to wait until a certain event occurs, such as a device to initialise, I/O to complete or a timer to expire. In such a case, the thread is said to sleep on that event. A thread can go to sleep using the schedule() function. The following code puts the executing thread to sleep:

sleeping_task = current;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
func1();
/* The rest of the code */

sleeping_task is used to store the context of the task so that it can be woken up later on interrupt/timer expiration or any similar event.

set_current_state() takes argument as the state of the task and switches the current task to that state. Hence in this case the task is brought out of the run queue and suspended or put to sleep till the code wakes up the task. Hence the code gets control over scheduling or state of the task.

When the schedule() function is called with the state as TASK_INTERRUPTIBLE in this case, the currently executing process is moved off the run queue before another process is scheduled. The effect of this is the executing process goes to sleep, as it no longer is on the run queue. Hence, it never is scheduled by the scheduler. And, that is how a process can sleep.

The schedule() function is used by the thread in this case to indicate to the scheduler that it can schedule some other process on the processor.

let's wake it up now. Given a reference to a task structure, the thread could be woken up by calling:
wake_up_process(sleeping_task);








No comments:

Post a Comment