zoukankan      html  css  js  c++  java
  • linux wait queue详解

    #include <linux/wait.h> 
    
    typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
    int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);
    struct __wait_queue_head {
        spinlock_t lock;
        struct list_head task_list;
    };
    typedef struct __wait_queue_head wait_queue_head_t; 
    
    #define __WAITQUEUE_INITIALIZER(name, tsk) {                \
        .private    = tsk,                        \
        .func        = default_wake_function,            \
        .task_list    = { NULL, NULL } } 
    
    #define DECLARE_WAITQUEUE(name, tsk)                    \
        wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk) 
    
    #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                \
        .lock        = __SPIN_LOCK_UNLOCKED(name.lock),        \
        .task_list    = { &(name).task_list, &(name).task_list } } 
    
    #define DECLARE_WAIT_QUEUE_HEAD(name) \
        wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name) 
    
    #define __WAIT_BIT_KEY_INITIALIZER(word, bit)                \
        { .flags = word, .bit_nr = bit, } 
    
    extern void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *); 
    
    #define init_waitqueue_head(q)                \
        do {                        \
            static struct lock_class_key __key;    \
                                \
            __init_waitqueue_head((q), &__key);    \
        } while (0) 
    
    void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *key)
    {
        spin_lock_init(&q->lock);
        lockdep_set_class(&q->lock, key);
        INIT_LIST_HEAD(&q->task_list);
    } 

    操作:
    1. 定义"等待队列头"

    wait_queue_head_t my_queue;

    2. 初始化"等待队列头"

    init_waitqueue_head(&my_queue);

    同时, DECLARE_WAIT_QUEUE_HEAD(name)宏可以定义并初始化等待队列头.

    #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 } }

    3. 定义等待队列

    DECLARE_WAITQUEUE(name, tsk)

    tsk一般为当前进行current. 这个宏定义并初始化一个名为name的等待队列.

    #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 } }

    这时的private将会在wake_up()及其变种中使用, 最终将会默认调用default_wake_function()函数, 此函数实际上为try_to_wake_up(curr->private, mode, wake_flags);

    /***
     * try_to_wake_up - wake up a thread
     * @p: the to-be-woken-up thread
     * @state: the mask of task states that can be woken
     * @sync: do a synchronous wakeup?
     *
     * Put it on the run-queue if it's not already there. The "current"
     * thread is always on the run-queue (except when the actual
     * re-schedule is in progress), and as such you're allowed to do
     * the simpler "current->state = TASK_RUNNING" to mark yourself
     * runnable without the overhead of this.
     *
     * returns failure only if the task is already active.
     */
    static int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags);

    4. 添加/删除等待队列

    void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
    void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
    void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

    5. 等待事件

    wait_event(wq, condition)
    wait_event_timeout(wq, condition, timeout)
    wait_event_interruptible(wq, condition)
    wait_event_interruptible_timeout(wq, condition, timeout)

    6. 唤醒等待队列

    #define wake_up(x)            __wake_up(x, TASK_NORMAL, 1, NULL)
    #define wake_up_nr(x, nr)        __wake_up(x, TASK_NORMAL, nr, NULL)
    #define wake_up_all(x)            __wake_up(x, TASK_NORMAL, 0, NULL)
    #define wake_up_locked(x)        __wake_up_locked((x), TASK_NORMAL) 
    
    #define wake_up_interruptible(x)    __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)
    #define wake_up_interruptible_nr(x, nr)    __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL)
    #define wake_up_interruptible_all(x)    __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)
    #define wake_up_interruptible_sync(x)    __wake_up_sync((x), TASK_INTERRUPTIBLE, 1) 
    
    /**
     * __wake_up - wake up threads blocked on a waitqueue.
     * @q: the waitqueue
     * @mode: which threads
     * @nr_exclusive: how many wake-one or wake-many threads to wake up
     * @key: is directly passed to the wakeup function
     *
     * It may be assumed that this function implies a write memory barrier before
     * changing the task state if and only if any tasks are woken up.
     */
    void __wake_up(wait_queue_head_t *q, unsigned int mode,
                int nr_exclusive, void *key)
    {
        unsigned long flags; 
    
        spin_lock_irqsave(&q->lock, flags);
        __wake_up_common(q, mode, nr_exclusive, 0, key);
        spin_unlock_irqrestore(&q->lock, flags);
    }

    7. 在等待队列上睡眠

    void __sched sleep_on(wait_queue_head_t *q)
    long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout);
    void __sched interruptible_sleep_on(wait_queue_head_t *q);
    long __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout);
    #define __sched        __attribute__((__section__(".sched.text")))

    sleep_on()函数应该与wake_up()成对使用, interrupt_sleep_on()应该与wake_up_interruptible()成对使用

    #include <linux/wait.h> 
  • 相关阅读:
    rabbitmq无用使用guest用户远程连接
    SpringMVC 过滤器
    Spring MVC的Controller统一异常处理:HandlerExceptionResolver
    springMVC之mvc:interceptors拦截器的用法
    spring中排除某个类
    mysql中的CURRENT_TIMESTAMP
    [QT]Qt+VS2012+Win8 64Bit安装
    UOJ#55. 【WC2014】紫荆花之恋
    CodeChef SADPAIRS:Chef and Sad Pairs
    BZOJ4771: 七彩树
  • 原文地址:https://www.cnblogs.com/codestub/p/2144985.html
Copyright © 2011-2022 走看看