Linux kernel wait Queue inquiry-wait_queue_t-wait_queue_head_t__linux

Source: Internet
Author: User
Tags mutex semaphore


Linux kernel wait queue inquiry-wait_queue_t-wait_queue_head_t

Related source version:

Linux kernel source version: linux-3.0.86

Uboot version: uboot-2010.12.

Android System Source version: Android-5.0.2 "

Waiting queues are one way in which the Linux kernel implements blocking access, while the amount of semaphore and completion for the Linux kernel is a low-level approach that is implemented with wait queues. As we know in the Linux kernel, there are many ways to implement the race, such as rotating locks, atomic operations, semaphores, RCU mechanisms, waiting queues. The difference is that in addition to the semaphore and wait queue when the resource is inaccessible, the CPU resources will be given up to invoke other processes (the Linux kernel is only a process concept, not a full line concept), while other ways of protecting large pieces of code will be strictly affected by the CPU performance (the specific principle to see the The implementation framework for waiting queues in the Linux kernel is already well designed, and it is only possible for the driver developer to simply invoke the relevant macro or function to complete the protection of the resource. We will only analyze the common waiting queues and not subdivide the waiting extensions.

The following functions are implemented with wait queues: When a condition is not satisfied, the current process blocks both hibernation and, when this condition is met, wakes up the process before hibernation. To implement this functionality, the code block is as follows (assuming that the following function blocks are in the same file for easy understanding):

Declare_wait_queue_head (a);//define a queue header

Condition = FALSE;

Process 1 Function 1

Wait_event (a,condition)//Condition condition is not satisfied the current process 1 sleeps until this condition is met, and then continues executing the code behind the function of process 1. It has several derivative versions listed below:

Wait_event_timeout

Wait_event_interruptible

Wait_event_interruptible_timeout

Wait_event_interruptible_exclusive ...

........

condition=false;//after the completion of the conditions to clear out, in order to call the next function 1 o'clock can achieve the function of cold resistance

Process 2 Function 2

The condition=true;//condition is first set up so that you can wake up and then execute the dormant code. The wait function has the condition of judgment, and if it is not satisfied, it continues to sleep.

WAKE_UP (A);//Wake Process 1, the following are the different versions of the wake functions that are used by the corresponding process 1:

Wake_up_interruptible

//.....

For the drive development project, as long as the above frame can be correctly implemented blocking function, not only to achieve when the condition is not satisfied with the process of blocking, when the conditions are met to wake up the corresponding process. In practical engineering, the blocking part is generally placed in the resource reading function, blocking when resources are not available. The wake-up function is generally placed in the interrupt, or receive, to allow the resource to enter the available state. The following is followed by an analysis of the internal principles of the various functions of the frameworks listed above. We only analyze the main thread and do not analyze the derived version.

Parse Declare_wait_queue_head (a);//define a queue header, and initialize

#define DECLARE_WAIT_QUEUE_HEAD (name) \

wait_queue_head_t name = __wait_queue_head_initializer (name)

#define __WAIT_QUEUE_HEAD_INITIALIZER (name) {\

. lock= __spin_lock_unlocked (name.lock), \

. task_list= {& (name). Task_list, & (name). Task_list}}

The initialization function above is to initialize some of the primitives in the above figure to initialize the

. task_list= {& (name). Task_list, & (name). Task_list}//the last and next initialization points pointed to by the task list for the queue header point to itself.

. Raw_lock = __arch_spin_lock_unlocked//of the pending queue is actually started as a unlock

Analysis Wait_event (a,condition);//Condition condition not satisfied the current process 1 sleeps until this condition is met, and then continues executing the code behind the function of process 1.

First list the function and parameters of this function according to the source code description: wait_event hibernate until condition becomes valid. Wq is used for waiting queues, waiting for queue headers. Conditon is a C-expression that is an event to wait for.

This process is put into hibernation (the taks_uninterruptible process enters the state to not be able to interrupt the wake-up, neither the process receives the interrupt signal nor is it awakened, specific meaning for a process if it was set to a state for this before being transferred by the scheduler to hibernation, This process cannot be scheduled to be restarted by the interrupt signal, which can only be awakened by the corresponding wake function. There are several different states of the process, as follows:

Task_running: Run state, the process is running in task_running it, the Scheduler can dispatch it to run. Periodically, according to the scheduling strategy.

Task_interruptible: interruptible state. If the process is running in task_interruptible, the process receives the interrupt signal and wakes up from the wait queue.

This wait queue will be awakened when the condition is satisfied. In order to wake up this function wake_up had to be invoked when condition changed.

#define Wait_event (Wq, condition) \

do {\

if (condition) \//If the condition is satisfied, exit directly

Break;\

__wait_event (Wq, condition);

} while (0)

#define __wait_event (Wq, condition) \

do {\

Define_wait (__wait); \//define wait queues, according to current process, and define a default wake-up function, wake up if no custom function is passed in, use the following default wake function to perform wake function

#define DEFINE_WAIT (name) define_wait_func (name, autoremove_wake_function)

. task_list= List_head_init ((name). task_list)

for (;;) {\

Prepare_to_wait (&wq, &__wait, task_uninterruptible);

[

Wait to prepare function This function completes the function is to set the Flage as ~wq_flag_exclusive and not mutually exclusive, wake up if the current hibernation process is mutually exclusive, only one mutex process can be awakened at a time, and a mutex-only process may be awakened all at once. Determines whether the current process has joined the wait queue, or joins a wait queue header via function __add_wait_queue if not joined. At the same time, the current process state is set to task_uninterruptible the state of the non interruptible wake-up. This process completes the process waiting for hibernation. This will require the wake function to wake up the process dispatch.

]

if (condition) \

Break;\

Schedule ()//Let the CPU manually schedule, when the current process is swapped out of the dispatch queue until the current process is satisfied before the state of the preparation condition setting is awakened because the task_uninterruptible state is set before the kernel process Scheduler can not actively call it, task_ The process of running state can be dispatched into the execution state by dispatching policy.

}\

Finish_wait (&wq, &__wait); \//when the current process wakes up and then executes the function it does the opposite of the prepare_to_wait, which requires that the process state be set to run Deletes the current process from the wait queue header at the same time.

} while (0)

Analysis Wake_up (A);//Wake Process 1, the following are the different versions of the wake functions that are used in the corresponding process 1:

__WAKE_UP (x, Task_normal, 1, NULL)

#define TASK_NORMAL (task_interruptible | task_uninterruptible)

__wake_up_common (q, Mode, nr_exclusive, 0, key);

static void __wake_up_common (wait_queue_head_t *q, unsigned int mode,

int nr_exclusive, int wake_flags, void *key)

{

wait_queue_t *curr, *next;

List_for_each_entry_safe (Curr, Next, &q->task_list, task_list) {//Wakeup wait queue on the head of the queue, which is a for loop that traverses all queues on the header.

Unsigned flags = curr->flags;

if (Curr->func (curr, mode, Wake_flags, key) &&

(Flags & wq_flag_exclusive) &&!--nr_exclusive)

break;//executes the wake function, and if it is a mutually exclusive process, only the number of nr_exclusive processes can be awakened. If hibernation is a specified non-mutex process, all mutexes can be awakened. Wake_up This function can wake up at least one mutex process and wake up all non-mutex processes. Invoke the Wake function specified above when defining the queue to wake us to join the wait process in the wait queue. After execution, enter wait_event to continue execution.

}

}

The core data structure relationship of the waiting queue is the queue header wait_queue_head_t as the structure header, then all the waiting processes join the wait_queue_t build queue, and finally the queue is added to the queue header. And multiple waiting queues can create a bidirectional cyclic link list in the join header of a linked list, which facilitates the deletion and construction of waiting queues.

The approximate flowchart

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.