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

bitmap: Switch from inline to __always_inline

'inline' keyword is only a recommendation for compiler. If it decides to
not inline bitmap functions, the whole small_const_nbits() machinery
doesn't work.

This is how a standard GCC 11.3.0 does for my x86_64 build now. This patch
replaces 'inline' directive with unconditional '__always_inline' to make
sure that there's always a chance for compile-time optimization. It doesn't
change size of kernel image, according to bloat-o-meter.

[[ Brian: split out from:
Subject: [PATCH 1/3] bitmap: switch from inline to __always_inline
https://lore.kernel.org/all/20221027043810.350460-2-yury.norov@gmail.com/
But rewritten, as there were too many conflicts. ]]

Co-developed-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Kees Cook <kees@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Yury Norov <yury.norov@gmail.com>

+76 -64
+76 -64
include/linux/bitmap.h
··· 203 203 * the bit offset of all zero areas this function finds is multiples of that 204 204 * power of 2. A @align_mask of 0 means no alignment is required. 205 205 */ 206 - static inline unsigned long 207 - bitmap_find_next_zero_area(unsigned long *map, 208 - unsigned long size, 209 - unsigned long start, 210 - unsigned int nr, 211 - unsigned long align_mask) 206 + static __always_inline 207 + unsigned long bitmap_find_next_zero_area(unsigned long *map, 208 + unsigned long size, 209 + unsigned long start, 210 + unsigned int nr, 211 + unsigned long align_mask) 212 212 { 213 213 return bitmap_find_next_zero_area_off(map, size, start, nr, 214 214 align_mask, 0); ··· 228 228 229 229 #define bitmap_size(nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE) 230 230 231 - static inline void bitmap_zero(unsigned long *dst, unsigned int nbits) 231 + static __always_inline void bitmap_zero(unsigned long *dst, unsigned int nbits) 232 232 { 233 233 unsigned int len = bitmap_size(nbits); 234 234 ··· 238 238 memset(dst, 0, len); 239 239 } 240 240 241 - static inline void bitmap_fill(unsigned long *dst, unsigned int nbits) 241 + static __always_inline void bitmap_fill(unsigned long *dst, unsigned int nbits) 242 242 { 243 243 unsigned int len = bitmap_size(nbits); 244 244 ··· 248 248 memset(dst, 0xff, len); 249 249 } 250 250 251 - static inline void bitmap_copy(unsigned long *dst, const unsigned long *src, 252 - unsigned int nbits) 251 + static __always_inline 252 + void bitmap_copy(unsigned long *dst, const unsigned long *src, unsigned int nbits) 253 253 { 254 254 unsigned int len = bitmap_size(nbits); 255 255 ··· 262 262 /* 263 263 * Copy bitmap and clear tail bits in last word. 264 264 */ 265 - static inline void bitmap_copy_clear_tail(unsigned long *dst, 266 - const unsigned long *src, unsigned int nbits) 265 + static __always_inline 266 + void bitmap_copy_clear_tail(unsigned long *dst, const unsigned long *src, unsigned int nbits) 267 267 { 268 268 bitmap_copy(dst, src, nbits); 269 269 if (nbits % BITS_PER_LONG) ··· 306 306 bitmap_copy_clear_tail((unsigned long *)(buf), (const unsigned long *)(bitmap), (nbits)) 307 307 #endif 308 308 309 - static inline bool bitmap_and(unsigned long *dst, const unsigned long *src1, 310 - const unsigned long *src2, unsigned int nbits) 309 + static __always_inline 310 + bool bitmap_and(unsigned long *dst, const unsigned long *src1, 311 + const unsigned long *src2, unsigned int nbits) 311 312 { 312 313 if (small_const_nbits(nbits)) 313 314 return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0; 314 315 return __bitmap_and(dst, src1, src2, nbits); 315 316 } 316 317 317 - static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, 318 - const unsigned long *src2, unsigned int nbits) 318 + static __always_inline 319 + void bitmap_or(unsigned long *dst, const unsigned long *src1, 320 + const unsigned long *src2, unsigned int nbits) 319 321 { 320 322 if (small_const_nbits(nbits)) 321 323 *dst = *src1 | *src2; ··· 325 323 __bitmap_or(dst, src1, src2, nbits); 326 324 } 327 325 328 - static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1, 329 - const unsigned long *src2, unsigned int nbits) 326 + static __always_inline 327 + void bitmap_xor(unsigned long *dst, const unsigned long *src1, 328 + const unsigned long *src2, unsigned int nbits) 330 329 { 331 330 if (small_const_nbits(nbits)) 332 331 *dst = *src1 ^ *src2; ··· 335 332 __bitmap_xor(dst, src1, src2, nbits); 336 333 } 337 334 338 - static inline bool bitmap_andnot(unsigned long *dst, const unsigned long *src1, 339 - const unsigned long *src2, unsigned int nbits) 335 + static __always_inline 336 + bool bitmap_andnot(unsigned long *dst, const unsigned long *src1, 337 + const unsigned long *src2, unsigned int nbits) 340 338 { 341 339 if (small_const_nbits(nbits)) 342 340 return (*dst = *src1 & ~(*src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0; 343 341 return __bitmap_andnot(dst, src1, src2, nbits); 344 342 } 345 343 346 - static inline void bitmap_complement(unsigned long *dst, const unsigned long *src, 347 - unsigned int nbits) 344 + static __always_inline 345 + void bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int nbits) 348 346 { 349 347 if (small_const_nbits(nbits)) 350 348 *dst = ~(*src); ··· 360 356 #endif 361 357 #define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1) 362 358 363 - static inline bool bitmap_equal(const unsigned long *src1, 364 - const unsigned long *src2, unsigned int nbits) 359 + static __always_inline 360 + bool bitmap_equal(const unsigned long *src1, const unsigned long *src2, unsigned int nbits) 365 361 { 366 362 if (small_const_nbits(nbits)) 367 363 return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); ··· 380 376 * 381 377 * Returns: True if (*@src1 | *@src2) == *@src3, false otherwise 382 378 */ 383 - static inline bool bitmap_or_equal(const unsigned long *src1, 384 - const unsigned long *src2, 385 - const unsigned long *src3, 386 - unsigned int nbits) 379 + static __always_inline 380 + bool bitmap_or_equal(const unsigned long *src1, const unsigned long *src2, 381 + const unsigned long *src3, unsigned int nbits) 387 382 { 388 383 if (!small_const_nbits(nbits)) 389 384 return __bitmap_or_equal(src1, src2, src3, nbits); ··· 390 387 return !(((*src1 | *src2) ^ *src3) & BITMAP_LAST_WORD_MASK(nbits)); 391 388 } 392 389 393 - static inline bool bitmap_intersects(const unsigned long *src1, 394 - const unsigned long *src2, 395 - unsigned int nbits) 390 + static __always_inline 391 + bool bitmap_intersects(const unsigned long *src1, const unsigned long *src2, unsigned int nbits) 396 392 { 397 393 if (small_const_nbits(nbits)) 398 394 return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0; ··· 399 397 return __bitmap_intersects(src1, src2, nbits); 400 398 } 401 399 402 - static inline bool bitmap_subset(const unsigned long *src1, 403 - const unsigned long *src2, unsigned int nbits) 400 + static __always_inline 401 + bool bitmap_subset(const unsigned long *src1, const unsigned long *src2, unsigned int nbits) 404 402 { 405 403 if (small_const_nbits(nbits)) 406 404 return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits)); ··· 408 406 return __bitmap_subset(src1, src2, nbits); 409 407 } 410 408 411 - static inline bool bitmap_empty(const unsigned long *src, unsigned nbits) 409 + static __always_inline 410 + bool bitmap_empty(const unsigned long *src, unsigned nbits) 412 411 { 413 412 if (small_const_nbits(nbits)) 414 413 return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); ··· 417 414 return find_first_bit(src, nbits) == nbits; 418 415 } 419 416 420 - static inline bool bitmap_full(const unsigned long *src, unsigned int nbits) 417 + static __always_inline 418 + bool bitmap_full(const unsigned long *src, unsigned int nbits) 421 419 { 422 420 if (small_const_nbits(nbits)) 423 421 return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); ··· 452 448 return __bitmap_weight_andnot(src1, src2, nbits); 453 449 } 454 450 455 - static __always_inline void bitmap_set(unsigned long *map, unsigned int start, 456 - unsigned int nbits) 451 + static __always_inline 452 + void bitmap_set(unsigned long *map, unsigned int start, unsigned int nbits) 457 453 { 458 454 if (__builtin_constant_p(nbits) && nbits == 1) 459 455 __set_bit(start, map); ··· 468 464 __bitmap_set(map, start, nbits); 469 465 } 470 466 471 - static __always_inline void bitmap_clear(unsigned long *map, unsigned int start, 472 - unsigned int nbits) 467 + static __always_inline 468 + void bitmap_clear(unsigned long *map, unsigned int start, unsigned int nbits) 473 469 { 474 470 if (__builtin_constant_p(nbits) && nbits == 1) 475 471 __clear_bit(start, map); ··· 484 480 __bitmap_clear(map, start, nbits); 485 481 } 486 482 487 - static inline void bitmap_shift_right(unsigned long *dst, const unsigned long *src, 488 - unsigned int shift, unsigned int nbits) 483 + static __always_inline 484 + void bitmap_shift_right(unsigned long *dst, const unsigned long *src, 485 + unsigned int shift, unsigned int nbits) 489 486 { 490 487 if (small_const_nbits(nbits)) 491 488 *dst = (*src & BITMAP_LAST_WORD_MASK(nbits)) >> shift; ··· 494 489 __bitmap_shift_right(dst, src, shift, nbits); 495 490 } 496 491 497 - static inline void bitmap_shift_left(unsigned long *dst, const unsigned long *src, 498 - unsigned int shift, unsigned int nbits) 492 + static __always_inline 493 + void bitmap_shift_left(unsigned long *dst, const unsigned long *src, 494 + unsigned int shift, unsigned int nbits) 499 495 { 500 496 if (small_const_nbits(nbits)) 501 497 *dst = (*src << shift) & BITMAP_LAST_WORD_MASK(nbits); ··· 504 498 __bitmap_shift_left(dst, src, shift, nbits); 505 499 } 506 500 507 - static inline void bitmap_replace(unsigned long *dst, 508 - const unsigned long *old, 509 - const unsigned long *new, 510 - const unsigned long *mask, 511 - unsigned int nbits) 501 + static __always_inline 502 + void bitmap_replace(unsigned long *dst, 503 + const unsigned long *old, 504 + const unsigned long *new, 505 + const unsigned long *mask, 506 + unsigned int nbits) 512 507 { 513 508 if (small_const_nbits(nbits)) 514 509 *dst = (*old & ~(*mask)) | (*new & *mask); ··· 552 545 * bitmap_gather() can be seen as the 'reverse' bitmap_scatter() operation. 553 546 * See bitmap_scatter() for details related to this relationship. 554 547 */ 555 - static inline void bitmap_scatter(unsigned long *dst, const unsigned long *src, 556 - const unsigned long *mask, unsigned int nbits) 548 + static __always_inline 549 + void bitmap_scatter(unsigned long *dst, const unsigned long *src, 550 + const unsigned long *mask, unsigned int nbits) 557 551 { 558 552 unsigned int n = 0; 559 553 unsigned int bit; ··· 607 599 * bitmap_scatter(res, src, mask, n) and a call to 608 600 * bitmap_scatter(res, result, mask, n) will lead to the same res value. 609 601 */ 610 - static inline void bitmap_gather(unsigned long *dst, const unsigned long *src, 611 - const unsigned long *mask, unsigned int nbits) 602 + static __always_inline 603 + void bitmap_gather(unsigned long *dst, const unsigned long *src, 604 + const unsigned long *mask, unsigned int nbits) 612 605 { 613 606 unsigned int n = 0; 614 607 unsigned int bit; ··· 620 611 __assign_bit(n++, dst, test_bit(bit, src)); 621 612 } 622 613 623 - static inline void bitmap_next_set_region(unsigned long *bitmap, 624 - unsigned int *rs, unsigned int *re, 625 - unsigned int end) 614 + static __always_inline 615 + void bitmap_next_set_region(unsigned long *bitmap, unsigned int *rs, 616 + unsigned int *re, unsigned int end) 626 617 { 627 618 *rs = find_next_bit(bitmap, end, *rs); 628 619 *re = find_next_zero_bit(bitmap, end, *rs + 1); ··· 637 628 * This is the complement to __bitmap_find_free_region() and releases 638 629 * the found region (by clearing it in the bitmap). 639 630 */ 640 - static inline void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order) 631 + static __always_inline 632 + void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order) 641 633 { 642 634 bitmap_clear(bitmap, pos, BIT(order)); 643 635 } ··· 654 644 * Returns: 0 on success, or %-EBUSY if specified region wasn't 655 645 * free (not all bits were zero). 656 646 */ 657 - static inline int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order) 647 + static __always_inline 648 + int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order) 658 649 { 659 650 unsigned int len = BIT(order); 660 651 ··· 679 668 * Returns: the bit offset in bitmap of the allocated region, 680 669 * or -errno on failure. 681 670 */ 682 - static inline int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order) 671 + static __always_inline 672 + int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order) 683 673 { 684 674 unsigned int pos, end; /* scans bitmap by regions of size order */ 685 675 ··· 734 722 * That is ``(u32 *)(&val)[0]`` gets the upper 32 bits, 735 723 * but we expect the lower 32-bits of u64. 736 724 */ 737 - static inline void bitmap_from_u64(unsigned long *dst, u64 mask) 725 + static __always_inline void bitmap_from_u64(unsigned long *dst, u64 mask) 738 726 { 739 727 bitmap_from_arr64(dst, &mask, 64); 740 728 } ··· 749 737 * @map memory region. For @nbits = 0 and @nbits > BITS_PER_LONG the return 750 738 * value is undefined. 751 739 */ 752 - static inline unsigned long bitmap_read(const unsigned long *map, 753 - unsigned long start, 754 - unsigned long nbits) 740 + static __always_inline 741 + unsigned long bitmap_read(const unsigned long *map, unsigned long start, unsigned long nbits) 755 742 { 756 743 size_t index = BIT_WORD(start); 757 744 unsigned long offset = start % BITS_PER_LONG; ··· 783 772 * 784 773 * For @nbits == 0 and @nbits > BITS_PER_LONG no writes are performed. 785 774 */ 786 - static inline void bitmap_write(unsigned long *map, unsigned long value, 787 - unsigned long start, unsigned long nbits) 775 + static __always_inline 776 + void bitmap_write(unsigned long *map, unsigned long value, 777 + unsigned long start, unsigned long nbits) 788 778 { 789 779 size_t index; 790 780 unsigned long offset;