Skip to content

Commit cfb186c

Browse files
committed
sched: Add wait/wake interface for variable updated under a lock.
JIRA: https://issues.redhat.com/browse/RHEL-117497 commit cc2e1c8 Author: NeilBrown <neilb@suse.de> Date: Wed Sep 25 15:31:42 2024 +1000 sched: Add wait/wake interface for variable updated under a lock. Sometimes we need to wait for a condition to be true which must be testing while holding a lock. Correspondingly the condition is made true while holding the lock and the wake up is sent under the lock. This patch provides wake and wait interfaces which can be used for this situation when the lock is a mutex or a spinlock, or any other lock for which there are foo_lock() and foo_unlock() functions. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20240925053405.3960701-6-neilb@suse.de Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
1 parent 10834b7 commit cfb186c

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

include/linux/wait_bit.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,112 @@ do { \
400400
__ret; \
401401
})
402402

403+
/**
404+
* wait_var_event_any_lock - wait for a variable to be updated under a lock
405+
* @var: the address of the variable being waited on
406+
* @condition: condition to wait for
407+
* @lock: the object that is locked to protect updates to the variable
408+
* @type: prefix on lock and unlock operations
409+
* @state: waiting state, %TASK_UNINTERRUPTIBLE etc.
410+
*
411+
* Wait for a condition which can only be reliably tested while holding
412+
* a lock. The variables assessed in the condition will normal be updated
413+
* under the same lock, and the wake up should be signalled with
414+
* wake_up_var_locked() under the same lock.
415+
*
416+
* This is similar to wait_var_event(), but assumes a lock is held
417+
* while calling this function and while updating the variable.
418+
*
419+
* This must be called while the given lock is held and the lock will be
420+
* dropped when schedule() is called to wait for a wake up, and will be
421+
* reclaimed before testing the condition again. The functions used to
422+
* unlock and lock the object are constructed by appending _unlock and _lock
423+
* to @type.
424+
*
425+
* Return %-ERESTARTSYS if a signal arrives which is allowed to interrupt
426+
* the wait according to @state.
427+
*/
428+
#define wait_var_event_any_lock(var, condition, lock, type, state) \
429+
({ \
430+
int __ret = 0; \
431+
if (!(condition)) \
432+
__ret = ___wait_var_event(var, condition, state, 0, 0, \
433+
type ## _unlock(lock); \
434+
schedule(); \
435+
type ## _lock(lock)); \
436+
__ret; \
437+
})
438+
439+
/**
440+
* wait_var_event_spinlock - wait for a variable to be updated under a spinlock
441+
* @var: the address of the variable being waited on
442+
* @condition: condition to wait for
443+
* @lock: the spinlock which protects updates to the variable
444+
*
445+
* Wait for a condition which can only be reliably tested while holding
446+
* a spinlock. The variables assessed in the condition will normal be updated
447+
* under the same spinlock, and the wake up should be signalled with
448+
* wake_up_var_locked() under the same spinlock.
449+
*
450+
* This is similar to wait_var_event(), but assumes a spinlock is held
451+
* while calling this function and while updating the variable.
452+
*
453+
* This must be called while the given lock is held and the lock will be
454+
* dropped when schedule() is called to wait for a wake up, and will be
455+
* reclaimed before testing the condition again.
456+
*/
457+
#define wait_var_event_spinlock(var, condition, lock) \
458+
wait_var_event_any_lock(var, condition, lock, spin, TASK_UNINTERRUPTIBLE)
459+
460+
/**
461+
* wait_var_event_mutex - wait for a variable to be updated under a mutex
462+
* @var: the address of the variable being waited on
463+
* @condition: condition to wait for
464+
* @mutex: the mutex which protects updates to the variable
465+
*
466+
* Wait for a condition which can only be reliably tested while holding
467+
* a mutex. The variables assessed in the condition will normal be
468+
* updated under the same mutex, and the wake up should be signalled
469+
* with wake_up_var_locked() under the same mutex.
470+
*
471+
* This is similar to wait_var_event(), but assumes a mutex is held
472+
* while calling this function and while updating the variable.
473+
*
474+
* This must be called while the given mutex is held and the mutex will be
475+
* dropped when schedule() is called to wait for a wake up, and will be
476+
* reclaimed before testing the condition again.
477+
*/
478+
#define wait_var_event_mutex(var, condition, lock) \
479+
wait_var_event_any_lock(var, condition, lock, mutex, TASK_UNINTERRUPTIBLE)
480+
481+
/**
482+
* wake_up_var_protected - wake up waiters for a variable asserting that it is safe
483+
* @var: the address of the variable being waited on
484+
* @cond: the condition which afirms this is safe
485+
*
486+
* When waking waiters which use wait_var_event_any_lock() the waker must be
487+
* holding the reelvant lock to avoid races. This version of wake_up_var()
488+
* asserts that the relevant lock is held and so no barrier is needed.
489+
* The @cond is only tested when CONFIG_LOCKDEP is enabled.
490+
*/
491+
#define wake_up_var_protected(var, cond) \
492+
do { \
493+
lockdep_assert(cond); \
494+
wake_up_var(var); \
495+
} while (0)
496+
497+
/**
498+
* wake_up_var_locked - wake up waiters for a variable while holding a spinlock or mutex
499+
* @var: the address of the variable being waited on
500+
* @lock: The spinlock or mutex what protects the variable
501+
*
502+
* Send a wake up for the given variable which should be waited for with
503+
* wait_var_event_spinlock() or wait_var_event_mutex(). Unlike wake_up_var(),
504+
* no extra barriers are needed as the locking provides sufficient sequencing.
505+
*/
506+
#define wake_up_var_locked(var, lock) \
507+
wake_up_var_protected(var, lockdep_is_held(lock))
508+
403509
/**
404510
* clear_and_wake_up_bit - clear a bit and wake up anyone waiting on that bit
405511
* @bit: the bit of the word being waited on

0 commit comments

Comments
 (0)