sched/wait: Add a waitqueue helper for fully exclusive priority waiters
Add a waitqueue helper to add a priority waiter that requires exclusive wakeups, i.e. that requires that it be the _only_ priority waiter. The API will be used by KVM to ensure that at most one of KVM's irqfds is bound to a single eventfd (across the entire kernel). Open code the helper instead of using __add_wait_queue() so that the common path doesn't need to "handle" impossible failures. Cc: K Prateek Nayak <kprateek.nayak@amd.com> Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com> Tested-by: K Prateek Nayak <kprateek.nayak@amd.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20250522235223.3178519-9-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
@@ -164,6 +164,8 @@ static inline bool wq_has_sleeper(struct wait_queue_head *wq_head)
|
||||
extern void add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
|
||||
extern void add_wait_queue_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
|
||||
extern void add_wait_queue_priority(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
|
||||
extern int add_wait_queue_priority_exclusive(struct wait_queue_head *wq_head,
|
||||
struct wait_queue_entry *wq_entry);
|
||||
extern void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
|
||||
|
||||
static inline void __add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry)
|
||||
|
||||
@@ -47,6 +47,24 @@ void add_wait_queue_priority(struct wait_queue_head *wq_head, struct wait_queue_
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(add_wait_queue_priority);
|
||||
|
||||
int add_wait_queue_priority_exclusive(struct wait_queue_head *wq_head,
|
||||
struct wait_queue_entry *wq_entry)
|
||||
{
|
||||
struct list_head *head = &wq_head->head;
|
||||
|
||||
wq_entry->flags |= WQ_FLAG_EXCLUSIVE | WQ_FLAG_PRIORITY;
|
||||
|
||||
guard(spinlock_irqsave)(&wq_head->lock);
|
||||
|
||||
if (!list_empty(head) &&
|
||||
(list_first_entry(head, typeof(*wq_entry), entry)->flags & WQ_FLAG_PRIORITY))
|
||||
return -EBUSY;
|
||||
|
||||
list_add(&wq_entry->entry, head);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(add_wait_queue_priority_exclusive);
|
||||
|
||||
void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
Reference in New Issue
Block a user