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

Reply via email to