diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h index 0dcc60e820de71cb21199bbbcf515aed2c1d7645..841585f6e5f28fb6fde79204732e23158e4b58b2 100644 --- a/include/linux/sbitmap.h +++ b/include/linux/sbitmap.h @@ -171,6 +171,8 @@ void sbitmap_resize(struct sbitmap *sb, unsigned int depth); * starting from the last allocated bit. This is less efficient * than the default behavior (false). * + * This operation provides acquire barrier semantics if it succeeds. + * * Return: Non-negative allocated bit number if successful, -1 otherwise. */ int sbitmap_get(struct sbitmap *sb, unsigned int alloc_hint, bool round_robin); @@ -300,6 +302,12 @@ static inline void sbitmap_clear_bit(struct sbitmap *sb, unsigned int bitnr) clear_bit(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); } +static inline void sbitmap_clear_bit_unlock(struct sbitmap *sb, + unsigned int bitnr) +{ + clear_bit_unlock(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); +} + static inline int sbitmap_test_bit(struct sbitmap *sb, unsigned int bitnr) { return test_bit(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 42b5ca0acf9344ab5c462237a5e2a1705c220063..e6a9c06ec70cb98eda9b893715fb3ca590b01c65 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -100,7 +100,7 @@ static int __sbitmap_get_word(unsigned long *word, unsigned long depth, return -1; } - if (!test_and_set_bit(nr, word)) + if (!test_and_set_bit_lock(nr, word)) break; hint = nr + 1; @@ -434,9 +434,9 @@ static void sbq_wake_up(struct sbitmap_queue *sbq) /* * Pairs with the memory barrier in set_current_state() to ensure the * proper ordering of clear_bit()/waitqueue_active() in the waker and - * test_and_set_bit()/prepare_to_wait()/finish_wait() in the waiter. See - * the comment on waitqueue_active(). This is __after_atomic because we - * just did clear_bit() in the caller. + * test_and_set_bit_lock()/prepare_to_wait()/finish_wait() in the + * waiter. See the comment on waitqueue_active(). This is __after_atomic + * because we just did clear_bit_unlock() in the caller. */ smp_mb__after_atomic(); @@ -469,7 +469,7 @@ static void sbq_wake_up(struct sbitmap_queue *sbq) void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr, unsigned int cpu) { - sbitmap_clear_bit(&sbq->sb, nr); + sbitmap_clear_bit_unlock(&sbq->sb, nr); sbq_wake_up(sbq); if (likely(!sbq->round_robin && nr < sbq->sb.depth)) *per_cpu_ptr(sbq->alloc_hint, cpu) = nr;