typedef struct {
task_t *task;
- list_head_t task_list;
-} wait_queue_t;
+ list_head_t entry;
+} wait_queue_entry_t;
#define WAIT_QUEUE_HEAD_INITIALIZER(name) \
{ .task_list = LIST_HEAD_INIT((name).task_list) }
#define DECLARE_WAIT_QUEUE_HEAD(name) wait_queue_head_t name = WAIT_QUEUE_HEAD_INITIALIZER(name)
-#define WAIT_QUEUE_INITIALIZER(name, tsk) \
- { .task = tsk, .task_list = LIST_HEAD_INIT((name).task_list) }
+#define WAIT_QUEUE_ENTRY_INITIALIZER(name, tsk) \
+ { .task = tsk, .entry = LIST_HEAD_INIT((name).entry) }
-#define DECLARE_WAIT_QUEUE(name, tsk) wait_queue_t name = WAIT_QUEUE_INITIALIZER(name, tsk)
+#define DECLARE_WAIT_QUEUE_ENTRY(name, tsk) wait_queue_entry_t name = WAIT_QUEUE_ENTRY_INITIALIZER(name, tsk)
void init_wait_queue_head(wait_queue_head_t *wqh);
-void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq);
-void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq);
+void add_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wq);
+void del_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wq);
// prepare_to_wait 不会调用schedule
-void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state);
+void prepare_to_wait(wait_queue_head_t *head, wait_queue_entry_t *wq, unsigned int state);
-void __end_wait(wait_queue_t *wq);
+void __end_wait(wait_queue_entry_t *wq);
// 使用这个函数的时候需要注意
// 设置condition为真的语句和wake_up原子地执行
void wake_up(wait_queue_head_t *head);
void __wake_up(wait_queue_head_t *head, int nr);
+// 以下wait_event被定义成宏,而不是函数是因为condition
+// condition可能是一个表达式,如果定义成函数,往下传递就直接变成了一个值
+// 如果在某一步这个值变了,并不会反应在这些逻辑判断上
+
// 只要保证condition设置为真时,它是和wake_up一起原子执行的
// 那就能保证condition为真是如下__wait_event和wait_event里的if不出问题
// 也就是不会出现if-break后进程又再次因为其它原因阻塞后,又被wake_up的逻辑
// 设置为READY状态
#define __wait_event(head, condition) \
do { \
- DECLARE_WAIT_QUEUE(__wait, current); \
+ DECLARE_WAIT_QUEUE_ENTRY(__wait, current); \
while (1) { \
prepare_to_wait(head, &__wait, TASK_WAIT); \
if ((condition)) { \
volatile void init_wait_queue_head(wait_queue_head_t *wqh) { INIT_LIST_HEAD(&wqh->task_list); }
-volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state) {
+volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_entry_t *wqe, unsigned int state) {
unsigned long flags;
irq_save(flags);
- if (list_empty(&wq->task_list)) {
- list_add_tail(&wq->task_list, &head->task_list);
+ if (list_empty(&wqe->entry)) {
+ list_add_tail(&wqe->entry, &head->task_list);
}
set_current_state(state);
irq_restore(flags);
}
-volatile void __end_wait(wait_queue_t *wq) {
+volatile void __end_wait(wait_queue_entry_t *wqe) {
set_current_state(TASK_READY);
unsigned long flags;
irq_save(flags);
- list_del_init(&wq->task_list);
+ list_del_init(&wqe->entry);
irq_restore(flags);
}
-volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) {
+volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wqe) {
unsigned long flags;
irq_save(flags);
- list_add_tail(&wq->task_list, &head->task_list);
+ list_add_tail(&wqe->entry, &head->task_list);
irq_restore(flags);
}
-volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) {
+volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wqe) {
unsigned long flags;
irq_save(flags);
- list_del(&wq->task_list);
+ list_del(&wqe->entry);
irq_restore(flags);
}
volatile void __wake_up(wait_queue_head_t *head, int nr) {
unsigned long flags;
- wait_queue_t *p, *tmp;
+ wait_queue_entry_t *p, *tmp;
irq_save(flags);
- list_for_each_entry_safe(p, tmp, &head->task_list, task_list) {
+ list_for_each_entry_safe(p, tmp, &head->task_list, entry) {
p->task->state = TASK_READY;
current->reason = "wake_up";
volatile void wake_up(wait_queue_head_t *head) {
//
- __wake_up(head, 1);
+ __wake_up(head, 0); // wake up all
}
volatile void wait_on(wait_queue_head_t *head) {
- DECLARE_WAIT_QUEUE(wait, current);
+ DECLARE_WAIT_QUEUE_ENTRY(wait, current);
unsigned long flags;
irq_save(flags);
current->state = TASK_WAIT;
current->reason = "sleep_on";
- list_add_tail(&wait.task_list, &head->task_list);
+ list_add_tail(&wait.entry, &head->task_list);
irq_restore(flags);