Re: [PATCH 1/1] kernel/locking: Add mutual exclusion self-test
John Stultz <[email protected]>
| Newsgroups | org.kernel.vger.linux-kselftest,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CANDhNCoPDZeXXGn-hKZ_jgE8gkELEaufDXDYWV=hqLWxtD6gJg@mail.gmail.com> |
On Mon, Aug 17, 2026 at 6:03 AM Håkon Bugge <[email protected]> wrote: > diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile > index cee1901d4cff8..240084b4abbb7 100644 > --- a/kernel/locking/Makefile > +++ b/kernel/locking/Makefile > @@ -38,3 +38,4 @@ obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o > obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o > obj-$(CONFIG_WW_MUTEX_SELFTEST) += test-ww_mutex.o > obj-$(CONFIG_LOCK_EVENT_COUNTS) += lock_events.o > +obj-$(CONFIG_MX_TEST) += mx_test.o Total bikeshed item, but both CONFIG_MX_TEST and mx_test are not very obvious names for someone looking at this make file. > diff --git a/kernel/locking/mx_test.c b/kernel/locking/mx_test.c > new file mode 100644 > index 0000000000000..71d9ddc48a44b > --- /dev/null > +++ b/kernel/locking/mx_test.c ... > +static int __init mx_test_init(void) > +{ > + unsigned int threads = 4 * num_online_cpus(); > + enum mx_test test = MX_ILLEGAL; > + char *mnemonic; > + unsigned int i; > + unsigned int p; > + struct { > + enum mx_test test; > + char *mnemonic; > + } mx_test_types[] = { > + { > + .test = MX_BUSTED, > + .mnemonic = "busted", > + }, > + { > + .test = MX_SPIN_LOCK, > + .mnemonic = "spin_lock", > + }, > + { > + .test = MX_SPIN_LOCK_IRQ, > + .mnemonic = "spin_lock_irq", > + }, > + { > + .test = MX_SPIN_LOCK_IRQSAVE, > + .mnemonic = "spin_lock_irqsave", > + }, > + { > + .test = MX_RW_LOCK_W, > + .mnemonic = "write_lock", > + }, > + { > + .test = MX_RW_LOCK_W_BH, > + .mnemonic = "write_lock_bh", > + }, > + { > + .test = MX_RW_LOCK_TRW, > + .mnemonic = "read_trylock_write_lock", > + }, > + { > + .test = MX_RW_LOCK_TRW_BH, > + .mnemonic = "read_trylock_write_lock_bh", > + }, > + { > + .test = MX_MUTEX, > + .mnemonic = "mutex", > + }, > + { > + .test = MX_ATOMIC_ADD, > + .mnemonic = "atomic_add", > + }, > + { > + .test = MX_CMPXCHG, > + .mnemonic = "cmpxchg", > + }, > + { > + .test = MX_RDS_BUSTED, > + .mnemonic = "rds_busted", > + }, > + { > + .test = MX_TEST_AND_SET_BIT_LOCK, > + .mnemonic = "test_and_set_bit_lock", > + }, > + { > + .test = MX_TEST_AND_SET_BIT_INNOV, > + .mnemonic = "test_and_set_bit_innov", > + }, > + { > + .test = MX_TEST_AND_SET_BIT_PLAIN, > + .mnemonic = "test_and_set_bit_plain", > + }, > + { > + .test = MX_TEST_AND_CLEAR_BIT_INNOV, > + .mnemonic = "test_and_clear_bit_innov", > + }, > + { > + .test = MX_TEST_AND_CLEAR_BIT_PLAIN, > + .mnemonic = "test_and_clear_bit_plain", > + }, > + { > + .test = MX_SINGLE_WW_MUTEX_WW, > + .mnemonic = "single_ww_mutex_wound_wait", > + }, > + { > + .test = MX_SINGLE_WW_MUTEX_WD, > + .mnemonic = "single_ww_mutex_wait_die", > + }, > + }; > + > + /* Select the test type */ > + for (i = 0; i < ARRAY_SIZE(mx_test_types); ++i) > + if (!strcmp(mx_test, mx_test_types[i].mnemonic)) { > + test = mx_test_types[i].test; > + mnemonic = mx_test_types[i].mnemonic; > + break; > + } > + > + if (test == MX_ILLEGAL) { > + pr_err("mx_test: unknown test type %s\n", mx_test); > + pr_notice("mx_test: legitimate test types:\n"); > + for (i = 0; i < ARRAY_SIZE(mx_test_types); ++i) > + pr_notice("mx_test_types: %s\n", mx_test_types[i].mnemonic); > + return -ENOPROTOOPT; > + } > + > + if ((mx_min_padding % 8) || (mx_max_padding % 8)) { > + pr_err("mx_test: padding must be a multiple of 8 bytes\n"); > + return -EINVAL; > + } > + > + if (mx_min_padding > mx_max_padding) { > + pr_err("mx_test: mx_min_padding must be less than equal to mx_max_padding\n"); > + return -EINVAL; > + } > + > + if (mx_max_padding > L1_CACHE_BYTES) { > + pr_err("mx_test: mx_max_padding must be less than equal to L1_CACHE_BYTES (%d)\n", > + L1_CACHE_BYTES); > + return -EINVAL; > + } > + > + if (mx_nmbr_elems < 1) { > + pr_err("Number of elements must be greater than equal to one\n"); > + return -EINVAL; > + } > + > + if (mx_scnds_per_test > MAX_JIFFY_OFFSET / HZ) { > + pr_err("mx_scnds_per_test too large\n"); > + return -EINVAL; > + } > + > + for (p = mx_min_padding; p <= mx_max_padding; p += 8) { > + int sts = run_test(test, mnemonic, threads, p); > + > + if (sts) > + return sts; > + } > + > + return 0; > +} Apologies, I've not had a chance to apply and try this yet. So this looks like the test has to be run via module load? I almost never use modules in my test environment, so its often nice to allow it to be built in and be triggered/re-triggered without having to unload/reload (assuming this is not something like locktorture which never finishes - and if that is the case, it might be good to integrate into the locktorture framework instead of adding a new one). Maybe something to consider? thanks -john