#include #include #include void waitq_init(waitq_t *waitq) { spin_lock_init(&waitq->lock); list_head_init(&waitq->waitq); } void waitq_init_entry(waitq_entry_t *entry, struct task_struct *task) { entry->task = task; list_head_init(&entry->link); } bool waitq_active(waitq_t *waitq) { bool active; unsigned long irqstate; spin_lock_irqsave(&waitq->lock, irqstate); active = !list_empty(&waitq->waitq); spin_unlock_irqrestore(&waitq->lock, irqstate); return active; } void waitq_add_entry(waitq_t *waitq, waitq_entry_t *entry) { unsigned long irqstate; spin_lock_irqsave(&waitq->lock, irqstate); BUG_ON(!list_empty(&entry->link)); list_add(&entry->link, &waitq->waitq); spin_unlock_irqrestore(&waitq->lock, irqstate); } void waitq_remove_entry(waitq_t *waitq, waitq_entry_t *entry) { unsigned long irqstate; spin_lock_irqsave(&waitq->lock, irqstate); BUG_ON(list_empty(&entry->link)); list_del_init(&entry->link); spin_unlock_irqrestore(&waitq->lock, irqstate); } void waitq_prepare_to_wait(waitq_t *waitq, waitq_entry_t *entry, taskstate_t state) { unsigned long irqstate; spin_lock_irqsave(&waitq->lock, irqstate); if (list_empty(&entry->link)) list_add(&entry->link, &waitq->waitq); set_mb(entry->task->state, state); spin_unlock_irqrestore(&waitq->lock, irqstate); } void waitq_finish_wait(waitq_t *waitq, waitq_entry_t *entry) { set_mb(entry->task->state, TASKSTATE_READY); waitq_remove_entry(waitq, entry); } void waitq_wakeup(waitq_t *waitq) { unsigned long irqstate; struct list_head *tmp; waitq_entry_t *entry; spin_lock_irqsave(&waitq->lock, irqstate); list_for_each(tmp, &waitq->waitq) { entry = list_entry(tmp, waitq_entry_t, link); sched_wakeup_task( entry->task, (TASKSTATE_UNINTERRUPTIBLE | TASKSTATE_INTERRUPTIBLE) ); } spin_unlock_irqrestore(&waitq->lock, irqstate); }