]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
tests: (helpers) add a thread creation helper
authorChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Wed, 22 Apr 2026 00:56:26 +0000 (20:56 -0400)
committerChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Mon, 4 May 2026 12:55:15 +0000 (08:55 -0400)
This simple helper can be used to create an arbitrary amount
of threads to be used in test scripts for tools like chrt(1).
chrt(1) can perform tasks on multiple threads for a process
and to conveniently test this 'test_threads_create' can be
used to spawn threads for a specified amount of time to act on.

Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
meson.build
tests/commands.sh
tests/helpers/Makemodule.am
tests/helpers/test_threads_create.c [new file with mode: 0644]

index 185f5597702e3b5f3ea4db43843347945da479ad..bd5adb47c92d0618c1a9cdec00967c3676ab31f6 100644 (file)
@@ -4005,6 +4005,17 @@ if not is_disabler(exe)
   exes += exe
 endif
 
+exe = executable(
+  'test_threads_create',
+  'tests/helpers/test_threads_create.c',
+  include_directories : includes,
+  dependencies : thread_libs,
+  link_with : lib_common,
+  build_by_default: program_tests)
+if not is_disabler(exe)
+  exes += exe
+endif
+
 ############################################################
 
 if conf.get('HAVE_OPENAT').to_string() == '1'
index f1cdf52a6b58a558f7a82421c52f87de7b91c9cc..4c08c4416dc1a92fb168afb5bdc091c9f7579554 100644 (file)
@@ -54,6 +54,7 @@ TS_HELPER_SIGSTATE="${ts_helpersdir}test_sigstate"
 TS_HELPER_STRERROR="${ts_helpersdir}test_strerror"
 TS_HELPER_STRUTILS="${ts_helpersdir}test_strutils"
 TS_HELPER_SYSINFO="${ts_helpersdir}test_sysinfo"
+TS_HELPER_THREADS_CREATE="${ts_helpersdir}test_threads_create"
 TS_HELPER_TIOCSTI="${ts_helpersdir}test_tiocsti"
 TS_HELPER_UUID_PARSER="${ts_helpersdir}test_uuid_parser"
 TS_HELPER_UUID_NAMESPACE="${ts_helpersdir}test_uuid_namespace"
index bdf2d2d8dca98feb334ed28fd539e10344b81405..4b575ae38933e947a0bd02a893d7129f169925e1 100644 (file)
@@ -63,3 +63,7 @@ endif
 
 check_PROGRAMS += test_open_twice
 test_open_twice_SOURCES = tests/helpers/test_open_twice.c
+
+check_PROGRAMS += test_threads_create
+test_threads_create_SOURCES = tests/helpers/test_threads_create.c
+test_threads_create_LDADD =  $(LDADD) libcommon.la $(PTHREAD_LIBS)
diff --git a/tests/helpers/test_threads_create.c b/tests/helpers/test_threads_create.c
new file mode 100644 (file)
index 0000000..d50d74f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2026 Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <err.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "xalloc.h"
+#include "strutils.h"
+
+static void __attribute__((__noreturn__)) usage(void)
+{
+       printf("%s [options] <thread count>\n\n", program_invocation_short_name);
+       fputs("Options:\n", stdout);
+       fputs(" -s, --sleep <n>         <n> seconds threads should sleep (default: 3)\n", stdout);
+
+       exit(EXIT_SUCCESS);
+}
+
+#define DEFAULT_NUM_THREADS 5
+#define DEFAULT_THREAD_SLEEP_SEC 3
+
+struct thread_ctl {
+    int thread_id;
+    uint16_t sleep_time;
+};
+
+static void* thread_func(void* arg)
+{
+       pid_t tid = syscall(SYS_gettid);
+       struct thread_ctl *tctl = (struct thread_ctl *)arg;
+       int id = tctl->thread_id + 2;
+       uint16_t sec = tctl->sleep_time;
+
+       printf("Thread %d: %d\n", id, tid);
+       sleep(sec);
+
+       free(arg);
+       return NULL;
+}
+
+int main(int argc, char **argv)
+{
+       int c, rc = 0;
+       uint16_t sleep_time = DEFAULT_THREAD_SLEEP_SEC;
+       size_t t_cnt = DEFAULT_NUM_THREADS;
+
+       static const struct option longopts[] = {
+               { "sleep",      1, NULL, 's' },
+               { "help",       0, NULL, 'h' },
+               { NULL, 0, NULL, 0 },
+       };
+
+       while((c = getopt_long(argc, argv, "hs:", longopts, NULL)) != -1) {
+               switch(c) {
+               case 's':
+                       sleep_time = strtou16_or_err(optarg, "invalid --sleep argument");
+                       break;
+               case 'h':
+                       usage();
+                       break;
+               default:
+                       err(EXIT_FAILURE, "try --help");
+               }
+       }
+
+       if (argc - optind > 1)
+               errx(EXIT_FAILURE, "too many arguments");
+
+       if (optind < argc)
+               t_cnt = strtou16_or_err(argv[optind], "invalid <thread count> argument");
+
+       printf("Thread 1: %d\n", getpid());
+
+       pthread_t *threads = xcalloc(t_cnt, sizeof(pthread_t));
+
+       for (size_t i = 0; i < t_cnt; i++) {
+               struct thread_ctl *tctl = xmalloc(sizeof(struct thread_ctl));
+
+               tctl->thread_id = i;
+               tctl->sleep_time = sleep_time;
+
+               rc = pthread_create(&threads[i], NULL, thread_func, tctl);
+               if (rc)
+                       errx(EXIT_FAILURE, "failed to create thread %zu: %s", i, strerror(rc));
+       }
+
+       for (size_t i = 0; i < t_cnt; i++) {
+               rc = pthread_join(threads[i], NULL);
+               if (rc)
+                       errx(EXIT_FAILURE, "failed to join thread %zu: %s", i, strerror(rc));
+       }
+
+       free(threads);
+       return EXIT_SUCCESS;
+}