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

Configure Feed

Select the types of activity you want to include in your feed.

test-ww_mutex: Extend ww_mutex tests to test both classes of ww_mutexes

Currently the test-ww_mutex tool only utilizes the wait-die
class of ww_mutexes, and thus isn't very helpful in exercising
the wait-wound class of ww_mutexes.

So extend the test to exercise both classes of ww_mutexes for
all of the subtests.

Signed-off-by: John Stultz <jstultz@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251205013515.759030-2-jstultz@google.com

authored by

John Stultz and committed by
Peter Zijlstra
34d80c93 8f0b4cce

+92 -60
+92 -60
kernel/locking/test-ww_mutex.c
··· 13 13 #include <linux/slab.h> 14 14 #include <linux/ww_mutex.h> 15 15 16 - static DEFINE_WD_CLASS(ww_class); 16 + static DEFINE_WD_CLASS(wd_class); 17 + static DEFINE_WW_CLASS(ww_class); 17 18 struct workqueue_struct *wq; 18 19 19 20 #ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH ··· 55 54 ww_mutex_unlock(&mtx->mutex); 56 55 } 57 56 58 - static int __test_mutex(unsigned int flags) 57 + static int __test_mutex(struct ww_class *class, unsigned int flags) 59 58 { 60 59 #define TIMEOUT (HZ / 16) 61 60 struct test_mutex mtx; 62 61 struct ww_acquire_ctx ctx; 63 62 int ret; 64 63 65 - ww_mutex_init(&mtx.mutex, &ww_class); 64 + ww_mutex_init(&mtx.mutex, class); 66 65 if (flags & TEST_MTX_CTX) 67 - ww_acquire_init(&ctx, &ww_class); 66 + ww_acquire_init(&ctx, class); 68 67 69 68 INIT_WORK_ONSTACK(&mtx.work, test_mutex_work); 70 69 init_completion(&mtx.ready); ··· 107 106 #undef TIMEOUT 108 107 } 109 108 110 - static int test_mutex(void) 109 + static int test_mutex(struct ww_class *class) 111 110 { 112 111 int ret; 113 112 int i; 114 113 115 114 for (i = 0; i < __TEST_MTX_LAST; i++) { 116 - ret = __test_mutex(i); 115 + ret = __test_mutex(class, i); 117 116 if (ret) 118 117 return ret; 119 118 } ··· 121 120 return 0; 122 121 } 123 122 124 - static int test_aa(bool trylock) 123 + static int test_aa(struct ww_class *class, bool trylock) 125 124 { 126 125 struct ww_mutex mutex; 127 126 struct ww_acquire_ctx ctx; 128 127 int ret; 129 128 const char *from = trylock ? "trylock" : "lock"; 130 129 131 - ww_mutex_init(&mutex, &ww_class); 132 - ww_acquire_init(&ctx, &ww_class); 130 + ww_mutex_init(&mutex, class); 131 + ww_acquire_init(&ctx, class); 133 132 134 133 if (!trylock) { 135 134 ret = ww_mutex_lock(&mutex, &ctx); ··· 178 177 179 178 struct test_abba { 180 179 struct work_struct work; 180 + struct ww_class *class; 181 181 struct ww_mutex a_mutex; 182 182 struct ww_mutex b_mutex; 183 183 struct completion a_ready; ··· 193 191 struct ww_acquire_ctx ctx; 194 192 int err; 195 193 196 - ww_acquire_init_noinject(&ctx, &ww_class); 194 + ww_acquire_init_noinject(&ctx, abba->class); 197 195 if (!abba->trylock) 198 196 ww_mutex_lock(&abba->b_mutex, &ctx); 199 197 else ··· 219 217 abba->result = err; 220 218 } 221 219 222 - static int test_abba(bool trylock, bool resolve) 220 + static int test_abba(struct ww_class *class, bool trylock, bool resolve) 223 221 { 224 222 struct test_abba abba; 225 223 struct ww_acquire_ctx ctx; 226 224 int err, ret; 227 225 228 - ww_mutex_init(&abba.a_mutex, &ww_class); 229 - ww_mutex_init(&abba.b_mutex, &ww_class); 226 + ww_mutex_init(&abba.a_mutex, class); 227 + ww_mutex_init(&abba.b_mutex, class); 230 228 INIT_WORK_ONSTACK(&abba.work, test_abba_work); 231 229 init_completion(&abba.a_ready); 232 230 init_completion(&abba.b_ready); 231 + abba.class = class; 233 232 abba.trylock = trylock; 234 233 abba.resolve = resolve; 235 234 236 235 schedule_work(&abba.work); 237 236 238 - ww_acquire_init_noinject(&ctx, &ww_class); 237 + ww_acquire_init_noinject(&ctx, class); 239 238 if (!trylock) 240 239 ww_mutex_lock(&abba.a_mutex, &ctx); 241 240 else ··· 281 278 282 279 struct test_cycle { 283 280 struct work_struct work; 281 + struct ww_class *class; 284 282 struct ww_mutex a_mutex; 285 283 struct ww_mutex *b_mutex; 286 284 struct completion *a_signal; ··· 295 291 struct ww_acquire_ctx ctx; 296 292 int err, erra = 0; 297 293 298 - ww_acquire_init_noinject(&ctx, &ww_class); 294 + ww_acquire_init_noinject(&ctx, cycle->class); 299 295 ww_mutex_lock(&cycle->a_mutex, &ctx); 300 296 301 297 complete(cycle->a_signal); ··· 318 314 cycle->result = err ?: erra; 319 315 } 320 316 321 - static int __test_cycle(unsigned int nthreads) 317 + static int __test_cycle(struct ww_class *class, unsigned int nthreads) 322 318 { 323 319 struct test_cycle *cycles; 324 320 unsigned int n, last = nthreads - 1; ··· 331 327 for (n = 0; n < nthreads; n++) { 332 328 struct test_cycle *cycle = &cycles[n]; 333 329 334 - ww_mutex_init(&cycle->a_mutex, &ww_class); 330 + cycle->class = class; 331 + ww_mutex_init(&cycle->a_mutex, class); 335 332 if (n == last) 336 333 cycle->b_mutex = &cycles[0].a_mutex; 337 334 else ··· 372 367 return ret; 373 368 } 374 369 375 - static int test_cycle(unsigned int ncpus) 370 + static int test_cycle(struct ww_class *class, unsigned int ncpus) 376 371 { 377 372 unsigned int n; 378 373 int ret; 379 374 380 375 for (n = 2; n <= ncpus + 1; n++) { 381 - ret = __test_cycle(n); 376 + ret = __test_cycle(class, n); 382 377 if (ret) 383 378 return ret; 384 379 } ··· 389 384 struct stress { 390 385 struct work_struct work; 391 386 struct ww_mutex *locks; 387 + struct ww_class *class; 392 388 unsigned long timeout; 393 389 int nlocks; 394 390 }; ··· 449 443 int contended = -1; 450 444 int n, err; 451 445 452 - ww_acquire_init(&ctx, &ww_class); 446 + ww_acquire_init(&ctx, stress->class); 453 447 retry: 454 448 err = 0; 455 449 for (n = 0; n < nlocks; n++) { ··· 517 511 order = NULL; 518 512 519 513 do { 520 - ww_acquire_init(&ctx, &ww_class); 514 + ww_acquire_init(&ctx, stress->class); 521 515 522 516 list_for_each_entry(ll, &locks, link) { 523 517 err = ww_mutex_lock(ll->lock, &ctx); ··· 576 570 #define STRESS_ONE BIT(2) 577 571 #define STRESS_ALL (STRESS_INORDER | STRESS_REORDER | STRESS_ONE) 578 572 579 - static int stress(int nlocks, int nthreads, unsigned int flags) 573 + static int stress(struct ww_class *class, int nlocks, int nthreads, unsigned int flags) 580 574 { 581 575 struct ww_mutex *locks; 582 576 struct stress *stress_array; ··· 594 588 } 595 589 596 590 for (n = 0; n < nlocks; n++) 597 - ww_mutex_init(&locks[n], &ww_class); 591 + ww_mutex_init(&locks[n], class); 598 592 599 593 count = 0; 600 594 for (n = 0; nthreads; n++) { ··· 623 617 stress = &stress_array[count++]; 624 618 625 619 INIT_WORK(&stress->work, fn); 620 + stress->class = class; 626 621 stress->locks = locks; 627 622 stress->nlocks = nlocks; 628 623 stress->timeout = jiffies + 2*HZ; ··· 642 635 return 0; 643 636 } 644 637 645 - static int __init test_ww_mutex_init(void) 638 + static int __init run_tests(struct ww_class *class) 646 639 { 647 640 int ncpus = num_online_cpus(); 648 641 int ret, i; 649 642 650 - printk(KERN_INFO "Beginning ww mutex selftests\n"); 643 + ret = test_mutex(class); 644 + if (ret) 645 + return ret; 646 + 647 + ret = test_aa(class, false); 648 + if (ret) 649 + return ret; 650 + 651 + ret = test_aa(class, true); 652 + if (ret) 653 + return ret; 654 + 655 + for (i = 0; i < 4; i++) { 656 + ret = test_abba(class, i & 1, i & 2); 657 + if (ret) 658 + return ret; 659 + } 660 + 661 + ret = test_cycle(class, ncpus); 662 + if (ret) 663 + return ret; 664 + 665 + ret = stress(class, 16, 2 * ncpus, STRESS_INORDER); 666 + if (ret) 667 + return ret; 668 + 669 + ret = stress(class, 16, 2 * ncpus, STRESS_REORDER); 670 + if (ret) 671 + return ret; 672 + 673 + ret = stress(class, 2046, hweight32(STRESS_ALL) * ncpus, STRESS_ALL); 674 + if (ret) 675 + return ret; 676 + 677 + return 0; 678 + } 679 + 680 + static int __init run_test_classes(void) 681 + { 682 + int ret; 683 + 684 + pr_info("Beginning ww (wound) mutex selftests\n"); 685 + 686 + ret = run_tests(&ww_class); 687 + if (ret) 688 + return ret; 689 + 690 + pr_info("Beginning ww (die) mutex selftests\n"); 691 + ret = run_tests(&wd_class); 692 + if (ret) 693 + return ret; 694 + 695 + pr_info("All ww mutex selftests passed\n"); 696 + return 0; 697 + } 698 + 699 + static int __init test_ww_mutex_init(void) 700 + { 701 + int ret; 651 702 652 703 prandom_seed_state(&rng, get_random_u64()); 653 704 ··· 713 648 if (!wq) 714 649 return -ENOMEM; 715 650 716 - ret = test_mutex(); 717 - if (ret) 718 - return ret; 651 + ret = run_test_classes(); 719 652 720 - ret = test_aa(false); 721 - if (ret) 722 - return ret; 723 - 724 - ret = test_aa(true); 725 - if (ret) 726 - return ret; 727 - 728 - for (i = 0; i < 4; i++) { 729 - ret = test_abba(i & 1, i & 2); 730 - if (ret) 731 - return ret; 732 - } 733 - 734 - ret = test_cycle(ncpus); 735 - if (ret) 736 - return ret; 737 - 738 - ret = stress(16, 2*ncpus, STRESS_INORDER); 739 - if (ret) 740 - return ret; 741 - 742 - ret = stress(16, 2*ncpus, STRESS_REORDER); 743 - if (ret) 744 - return ret; 745 - 746 - ret = stress(2046, hweight32(STRESS_ALL)*ncpus, STRESS_ALL); 747 - if (ret) 748 - return ret; 749 - 750 - printk(KERN_INFO "All ww mutex selftests passed\n"); 751 - return 0; 653 + return ret; 752 654 } 753 655 754 656 static void __exit test_ww_mutex_exit(void)