1、等待队列头:wait_queue_head_t
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
》初始化等待队列头:
#define init_waitqueue_head(q) \
do { \
static struct lock_class_key __key; \
__init_waitqueue_head((q), &__key); \
} while (0)
》__init_waitqueue_head 实现:
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); /* 循环链表实现 */
}
2、等待队列容器:wait_queue_ttypedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
void *private;
wait_queue_func_t func;
struct list_head task_list;
};
typedef struct __wait_queue wait_queue_t;
》将当前进程current添加到等待队列容器中:
static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
{
q->flags = 0;
q->private = p; /* 当前进程PCB,赋值给等待队列容器的private */
q->func = default_wake_function;
}
3、将包装好的等待队列容器添加到等待队列头所在的链表中:add_wait_queue
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); /* list_add(&new->task_list, &head->task_list); */
spin_unlock_irqrestore (&q->lock, flags);
}
4、设置当前进程状态:set_current_state
#define TASK_RUNNING0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
5、将当前进程 current 添加到等待队列后,当前进程进入真正的睡眠,并开始调度任务:
schedule();
或 schedule_timeout(signed long timeout /* 5*HZ */);
6、改变当前任务状态并从等待队列中移除该进程:
set_current_state (TASK_RUNNING);
void remove_wait_queue (wait_queue_head_t *q/* 等待队列头 */,
wait_queue_t *wait /* 等待队列容器 */);
7、schedule() 返回后,判断返回条件:
1)schedule() 设备或者数据可读;
2)schedule_timeout() [a.设备或者数据可读][b.接收到中断信号][c.超时唤醒]