On Mon, Apr 08 2024 at 20:49, Oleg Nesterov wrote:
> To me this test should simply do
>
>       ksft_test_result(!ctd_failed, "check signal distribution\n");
>       return 0;

Right.

> but I am not familiar with tools/testing/selftests/ and I am not sure
> I understand the last email from Thomas.

The discussion started about running new tests on older kernels. As this
is a feature and not a bug fix that obviously fails on older kernels.

So something like the uncompiled below should work.

Thanks,

        tglx
---
--- a/tools/testing/selftests/timers/posix_timers.c
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -184,80 +184,83 @@ static int check_timer_create(int which)
        return 0;
 }
 
-int remain;
-__thread int got_signal;
+static pthread_t ctd_thread;
+static volatile int ctd_count, ctd_failed;
 
-static void *distribution_thread(void *arg)
+static void ctd_sighandler(int sig)
 {
-       while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
-       return NULL;
-}
-
-static void distribution_handler(int nr)
-{
-       if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED))
-               __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED);
+       if (pthread_self() != ctd_thread)
+               ctd_failed = 1;
+       ctd_count--;
 }
 
-/*
- * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID
- * timer signals. This primarily tests that the kernel does not favour any one.
- */
-static int check_timer_distribution(void)
+static void *ctd_thread_func(void *arg)
 {
-       int err, i;
-       timer_t id;
-       const int nthreads = 10;
-       pthread_t threads[nthreads];
        struct itimerspec val = {
                .it_value.tv_sec = 0,
                .it_value.tv_nsec = 1000 * 1000,
                .it_interval.tv_sec = 0,
                .it_interval.tv_nsec = 1000 * 1000,
        };
+       timer_t id;
 
-       remain = nthreads + 1;  /* worker threads + this thread */
-       signal(SIGALRM, distribution_handler);
-       err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
-       if (err < 0) {
-               ksft_perror("Can't create timer");
-               return -1;
-       }
-       err = timer_settime(id, 0, &val, NULL);
-       if (err < 0) {
-               ksft_perror("Can't set timer");
-               return -1;
-       }
+       /* 1/10 seconds to ensure the leader sleeps */
+       usleep(10000);
 
-       for (i = 0; i < nthreads; i++) {
-               err = pthread_create(&threads[i], NULL, distribution_thread,
-                                    NULL);
-               if (err) {
-                       ksft_print_msg("Can't create thread: %s (%d)\n",
-                                      strerror(errno), errno);
-                       return -1;
-               }
-       }
+       ctd_count = 100;
+       if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id))
+               return "Can't create timer";
+       if (timer_settime(id, 0, &val, NULL))
+               return "Can't set timer";
 
-       /* Wait for all threads to receive the signal. */
-       while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
+       while (ctd_count > 0 && !ctd_failed)
+               ;
 
-       for (i = 0; i < nthreads; i++) {
-               err = pthread_join(threads[i], NULL);
-               if (err) {
-                       ksft_print_msg("Can't join thread: %s (%d)\n",
-                                      strerror(errno), errno);
-                       return -1;
-               }
-       }
+       if (timer_delete(id))
+               return "Can't delete timer";
 
-       if (timer_delete(id)) {
-               ksft_perror("Can't delete timer");
+       return NULL;
+}
+
+static bool check_kernel_version(unsigned int min_major, unsigned int 
min_minor)
+{
+       unsigned int major, minor;
+       struct utsname info;
+
+       uname(&info);
+       if (sscanf(info.release, "%u.%u.", &major, &minor) != 2)
+               ksft_exit_fail();
+       return major > min_major || (major == min_major && minor >= min_minor);
+}
+
+/*
+ * Test that only the running thread receives the timer signal.
+ */
+static int check_timer_distribution(void)
+{
+       const char *errmsg;
+
+       if (!check_kernel_version(6, 3)) {
+               ksft_test_result_skip("check signal distribution (old 
kernel)\n");
                return 0;
        }
 
-       ksft_test_result_pass("check_timer_distribution\n");
+       signal(SIGALRM, ctd_sighandler);
+
+       errmsg = "Can't create thread";
+       if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL))
+               goto err;
+
+       errmsg = "Can't join thread";
+       if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg)
+               goto err;
+
+       ksft_test_result(!ctd_failed, "check signal distribution\n");
        return 0;
+
+err:
+       ksft_print_msg(errmsg);
+       return -1;
 }
 
 int main(int argc, char **argv)

Reply via email to