Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'bitmap-for-6.17' of https://github.com/norov/linux

Pull bitmap updates from Yury Norov:

- find_random_bit() series (Yury)

- GENMASK() consolidation (Vincent)

- random cleanups (Shaopeng, Ben, Yury)

* tag 'bitmap-for-6.17' of https://github.com/norov/linux:
bitfield: Ensure the return values of helper functions are checked
test_bits: add tests for __GENMASK() and __GENMASK_ULL()
bits: unify the non-asm GENMASK*()
bits: split the definition of the asm and non-asm GENMASK*()
cpumask: Remove unnecessary cpumask_nth_andnot()
watchdog: fix opencoded cpumask_next_wrap() in watchdog_next_cpu()
clocksource: Improve randomness in clocksource_verify_choose_cpus()
cpumask: introduce cpumask_random()
bitmap: generalize node_random()

+71 -92
+4 -4
include/linux/bitfield.h
··· 189 189 } 190 190 #define field_max(field) ((typeof(field))field_mask(field)) 191 191 #define ____MAKE_OP(type,base,to,from) \ 192 - static __always_inline __##type type##_encode_bits(base v, base field) \ 192 + static __always_inline __##type __must_check type##_encode_bits(base v, base field) \ 193 193 { \ 194 194 if (__builtin_constant_p(v) && (v & ~field_mask(field))) \ 195 195 __field_overflow(); \ 196 196 return to((v & field_mask(field)) * field_multiplier(field)); \ 197 197 } \ 198 - static __always_inline __##type type##_replace_bits(__##type old, \ 199 - base val, base field) \ 198 + static __always_inline __##type __must_check type##_replace_bits(__##type old, \ 199 + base val, base field) \ 200 200 { \ 201 201 return (old & ~to(field)) | type##_encode_bits(val, field); \ 202 202 } \ ··· 205 205 { \ 206 206 *p = (*p & ~to(field)) | type##_encode_bits(val, field); \ 207 207 } \ 208 - static __always_inline base type##_get_bits(__##type v, base field) \ 208 + static __always_inline base __must_check type##_get_bits(__##type v, base field) \ 209 209 { \ 210 210 return (from(v) & field)/field_multiplier(field); \ 211 211 }
+6 -23
include/linux/bits.h
··· 2 2 #ifndef __LINUX_BITS_H 3 3 #define __LINUX_BITS_H 4 4 5 - #include <linux/const.h> 6 5 #include <vdso/bits.h> 7 6 #include <uapi/linux/bits.h> 8 - #include <asm/bitsperlong.h> 9 7 10 8 #define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) 11 9 #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) ··· 48 50 (type_max(t) << (l) & \ 49 51 type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) 50 52 53 + #define GENMASK(h, l) GENMASK_TYPE(unsigned long, h, l) 54 + #define GENMASK_ULL(h, l) GENMASK_TYPE(unsigned long long, h, l) 55 + 51 56 #define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l) 52 57 #define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l) 53 58 #define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l) 54 59 #define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l) 60 + #define GENMASK_U128(h, l) GENMASK_TYPE(u128, h, l) 55 61 56 62 /* 57 63 * Fixed-type variants of BIT(), with additional checks like GENMASK_TYPE(). The ··· 81 79 * BUILD_BUG_ON_ZERO is not available in h files included from asm files, 82 80 * disable the input check if that is the case. 83 81 */ 84 - #define GENMASK_INPUT_CHECK(h, l) 0 82 + #define GENMASK(h, l) __GENMASK(h, l) 83 + #define GENMASK_ULL(h, l) __GENMASK_ULL(h, l) 85 84 86 85 #endif /* !defined(__ASSEMBLY__) */ 87 - 88 - #define GENMASK(h, l) \ 89 - (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) 90 - #define GENMASK_ULL(h, l) \ 91 - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l)) 92 - 93 - #if !defined(__ASSEMBLY__) 94 - /* 95 - * Missing asm support 96 - * 97 - * __GENMASK_U128() depends on _BIT128() which would not work 98 - * in the asm code, as it shifts an 'unsigned __int128' data 99 - * type instead of direct representation of 128 bit constants 100 - * such as long and unsigned long. The fundamental problem is 101 - * that a 128 bit constant will get silently truncated by the 102 - * gcc compiler. 103 - */ 104 - #define GENMASK_U128(h, l) \ 105 - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_U128(h, l)) 106 - #endif 107 86 108 87 #endif /* __LINUX_BITS_H */
+12 -16
include/linux/cpumask.h
··· 355 355 } 356 356 357 357 /** 358 + * cpumask_random - get random cpu in *src. 359 + * @src: cpumask pointer 360 + * 361 + * Return: random set bit, or >= nr_cpu_ids if @src is empty. 362 + */ 363 + static __always_inline 364 + unsigned int cpumask_random(const struct cpumask *src) 365 + { 366 + return find_random_bit(cpumask_bits(src), nr_cpu_ids); 367 + } 368 + 369 + /** 358 370 * for_each_cpu - iterate over every cpu in a mask 359 371 * @cpu: the (optionally unsigned) integer iterator 360 372 * @mask: the cpumask pointer ··· 555 543 const struct cpumask *srcp2) 556 544 { 557 545 return find_nth_and_bit(cpumask_bits(srcp1), cpumask_bits(srcp2), 558 - small_cpumask_bits, cpumask_check(cpu)); 559 - } 560 - 561 - /** 562 - * cpumask_nth_andnot - get the Nth cpu set in 1st cpumask, and clear in 2nd. 563 - * @srcp1: the cpumask pointer 564 - * @srcp2: the cpumask pointer 565 - * @cpu: the Nth cpu to find, starting from 0 566 - * 567 - * Return: >= nr_cpu_ids if such cpu doesn't exist. 568 - */ 569 - static __always_inline 570 - unsigned int cpumask_nth_andnot(unsigned int cpu, const struct cpumask *srcp1, 571 - const struct cpumask *srcp2) 572 - { 573 - return find_nth_andnot_bit(cpumask_bits(srcp1), cpumask_bits(srcp2), 574 546 small_cpumask_bits, cpumask_check(cpu)); 575 547 } 576 548
+2 -27
include/linux/find.h
··· 44 44 long size, unsigned long offset); 45 45 #endif 46 46 47 + unsigned long find_random_bit(const unsigned long *addr, unsigned long size); 48 + 47 49 #ifndef find_next_bit 48 50 /** 49 51 * find_next_bit - find the next set bit in a memory region ··· 267 265 } 268 266 269 267 return __find_nth_and_bit(addr1, addr2, size, n); 270 - } 271 - 272 - /** 273 - * find_nth_andnot_bit - find N'th set bit in 2 memory regions, 274 - * flipping bits in 2nd region 275 - * @addr1: The 1st address to start the search at 276 - * @addr2: The 2nd address to start the search at 277 - * @size: The maximum number of bits to search 278 - * @n: The number of set bit, which position is needed, counting from 0 279 - * 280 - * Returns the bit number of the N'th set bit. 281 - * If no such, returns @size. 282 - */ 283 - static __always_inline 284 - unsigned long find_nth_andnot_bit(const unsigned long *addr1, const unsigned long *addr2, 285 - unsigned long size, unsigned long n) 286 - { 287 - if (n >= size) 288 - return size; 289 - 290 - if (small_const_nbits(size)) { 291 - unsigned long val = *addr1 & (~*addr2) & GENMASK(size - 1, 0); 292 - 293 - return val ? fns(val, n) : size; 294 - } 295 - 296 - return __find_nth_andnot_bit(addr1, addr2, size, n); 297 268 } 298 269 299 270 /**
+2 -14
include/linux/nodemask.h
··· 492 492 static __always_inline int node_random(const nodemask_t *maskp) 493 493 { 494 494 #if defined(CONFIG_NUMA) && (MAX_NUMNODES > 1) 495 - int w, bit; 495 + int node = find_random_bit(maskp->bits, MAX_NUMNODES); 496 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; 497 + return node < MAX_NUMNODES ? node : NUMA_NO_NODE; 510 498 #else 511 499 return 0; 512 500 #endif
+1 -4
kernel/time/clocksource.c
··· 340 340 * CPUs that are currently online. 341 341 */ 342 342 for (i = 1; i < n; i++) { 343 - cpu = get_random_u32_below(nr_cpu_ids); 344 - cpu = cpumask_next(cpu - 1, cpu_online_mask); 345 - if (cpu >= nr_cpu_ids) 346 - cpu = cpumask_first(cpu_online_mask); 343 + cpu = cpumask_random(cpu_online_mask); 347 344 if (!WARN_ON_ONCE(cpu >= nr_cpu_ids)) 348 345 cpumask_set_cpu(cpu, &cpus_chosen); 349 346 }
+1 -4
kernel/watchdog_buddy.c
··· 12 12 { 13 13 unsigned int next_cpu; 14 14 15 - next_cpu = cpumask_next(cpu, &watchdog_cpus); 16 - if (next_cpu >= nr_cpu_ids) 17 - next_cpu = cpumask_first(&watchdog_cpus); 18 - 15 + next_cpu = cpumask_next_wrap(cpu, &watchdog_cpus); 19 16 if (next_cpu == cpu) 20 17 return nr_cpu_ids; 21 18
+24
lib/find_bit.c
··· 18 18 #include <linux/math.h> 19 19 #include <linux/minmax.h> 20 20 #include <linux/swab.h> 21 + #include <linux/random.h> 21 22 22 23 /* 23 24 * Common helper for find_bit() function family ··· 292 291 #endif 293 292 294 293 #endif /* __BIG_ENDIAN */ 294 + 295 + /** 296 + * find_random_bit - find a set bit at random position 297 + * @addr: The address to base the search on 298 + * @size: The bitmap size in bits 299 + * 300 + * Returns: a position of a random set bit; >= @size otherwise 301 + */ 302 + unsigned long find_random_bit(const unsigned long *addr, unsigned long size) 303 + { 304 + int w = bitmap_weight(addr, size); 305 + 306 + switch (w) { 307 + case 0: 308 + return size; 309 + case 1: 310 + /* Performance trick for single-bit bitmaps */ 311 + return find_first_bit(addr, size); 312 + default: 313 + return find_nth_bit(addr, size, get_random_u32_below(w)); 314 + } 315 + } 316 + EXPORT_SYMBOL(find_random_bit);
+19
lib/tests/test_bits.c
··· 26 26 static_assert(assert_type(u32, GENMASK_U32(31, 0)) == U32_MAX); 27 27 static_assert(assert_type(u64, GENMASK_U64(63, 0)) == U64_MAX); 28 28 29 + /* FIXME: add a test case written in asm for GENMASK() and GENMASK_ULL() */ 30 + 31 + static void __genmask_test(struct kunit *test) 32 + { 33 + KUNIT_EXPECT_EQ(test, 1ul, __GENMASK(0, 0)); 34 + KUNIT_EXPECT_EQ(test, 3ul, __GENMASK(1, 0)); 35 + KUNIT_EXPECT_EQ(test, 6ul, __GENMASK(2, 1)); 36 + KUNIT_EXPECT_EQ(test, 0xFFFFFFFFul, __GENMASK(31, 0)); 37 + } 38 + 39 + static void __genmask_ull_test(struct kunit *test) 40 + { 41 + KUNIT_EXPECT_EQ(test, 1ull, __GENMASK_ULL(0, 0)); 42 + KUNIT_EXPECT_EQ(test, 3ull, __GENMASK_ULL(1, 0)); 43 + KUNIT_EXPECT_EQ(test, 0x000000ffffe00000ull, __GENMASK_ULL(39, 21)); 44 + KUNIT_EXPECT_EQ(test, 0xffffffffffffffffull, __GENMASK_ULL(63, 0)); 45 + } 29 46 30 47 static void genmask_test(struct kunit *test) 31 48 { ··· 140 123 141 124 142 125 static struct kunit_case bits_test_cases[] = { 126 + KUNIT_CASE(__genmask_test), 127 + KUNIT_CASE(__genmask_ull_test), 143 128 KUNIT_CASE(genmask_test), 144 129 KUNIT_CASE(genmask_ull_test), 145 130 KUNIT_CASE(genmask_u128_test),