diff --git a/include/kernel/wait.h b/include/kernel/wait.h index 2903702..74b8fc6 100644 --- a/include/kernel/wait.h +++ b/include/kernel/wait.h @@ -40,6 +40,15 @@ extern void thread_wait_end_nosleep( struct waitqueue *q); extern void wait_on_queue(struct waitqueue *q); extern void wakeup_queue(struct waitqueue *q); +extern void wakeup_n(struct waitqueue *q, size_t n); extern void wakeup_one(struct waitqueue *q); +static inline bool waitqueue_empty(struct waitqueue *wq) +{ + unsigned long flags; + spin_lock_irqsave(&wq->wq_lock, &flags); + bool result = queue_empty(&wq->wq_waiters); + spin_unlock_irqrestore(&wq->wq_lock, flags); + return result; +} #endif diff --git a/sched/wait.c b/sched/wait.c index 0005bac..af025e8 100644 --- a/sched/wait.c +++ b/sched/wait.c @@ -69,6 +69,24 @@ void wakeup_queue(struct waitqueue *q) spin_unlock_irqrestore(&q->wq_lock, flags); } +void wakeup_n(struct waitqueue *q, size_t nr_waiters) +{ + unsigned long flags; + spin_lock_irqsave(&q->wq_lock, &flags); + struct queue_entry *ent = queue_pop_front(&q->wq_waiters); + while (ent && nr_waiters > 0) { + struct wait_item *waiter + = QUEUE_CONTAINER(struct wait_item, w_entry, ent); + struct thread *thr = waiter->w_thread; + thread_awaken(thr); + + ent = queue_pop_front(&q->wq_waiters); + nr_waiters--; + } + + spin_unlock_irqrestore(&q->wq_lock, flags); +} + void wakeup_one(struct waitqueue *q) { unsigned long flags;