Tasklet, wait_queue, completion, work_queue usage summary

Source: Internet
Author: User

Make a summary of the commonly used interrupt processors in the kernel to facilitate the adoption of the appropriate mechanism when appropriate.

 

Tasklet and work_queue are the mechanisms for deferred execution. They are implemented based on soft interruptions and completion based on wait_queue.

Bytes --------------------------------------------------------------------------------------------------------------
Tasklet

Small processes are mainly used to execute some small tasks. It is a waste of using full-featured processes for these tasks. It is also called the lower half of the interrupt, which is executed during soft interrupt processing.

Definition:

Struct tasklet_struct {struct tasklet_struct * next; unsigned long state; atomic_t count; void (* func) (unsigned long); unsigned long data ;};


Definition:

 

# Define DECLARE_TASKLET (name, func, data) struct tasklet_struct name = {NULL, 0, ATOMIC_INIT (0), func, data} # define DECLARE_TASKLET_DISABLED (name, func, data) struct tasklet_struct name = {NULL, 0, ATOMIC_INIT (1), func, data} enum {TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */TASKLET_STATE_RUN/* Tasklet is running (SMP only )*/};


Methods for initializing and destroying tasklet:

Void tasklet_init (struct tasklet_struct * t, void (* func) (unsigned long), unsigned long data) {t-> next = NULL; t-> state = 0; atomic_set (& t-> count, 0); t-> func = func; t-> data = data;} void tasklet_kill (struct tasklet_struct * t) {if (in_interrupt () printk ("Attempt to kill tasklet from interrupt \ n"); while (test_and_set_bit (TASKLET_STATE_SCHED, & t-> state )) {do {yield ();} while (test_bit (TASKLET_STATE_SCHED, & t-> state);} tasklet_unlock_wait (t); clear_bit (TASKLET_STATE_SCHED, & t-> state );}


Tasklet scheduling method:

 

Static inline void tasklet_schedule (struct tasklet_struct * t) {if (! Struct (TASKLET_STATE_SCHED, & t-> state) _ tasklet_schedule (t);} void _ tasklet_schedule (struct tasklet_struct * t) {unsigned long flags; local_irq_save (flags ); t-> next = NULL; * _ this_cpu_read (tasklet_vec.tail) = t; _ this_cpu_write (tasklet_vec.tail, & (t-> next); then (TASKLET_SOFTIRQ ); local_irq_restore (flags );}


 

Usage:
Tasklet_init-> tasklet_schedule

Bytes --------------------------------------------------------------------------------------------------------------
Wait_queue


It is used to wait for a process to wait for an event without frequent calls. The process is sleep while waiting, and the kernel automatically wakes up when the event occurs.

Usage 1 (add_wait_queue and wake_up combination ):
When the nand controller is used by a process, other processes are put into the waiting queue. After the first process is used up, call wake_up to wake up the waiting queue. The next process gets the right to use the nand controller.

 

# Define DECLARE_WAITQUEUE (name, tsk) wait_queue_t name = _ WAITQUEUE_INITIALIZER (name, tsk) # define _ WAITQUEUE_INITIALIZER (name, tsk ){. private = tsk ,. func = default_wake_function ,. task_list = {NULL, NULL} void add_wait_queue (wait_queue_head_t * q, wait_queue_t * wait) {unsigned long flags; wait-> flags & = ~ WQ_FLAG_EXCLUSIVE; spin_lock_irqsave (& q-> lock, flags); _ add_wait_queue (q, wait); spin_unlock_irqrestore (& q-> lock, flags );} <nand_base.c> static int nand_test_get_device (struct mtd_info * mtd, int new_state) {struct nand_chip * chip = mtd-> priv; spinlock_t * lock = & chip-> controller-> lock; wait_queue_head_t * wq = & chip-> controller-> wq; DECLARE_WAITQUEUE (wait, current); retry: spin_lock (lock);/* Hardware Controller shared among independent devices */if (! Chip-> controller-> active) chip-> controller-> active = chip; if (chip-> controller-> active = chip & chip-> state = FL_READY) {chip-> state = new_state; spin_unlock (lock); return 0;} if (new_state = fl_pm_susponded) {if (chip-> controller-> active-> state = fl_pm_suincluded) {chip-> state = fl_pm_suincluded; spin_unlock (lock); return 0 ;}} set_current_state (TASK_UNINTERRUPTIBLE ); add_wait_queue (wq, & wait); spin_unlock (lock); schedule (); remove_wait_queue (wq, & wait); goto retry;} static void cancel (struct mtd_info * mtd) {struct nand_chip * chip = mtd-> priv;/* Release the controller and the chip */spin_lock (& chip-> controller-> lock ); chip-> controller-> active = NULL; chip-> state = FL_READY; wake_up (& chip-> controller-> wq ); spin_unlock (& chip-> controller-> lock );}


 

 

Method 2 (prepare_to_wait and wake_up combination) can be used as a blocking method:

 

# Define DEFINE_WAIT_FUNC (name, function) wait_queue_t name = {. private = current ,. func = function ,. task_list = LIST_HEAD_INIT (name ). task_list), }# define DEFINE_WAIT (name) DEFINE_WAIT_FUNC (name, autoremove_wake_function)


 

Autoremove_wake_function calls default_wake_function and deletes the waiting queue member from the waiting queue.

 

Voidprepare_to_wait (wait_queue_head_t * q, wait_queue_t * wait, int state) {unsigned long flags; wait-> flags & = ~ WQ_FLAG_EXCLUSIVE; fig (& q-> lock, flags); if (list_empty (& wait-> task_list) _ add_wait_queue (q, wait); set_current_state (state ); spin_unlock_irqrestore (& q-> lock, flags);} static long do_CustomEvent_wait (long eventNum) {struct CustomEvent * tmp = NULL; struct CustomEvent * prev = NULL; pr_info ("Enten into % s, the eventNum is % d \ n", _ func __, eventNum); if (tmp = FindEventNum (eventNum, & pr Ev ))! = NULL) {DEFINE_WAIT (wait); prepare_to_wait (tmp-> p, & wait, TASK_INTERRUPTIBLE); schedule (); finish_wait (tmp-> p, & wait ); return eventNum;} return-1;} static long do_CustomEvent_signal (long eventNum) {struct CustomEvent * tmp = NULL; struct CustomEvent * prev = NULL; pr_info ("Enten into % s, the eventNum is % d \ n ", _ func __, eventNum); if (! (Tmp = FindEventNum (eventNum, & prev) return 0; wake_up (tmp-> p); return 1 ;}


 

Method 3 (wait_event and wake_up combination ):
This method sets the process status to TASK_UNINTERRUPTIBLE, and then determines whether the condition is met. If the condition is not met, the process is removed from the runqueue queue through schedule, this process enters the sleep state. Only when a process calls wake_up can it wake up again. After the process is awakened, it sets the process status to TASK_UNINTERRUPTIBLE again, and then determines whether the conditions are met. When the condition is met, the loop ends. finish_wait sets the process status to TASK_RUNNING and removes the corresponding items from the linked list of the waiting queue.


 

# Define _ wait_event (wq, condition) do {DEFINE_WAIT (_ wait); for (;) {prepare_to_wait (& wq, & __ wait, TASK_UNINTERRUPTIBLE ); if (condition) break; schedule () ;}finish_wait (& wq, & __ wait) ;}while (0) # define wait_event (wq, condition) do {if (condition) break; _ wait_event (wq, condition);} while (0)

 

Bytes --------------------------------------------------------------------------------------------------------------
Completion:
Based on the waiting queue, the kernel uses this mechanism to wait for an operation to end. Because it is similar to wait_queue usage, it is not described in detail.
Completion operation interface:
Init_completion () encapsulates the init_waitqueue_head () interface;
Wait_for_completion () encapsulates the wait_for_common () interface;
Complete () encapsulates the _ wake_up_common () interface.

Bytes --------------------------------------------------------------------------------------------------------------
Work_queue:

Because blocking operations cannot be performed during the interruption, and sometimes the value of some memory units or registers needs to be read during the interruption, you can consider using the working queue.

Definition of work queue:

Work queue is a means to extend the operation. Because they are executed in the user context through the Daemon, the function can sleep for any long time, which is irrelevant to the kernel. Replaced the previous kevented mechanism.

 
Use of Work queues:

To use a work queue, perform the following three steps:

1. Implement the task processing function

2. Create and initialize a job

3. Add a work task to a work queue and wait for system scheduling.


<Kernel/workqueue. c>

Int schedule_work (struct work_struct * work) int schedule_delayed_work (struct work_struct * dwork, unsigned long delay)

 

1. Define the job processing function:

Static void func (struct work_struct * work ){......}

 

2. Create and initialize a job

You can create and initialize a job in two ways:

1) create a job first, and then bind the processing function:
 

Struct work_struct xxx_wq; // create a job

 

During module initialization:

INIT_WORK (& xxx_wq, func); // initialize the job. The job must execute the function func.

 
2) initialize a job at the same time:
 

DECLARE_WORK (xxx_wq, func );


3. Add the task to the work queue in the interrupt processing function and wait for system scheduling.

Static inline bool queue_work (struct workqueue_struct * wq, struct work_struct * work) {return queue_work_on (WORK_CPU_UNBOUND, wq, work );}



Used to add a job to a work queue

The kernel creates a standard working queue events, which can be directly used if it is not necessary to create an independent working queue for each part of the kernel.

Static inline bool schedule_work (struct work_struct * work) // add the work task xxx_wq to the standard work queue events. After the interrupt processing is complete, run func {return queue_work (system_wq, work );}

 

Tasklet, wait_queue, completion, work_queue usage summary

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.