Skip to content

Commit 10834b7

Browse files
committed
sched: Add test_and_clear_wake_up_bit() and atomic_dec_and_wake_up()
JIRA: https://issues.redhat.com/browse/RHEL-117497 commit 52d633d Author: NeilBrown <neilb@suse.de> Date: Wed Sep 25 15:31:41 2024 +1000 sched: Add test_and_clear_wake_up_bit() and atomic_dec_and_wake_up() There are common patterns in the kernel of using test_and_clear_bit() before wake_up_bit(), and atomic_dec_and_test() before wake_up_var(). These combinations don't need extra barriers but sometimes include them unnecessarily. To help avoid the unnecessary barriers and to help discourage the general use of wake_up_bit/var (which is a fragile interface) introduce two combined functions which implement these patterns. Also add store_release_wake_up() which supports the task of simply setting a non-atomic variable and sending a wakeup. This pattern requires barriers which are often omitted. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20240925053405.3960701-5-neilb@suse.de Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
1 parent 00c0c59 commit 10834b7

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

include/linux/wait_bit.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,4 +418,64 @@ static inline void clear_and_wake_up_bit(int bit, unsigned long *word)
418418
wake_up_bit(word, bit);
419419
}
420420

421+
/**
422+
* test_and_clear_wake_up_bit - clear a bit if it was set: wake up anyone waiting on that bit
423+
* @bit: the bit of the word being waited on
424+
* @word: the address of memory containing that bit
425+
*
426+
* If the bit is set and can be atomically cleared, any tasks waiting in
427+
* wait_on_bit() or similar will be woken. This call has the same
428+
* complete ordering semantics as test_and_clear_bit(). Any changes to
429+
* memory made before this call are guaranteed to be visible after the
430+
* corresponding wait_on_bit() completes.
431+
*
432+
* Returns %true if the bit was successfully set and the wake up was sent.
433+
*/
434+
static inline bool test_and_clear_wake_up_bit(int bit, unsigned long *word)
435+
{
436+
if (!test_and_clear_bit(bit, word))
437+
return false;
438+
/* no extra barrier required */
439+
wake_up_bit(word, bit);
440+
return true;
441+
}
442+
443+
/**
444+
* atomic_dec_and_wake_up - decrement an atomic_t and if zero, wake up waiters
445+
* @var: the variable to dec and test
446+
*
447+
* Decrements the atomic variable and if it reaches zero, send a wake_up to any
448+
* processes waiting on the variable.
449+
*
450+
* This function has the same complete ordering semantics as atomic_dec_and_test.
451+
*
452+
* Returns %true is the variable reaches zero and the wake up was sent.
453+
*/
454+
455+
static inline bool atomic_dec_and_wake_up(atomic_t *var)
456+
{
457+
if (!atomic_dec_and_test(var))
458+
return false;
459+
/* No extra barrier required */
460+
wake_up_var(var);
461+
return true;
462+
}
463+
464+
/**
465+
* store_release_wake_up - update a variable and send a wake_up
466+
* @var: the address of the variable to be updated and woken
467+
* @val: the value to store in the variable.
468+
*
469+
* Store the given value in the variable send a wake up to any tasks
470+
* waiting on the variable. All necessary barriers are included to ensure
471+
* the task calling wait_var_event() sees the new value and all values
472+
* written to memory before this call.
473+
*/
474+
#define store_release_wake_up(var, val) \
475+
do { \
476+
smp_store_release(var, val); \
477+
smp_mb(); \
478+
wake_up_var(var); \
479+
} while (0)
480+
421481
#endif /* _LINUX_WAIT_BIT_H */

0 commit comments

Comments
 (0)