linux 内核 条件等待,Linux内核机制之等待队列完全分析

//用记事本分析的等待队列机制

static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);//定义一个等待队列头

/*定义队列头分析*/

/**************************************************************************************/

struct list_head {

struct list_head *next, *prev;

};

struct __wait_queue_head {

spinlock_t lock;

struct list_head task_list;

};

typedef struct __wait_queue_head wait_queue_head_t;

/*初始化自旋锁和链表头*/

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

/**************************************************************************************/

//hub驱动示例

wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) || kthread_should_stop());

//跟踪调用链

#define wait_event_freezable(wq, condition)    wait_event_interruptible(wq, condition)

//跟踪调用链

#define wait_event_interruptible(wq, condition)                \

({                                    \

int __ret = 0;                            \

if (!(condition))                        \//先判断下调节,看是否满足

__wait_event_interruptible(wq, condition, __ret);    \

__ret;                                \

})

//继续跟踪调用链

#define __wait_event_interruptible(wq, condition, ret)            \

do {                                    \

DEFINE_WAIT(__wait);                        \//定义一个等待队列项

\

for (;;) {                            \

prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);    \

if (condition)                        \//再次判断条件是否满足

break;                        \

if (!signal_pending(current)) {                \//判断是否有信号要处理?

schedule();                    \//调度,睡眠

continue;                    \//唤醒后从该处继续执行?

}                            \

ret = -ERESTARTSYS;                    \

break;                            \

}                                \

finish_wait(&wq, &__wait);                    \

} while (0)

//分析DEFINE_WAIT()

typedef struct __wait_queue wait_queue_t;

struct __wait_queue {

unsigned int flags;

#define WQ_FLAG_EXCLUSIVE    0x01

void *private;

wait_queue_func_t func;

struct list_head task_list;

};

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

#define DEFINE_WAIT_FUNC(name, function)                \

wait_queue_t name = {                        \//赋值为当前进程的描述符

.private    = current,                \//唤醒时执行函数

.func        = function,                \

.task_list    = LIST_HEAD_INIT((name).task_list),    \//用于链接到等待队列头

}

void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)

{

unsigned long flags;

wait->flags &= ~WQ_FLAG_EXCLUSIVE;//把互斥标志清为0

spin_lock_irqsave(&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 inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)

{

list_add(&new->task_list, &head->task_list);

}

/*唤醒的处理,以hub唤醒为例*/

static void kick_khubd(struct usb_hub *hub)

{

unsigned long    flags;

spin_lock_irqsave(&hub_event_lock, flags);

if (!hub->disconnected && list_empty(&hub->event_list)) {

list_add_tail(&hub->event_list, &hub_event_list);//把等待的条件置为真

/* Suppress autosuspend until khubd runs */

usb_autopm_get_interface_no_resume(

to_usb_interface(hub->intfdev));

wake_up(&khubd_wait);//唤醒等待的进程

}

spin_unlock_irqrestore(&hub_event_lock, flags);

}

#define wake_up(x)    __wake_up(x, TASK_NORMAL, 1, NULL)

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);

}

//唤醒nr_exclusive个排他性进程

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) {//取出队列的每一个等待项

unsigned flags = curr->flags;

//针对普通的先执行function函数,唤醒所有的非互斥等待节点和nr_exclusive个互斥节点

if (curr->func(curr, mode, wake_flags, key) &&(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)

break;

}

}

/*导致上面注册*/

int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)

{

int ret = default_wake_function(wait, mode, sync, key);

if (ret)

list_del_init(&wait->task_list);//从等待队列中删除

return ret;

}

int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags, void *key)

{

return try_to_wake_up(curr->private, mode, wake_flags);//唤醒等待的进程

}

//从睡眠的地方继续调度

void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)

{

unsigned long flags;

__set_current_state(TASK_RUNNING);//设置该进程的状态为TASK_RUNNING

if (!list_empty_careful(&wait->task_list)) {

spin_lock_irqsave(&q->lock, flags);

list_del_init(&wait->task_list);//从等待队列中删除

spin_unlock_irqrestore(&q->lock, flags);

}

}

//有两个函数分别是增加互斥和不互斥的节点

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);

}

EXPORT_SYMBOL(add_wait_queue);

void add_wait_queue_exclusive(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_tail(q, wait);

spin_unlock_irqrestore(&q->lock, flags);

}

//因为completion机制是基于等待队列的,所以在此一并分析

struct completion {

unsigned int done;

wait_queue_head_t wait;

};

init_completion(&us->scanning_done);

static inline void init_completion(struct completion *x)

{

x->done = 0;

init_waitqueue_head(&x->wait);

}

#define init_waitqueue_head(q)                \

do {                        \

static struct lock_class_key __key;    \

\

__init_waitqueue_head((q), &__key);    \

} while (0)

//使用completion

wait_for_completion(&us->scanning_done);

void __sched wait_for_completion(struct completion *x)

{

wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE, 0);

}

static long __sched wait_for_common(struct completion *x, long timeout, int state, int iowait)

{

might_sleep();

spin_lock_irq(&x->wait.lock);

timeout = do_wait_for_common(x, timeout, state, iowait);

spin_unlock_irq(&x->wait.lock);

return timeout;

}

static inline long __sched do_wait_for_common(struct completion *x, long timeout, int state, int iowait)

{

if (!x->done) {//判断done是否为0

DECLARE_WAITQUEUE(wait, current);

__add_wait_queue_tail_exclusive(&x->wait, &wait);

do {

if (signal_pending_state(state, current)) {

timeout = -ERESTARTSYS;

break;

}

__set_current_state(state);//设置当前进程的状态

spin_unlock_irq(&x->wait.lock);

if (iowait)

timeout = io_schedule_timeout(timeout);

else

timeout = schedule_timeout(timeout);//调度,进入睡眠

spin_lock_irq(&x->wait.lock);

} while (!x->done && timeout);//看条件是否满足或者超时?

__remove_wait_queue(&x->wait, &wait);//从等待节点从队列中移除

if (!x->done)//如果不是done引起的唤醒,则返回超时时间

return timeout;

}

x->done--;//重新置为0

return timeout ?: 1;

}

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

//加入队列尾部

static inline void __add_wait_queue_tail_exclusive(wait_queue_head_t *q,

wait_queue_t *wait)

{

wait->flags |= WQ_FLAG_EXCLUSIVE;

__add_wait_queue_tail(q, wait);

}

complete(&us->scanning_done);

void complete(struct completion *x)

{

unsigned long flags;

spin_lock_irqsave(&x->wait.lock, flags);

x->done++;//done++

__wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL);//唤醒等待队列

spin_unlock_irqrestore(&x->wait.lock, flags);

}

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) {

unsigned flags = curr->flags;

if (curr->func(curr, mode, wake_flags, key) &&

(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)

break;

}

}

int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,

void *key)

{

return try_to_wake_up(curr->private, mode, wake_flags);

}

阅读(2826) | 评论(0) | 转发(0) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值