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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.