[Kernel sync] The completion of Linux kernel synchronization mechanism

Source: Internet
Author: User

Transferred from: http://blog.csdn.net/bullbat/article/details/7401688

A common pattern in kernel programming is to initialize an activity outside the current thread, and then wait for the activity to end. The activity might be to create a new kernel thread or a new user-space process, a request for an existing process, or some type of hardware action, and so on. In this case, we can use semaphores to synchronize the two tasks. However, another mechanism--completion interface is provided in the kernel. Completion is a lightweight mechanism that allows a thread to tell another thread that a job has been completed.

Structure and initialization

The implementation of completion in the kernel is based on the wait queue (the theory of waiting queue is described in the previous article), and the completion structure is simple:

[CPP]View PlainCopyprint?
    1. struct Completion {
    2. unsigned int done; /* Atomic weight for synchronization * /
    3. wait_queue_head_t wait; / * Wait for event queue * /
    4. };

As with semaphores, initialization is divided into static initialization and dynamic initialization in two cases:

Static initialization:

[CPP]View PlainCopyprint?
    1. #define Completion_initializer (work) \
    2. {0, __wait_queue_head_initializer (work). WAIT)}
    3. #define DECLARE_COMPLETION (work) \
    4. struct Completion work = Completion_initializer (work)

Dynamic initialization:

[CPP]View PlainCopyprint?
    1. static inline void init_completion (struct completion *x)
    2. {
    3. X->done = 0;
    4. Init_waitqueue_head (&x->wait);
    5. }

It can be seen that both types of initialization will be used to synchronize the done atomic weight 0, we will see later, the variable in the wait correlation function minus one, add one in the complete series function.

Realize

Synchronous functions are generally paired, and completion is no exception, so let's take a look at the most basic implementations of the two complete and wait_for_completion functions.

The wait_for_completion is eventually implemented by the following function:

[CPP]View PlainCopy print?
  1. Static inline long __sched
  2. Do_wait_for_common (struct completion *x, long timeout, int state)
  3. {
  4. if (!x->done) {
  5. Declare_waitqueue (wait, current);
  6. Wait.flags |= wq_flag_exclusive;
  7. __add_wait_queue_tail (&x->wait, &wait);
  8. Do {
  9. if (signal_pending_state (state, current)) {
  10. Timeout =-erestartsys;
  11. Break ;
  12. }
  13. __set_current_state (state);
  14. SPIN_UNLOCK_IRQ (&x->wait.lock);
  15. Timeout = schedule_timeout (timeout);
  16. SPIN_LOCK_IRQ (&x->wait.lock);
  17. } while (!x->done && timeout);
  18. __remove_wait_queue (&x->wait, &wait);
  19. if (!x->done)
  20. return timeout;
  21. }
  22. x->done--;
  23. return timeout?: 1;
  24. }

and complete is implemented as follows:

[CPP]View PlainCopyprint?
    1. void complete (struct completion *x)
    2. {
    3. unsigned long flags;
    4. Spin_lock_irqsave (&x->wait.lock, flags);
    5. x->done++;
    6. __wake_up_common (&x->wait, Task_normal, 1, 0, NULL);
    7. Spin_unlock_irqrestore (&x->wait.lock, flags);
    8. }

Do not look at the kernel implementation of the source code we can also think of his implementation, is not only in the wait function loop waiting for done to become available (positive), and the other side of the complete function is the wake function, of course, do add one, wake up the function to be processed. Yes, see from the code above, as we think. The kernel does the same.

Use

Use the examples in LDD3:

[CPP]View PlainCopyprint?
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/sched.h>
  4. #include <linux/kernel.h>
  5. #include <linux/fs.h>
  6. #include <linux/types.h>
  7. #include <linux/completion.h>
  8. Module_license ("GPL");
  9. static int complete_major=250;
  10. Declare_completion (comp);
  11. ssize_t complete_read (struct file *filp,char __user *buf,size_t count,loff_t *pos)
  12. {
  13. PRINTK (kern_err "process%i (%s) going to sleep\n", Current->pid,current->comm);
  14. Wait_for_completion (&comp);
  15. PRINTK (Kern_err "Awoken%i (%s) \ n", Current->pid,current->comm);
  16. return 0;
  17. }
  18. ssize_t complete_write (struct file *filp,const char __user *buf,size_t count,loff_t *pos)
  19. {
  20. PRINTK (kern_err "process%i (%s) awakening the readers...\n", Current->pid,current->comm);
  21. Complete (&COMP);
  22. return count;
  23. }
  24. struct File_operations complete_fops={
  25. . Owner=this_module,
  26. . Read=complete_read,
  27. . Write=complete_write,
  28. };
  29. int complete_init (void)
  30. {
  31. int result;
  32. Result=register_chrdev (Complete_major,"complete", &complete_fops);
  33. if (result<0)
  34. return result;
  35. if (complete_major==0)
  36. Complete_major=result;
  37. return 0;
  38. }
  39. void Complete_cleanup (void)
  40. {
  41. Unregister_chrdev (Complete_major,"complete");
  42. }
  43. Module_init (Complete_init);
  44. Module_exit (Complete_cleanup);

Test steps:

1, Mknod/dev/complete creates a complete node, and on Linux the driver needs to manually create the file node.

2, Insmod Complete.ko Insert the driver module, it is important to note that because our code is manually assigned to the device number, it is likely to be used by the system, so if this happens, view the/proc/devices file. Find a device number that is not being used.

3, Cat/dev/complete is used to read the device, call the device read function

4. Open another terminal input echo "Hello" >/dev/complete this command is used to write to the device.

[Kernel sync] The completion of Linux kernel synchronization mechanism

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.