[PATCH v2] Add threaded variants of single-threaded malloc tests

Florian Weimer fweimer@redhat.com
Tue Nov 11 11:32:01 GMT 2025


* Arjun Shankar:

> +# tests-threaded-{main,worker} are variants of base malloc tests that are
> +# run in a multi-threaded program.  The main variant is run in the main
> +# thread while an alternate thread exists, and the worker variant is run in
> +# a worker thread while the main thread waits on it.
> +
> +tests-exclude-threaded = \
> +  $(tests-link-with-libpthread) \
> +  $(tests-static) \
> +  tst-compathooks-off \
> +  tst-compathooks-on \
> +  tst-interpose-nothread \
> +  tst-malloc-usable \
> +  tst-malloc-usable-tunables \
> +  tst-mallocstate \
> +  tst-memalign-2 \
> +  tst-mxfast \
> +  tst-safe-linking \
> +# tests-exclude-threaded

Please add comments why these tests are excluded.

> +
> +tests-threaded-main = $(addsuffix -threaded-main, \
> +				  $(filter-out $(tests-exclude-threaded), \
> +					       $(tests)))
> +$(addprefix $(objpfx), $(tests-threaded-main)): $(shared-thread-library)
> +$(addprefix $(objpfx), $(tests-threaded-main:%=%-malloc-check)): $(shared-thread-library)
> +$(addprefix $(objpfx), $(tests-threaded-main:%=%-malloc-hugetlb1)): $(shared-thread-library)
> +$(addprefix $(objpfx), $(tests-threaded-main:%=%-malloc-hugetlb2)): $(shared-thread-library)
> +$(addprefix $(objpfx), $(tests-threaded-main:%=%-mcheck)): $(shared-thread-library)
> +$(addprefix $(objpfx), $(tests-threaded-main:%=%-malloc-largetcache)): $(shared-thread-library)

I think it would be sufficient to add the two threading tests in
parallel to -check, -hugetlb1, etc.  So two more test variants instead
of tripling the number of tests.

> +tests-threaded-worker = $(addsuffix -threaded-worker, \
> +				    $(filter-out $(tests-exclude-threaded) \
> +						 tst-free-errno \
> +						 tst-mallocfork, \
> +						 $(tests)))

Likewise why are tst-free-errno, tst-mallocfork excluded?

> diff --git a/support/Makefile b/support/Makefile
> index 2043e4e590..a7b1b39782 100644
> --- a/support/Makefile
> +++ b/support/Makefile
> @@ -98,6 +98,7 @@ libsupport-routines = \
>    support_test_compare_failure \
>    support_test_compare_string \
>    support_test_compare_string_wide \
> +  support_test_in_thread_wrapper \
>    support_test_main \
>    support_test_verify_impl \
>    support_wait_for_thread_exit \

I think the support changes should be in a separate patch.

> diff --git a/support/support_test_in_thread_wrapper.c b/support/support_test_in_thread_wrapper.c
> new file mode 100644
> index 0000000000..a4d5df0c12
> --- /dev/null
> +++ b/support/support_test_in_thread_wrapper.c
> @@ -0,0 +1,90 @@
> +/* Test-in-thread wrapper function for the test driver.
> +   Copyright (C) 2025 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */

Please add a comment here explaining the need for separate compilation
(both for Hurd and for static linking).

> +pthread_barrier_t barrier;

This needs to be static.

> +static void *
> +empty_thread (void *closure)
> +{
> +  /* Make sure that the alternate thread waits (and exists) till the main
> +     thread finishes running the test.  */
> +  xpthread_barrier_wait (&barrier);
> +
> +  return NULL;
> +}
> +
> +int
> +support_test_in_thread_wrapper (int argc, char **argv,
> +                                const struct test_config *config)
> +{
> +  pthread_t thread;
> +  struct test_thread_args closure = {.argc = argc,
> +                                     .argv = argv,
> +                                     .config = config};
> +
> +  if (config->test_in_thread == THREAD_MAIN)
> +    {
> +      xpthread_barrier_init (&barrier, NULL, 2);
> +      thread = xpthread_create (NULL, empty_thread, NULL);
> +
> +      /* Run the test in the main thread.  */
> +      test_thread (&closure);
> +
> +      /* Signal to the alternate thread that it can return.  */
> +      xpthread_barrier_wait (&barrier);
> +      xpthread_join (thread);
> +    }
> +  else /* config->test_in_thread == THREAD_WORKER.  */
> +    {
> +      /* Run the test in an alternate thread.  */
> +      thread = xpthread_create (NULL, test_thread, &closure);
> +      xpthread_join (thread);
> +    }
> +
> +  return closure.ret;
> +}

> diff --git a/support/test-driver.c b/support/test-driver.c
> index 40e2bc0ee2..cb65b9f078 100644
> --- a/support/test-driver.c
> +++ b/support/test-driver.c
> @@ -168,5 +168,13 @@ main (int argc, char **argv)
>    test_config.optstring = "+";
>  #endif
>  
> +#ifdef TEST_IN_THREAD
> +  test_config.test_in_thread = TEST_IN_THREAD;
> +  test_config.test_in_thread_wrapper = support_test_in_thread_wrapper;
> +#else
> +  test_config.test_in_thread = 0;
> +  test_config.test_in_thread_wrapper = NULL;
> +#endif
> +
>    return support_test_main (argc, argv, &test_config);
>  }
> diff --git a/support/test-driver.h b/support/test-driver.h
> index 9291611fbf..2d76ba4aab 100644
> --- a/support/test-driver.h
> +++ b/support/test-driver.h
> @@ -38,6 +38,8 @@ struct test_config
>    char no_setvbuf;       /* Boolean flag to disable setvbuf.  */
>    char run_command_mode; /* Boolean flag to indicate run-command-mode.  */
>    const char *optstring; /* Short command line options.  */
> +  int test_in_thread;    /* 0 => no threading, MAIN, WORKER.  */
> +  int (*test_in_thread_wrapper) (int, char **, const struct test_config *);
>  };
>  
>  enum
> @@ -54,6 +56,11 @@ enum
>      /* Used for command line argument parsing.  */
>      OPT_DIRECT = 1000,
>      OPT_TESTDIR,
> +
> +    /* Used for TEST_IN_THREAD to run single-threaded tests in a
> +       multi-threaded environment.  */
> +    THREAD_MAIN = 1,
> +    THREAD_WORKER = 2,
>    };

I would add a prefix, something like TEST_THREAD_MAIN.

>  /* Options provided by the test driver.  */
> @@ -78,6 +85,9 @@ extern unsigned int test_verbose;
>        printf (__VA_ARGS__);                      \
>    } while (0);
>  
> +extern int support_test_in_thread_wrapper (int argc, char **argv,
> +                                           const struct test_config *config);
> +

This should have a comment.

Thanks,
Florian



More information about the Libc-alpha mailing list