Skip to main content

Waitqueue

A "wait queue" in the Linux kernel is a data structure to manage threads that are waiting for some condition to become true; they are the normal means by which threads block (or "sleep") in kernel space.
While writing modules there might be situations where one might have to wait for input some condition to occur before proceeding further. Tasks that need such behavior can make use of the sleep functionality available in the kernel. 
In Linux sleeping is handled by a data structure called wait queue, which is nothing but a list of processes waiting for an input or  event.
To manage a wait queue ,we need a structure of the kind wait_queue_head_t, which is defined in linux/wait.h. Wait queue head can be initialized in the following ways 
  • Statically using: 
    • DECLARE_WAIT_QUEUE_HEAD(name); 
  • Dynamically using
    • wait_queue_head_t my_queue;
    • init_waitqueue_head(name), where "name" is name of queue on which task will be put to sleep.
 Once the wait queue has been created, we can put a task to sleep on the queue we created using one of the following. 
  • wait_event("queue","condition") : The task will keep waiting on the queue as long as the condition does not become true.If put to sleep using this call, the task can not be interrupted. 
  • wait_event_interruptible("queue","condition") : similar to wait_event, but it can be interrupted by other signals too. It is always preferable to use this interruptible way of sleeping so that the task can be stopped in case the condition never becomes true. 
  • wait_event_timeout("queue","condition","timeout") : The task will sleep on the queue until the condition becomes true or the timeout mentioned expires, which ever occurs first. The timeout is expressed in jiffies. Task can not be interrupted before the timeout if the condition does not become true. 
  • wait_event_interruptible_timeout("queue","condition","timeout") : Similar to wait_event_timeout but it can be interrupted. 
Once a task has been put to sleep we need to wake it up , which can be done using following : 
  • wake_up(queue)  : In case the task has been put to non interruptible sleep. 
  • wake_up_interruptible (queue) : In case the task has been put to an interruptible sleep. 

Comments

Popular posts from this blog

Spinlock implementation in ARM architecture

SEV and WFE are the main instructions used for implementing spinlock in case of ARM architecture . Let's look briefly at those two instructions before looking into actual spinlock implementation. SEV SEV causes an event to be signaled to all cores within a multiprocessor system. If SEV is implemented, WFE must also be implemented. Let's look briefly at those two instructions before looking into actual spinlock implementation. WFE If the Event Register is not set, WFE suspends execution until one of the following events occurs: an IRQ interrupt, unless masked by the CPSR I-bit an FIQ interrupt, unless masked by the CPSR F-bit an Imprecise Data abort, unless masked by the CPSR A-bit a Debug Entry request, if Debug is enabled an Event signaled by another processor using the SEV instruction. In case of  spin_lock_irq( )/spin_lock_irqsave( ) , as IRQs are disabled, the only way to to resume after WFE intruction has executed is to execute SEV ins

Explanation of "struct task_struct"

This document tries to explain clearly what fields in the structure task_struct do. It's not complete and everyone is welcome to add information. Let's start by saying that each process under Linux is defined by a structure task_struct. The following information are available (on kernel 2.6.7): - volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */ - struct thread_info *thread_info; a pointer to a thread_info... - atomic_t usage; used by get_task_struct(). It's also set in kernel/fork.c. This value acts like a reference count on the task structure of a process. It can be used if we don't want to hold the tasklist_lock. - unsigned long flags;    /* per process flags, defined below */ process flag can be, for example, PF_DEAD when exit_notify() is called. List is of possible values is in include/linux/sched.h - unsigned long ptrace; used by ptrace a system call that provides the ability to a parent process to observe and con

Macro "container_of"

Understanding container_of macro in the Linux kernel When you begin with the kernel, and you start to look around and read the code, you will eventually come across this magical preprocessor construct. What does it do? Well, precisely what its name indicates. It takes three arguments – a  pointer ,  type  of the container, and the  name  of the member the pointer refers to. The macro will then expand to a new address pointing to the container which accommodates the respective member. It is indeed a particularly clever macro, but how the hell can this possibly work? Let me illustrate… The first diagram illustrates the principle of the  container_of(ptr, type, member)  macro for who might find the above description too clumsy. I llustration of how the containter_of macro works. Bellow is the actual implementation of the macro from Linux Kernel: #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (