Skip to content

Commit c56f97c

Browse files
committed
bitmap: generalize node_random()
Generalize node_random() and make it available to general bitmaps and cpumasks users. Notice, find_first_bit() is generally faster than find_nth_bit(), and we employ it when there's a single set bit in the bitmap. See commit 3e061d9 ("lib/nodemask: optimize node_random for nodemask with single NUMA node"). CC: Andrew Morton <[email protected]> Signed-off-by: "Yury Norov [NVIDIA]" <[email protected]>
1 parent 7339233 commit c56f97c

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

include/linux/find.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ unsigned long _find_next_bit_le(const unsigned long *addr, unsigned
4444
long size, unsigned long offset);
4545
#endif
4646

47+
unsigned long find_random_bit(const unsigned long *addr, unsigned long size);
48+
4749
#ifndef find_next_bit
4850
/**
4951
* find_next_bit - find the next set bit in a memory region

include/linux/nodemask.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -492,21 +492,9 @@ static __always_inline int num_node_state(enum node_states state)
492492
static __always_inline int node_random(const nodemask_t *maskp)
493493
{
494494
#if defined(CONFIG_NUMA) && (MAX_NUMNODES > 1)
495-
int w, bit;
496-
497-
w = nodes_weight(*maskp);
498-
switch (w) {
499-
case 0:
500-
bit = NUMA_NO_NODE;
501-
break;
502-
case 1:
503-
bit = first_node(*maskp);
504-
break;
505-
default:
506-
bit = find_nth_bit(maskp->bits, MAX_NUMNODES, get_random_u32_below(w));
507-
break;
508-
}
509-
return bit;
495+
int node = find_random_bit(maskp->bits, MAX_NUMNODES);
496+
497+
return node < MAX_NUMNODES ? node : NUMA_NO_NODE;
510498
#else
511499
return 0;
512500
#endif

lib/find_bit.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/math.h>
1919
#include <linux/minmax.h>
2020
#include <linux/swab.h>
21+
#include <linux/random.h>
2122

2223
/*
2324
* Common helper for find_bit() function family
@@ -291,3 +292,26 @@ EXPORT_SYMBOL(_find_next_bit_le);
291292
#endif
292293

293294
#endif /* __BIG_ENDIAN */
295+
296+
/**
297+
* find_random_bit - find a set bit at random position
298+
* @addr: The address to base the search on
299+
* @size: The bitmap size in bits
300+
*
301+
* Returns: a position of a random set bit; >= @size otherwise
302+
*/
303+
unsigned long find_random_bit(const unsigned long *addr, unsigned long size)
304+
{
305+
int w = bitmap_weight(addr, size);
306+
307+
switch (w) {
308+
case 0:
309+
return size;
310+
case 1:
311+
/* Performance trick for single-bit bitmaps */
312+
return find_first_bit(addr, size);
313+
default:
314+
return find_nth_bit(addr, size, get_random_u32_below(w));
315+
}
316+
}
317+
EXPORT_SYMBOL(find_random_bit);

0 commit comments

Comments
 (0)