On Thu, Feb 05 2026 at 10:08, Yuwen Chen wrote:
> There are timing issues in the use of threads in some unit test cases
> for futex.

This is handwaving and contains zero technical information.

https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#changelog

> A potentially good solution is to check whether the thread

Either it's a solution or not. 

> is in the sleep state after creating it.

> This patch adds a file named futex_thread.h, in which several thread

# git grep 'This patch' Documentation/process/

> related functions are implemented to facilitate the solution of this
> problem.
>
> Signed-off-by: Yuwen Chen <[email protected]>

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes

> +#ifndef _FUTEX_THREAD_H
> +#define _FUTEX_THREAD_H
> +#include <stdio.h>
> +#include <string.h>
> +#include <errno.h>
> +
> +#define USEC_PER_SEC 1000000L

#include <linux/time64.h>

> +#define WAIT_THREAD_RETRIES 100
> +#define WAIT_THREAD_CREATE_TIMEOUT_USECS (USEC_PER_SEC)
> +
> +struct futex_thread {
> +     pthread_t               thread;
> +     pthread_barrier_t       barrier;
> +     pid_t                   tid;
> +     int                     (*threadfn)(void *arg);
> +     void                    *arg;
> +     int                     retval;
> +};
> +
> +static int __wait_for_thread(FILE *fp)
> +{
> +     char buf[80] = "";
> +
> +     for (int i = 0; i < WAIT_THREAD_RETRIES; i++) {
> +             if (!fgets(buf, sizeof(buf), fp))
> +                     return -EIO;
> +             if (!strncmp(buf, "futex", 5))
> +                     return 0;
> +             usleep(WAIT_THREAD_CREATE_TIMEOUT_USECS / WAIT_THREAD_RETRIES);

What's wrong with

#define WAIT_THREAD_DELAY       (USEC_PER_SEC / WAIT_THREAD_RETRIES)
...
                usleep(WAIT_THREAD_DELAY);

> +             rewind(fp);
> +     }
> +     return -ETIMEDOUT;
> +}
> +
> +static void *__futex_thread_fn(void *arg)
> +{
> +     struct futex_thread *t = arg;
> +
> +     t->tid = gettid();
> +     pthread_barrier_wait(&t->barrier);
> +     t->retval = t->threadfn(t->arg);
> +     return NULL;
> +}
> +
> +/**
> + * futex_wait_for_thread - Wait for the child thread to sleep in the futex 
> context
> + * @t: Thread handle.
> + */
> +static int futex_wait_for_thread(struct futex_thread *t)
> +{
> +     char fname[80];
> +     FILE *fp;
> +     int res;
> +
> +     snprintf(fname, sizeof(fname), "/proc/%d/wchan", t->tid);
> +     fp = fopen(fname, "r");
> +     if (!fp) {
> +             usleep(USEC_PER_SEC / 10);

What is this usleep for?

> +             return -EIO;
> +     }
> +
> +     res = __wait_for_thread(fp);
> +     if (res == -EIO)
> +             usleep(USEC_PER_SEC / 10);

Again. What's this usleep for?

If the file cannot be opened or fgets() fails then this fails hard.

> +     fclose(fp);
> +     return res;
> +}
> +
> +/**
> + * futex_thread_create - Create a new thread for testing.
> + * @t:        The handle of the newly created thread.
> + * @threadfn: The new thread starts execution by invoking threadfn
> + * @arg:      The parameters passed to threadfn.
> + */
> +static int futex_thread_create(struct futex_thread *t, int (*threadfn)(void 
> *), void *arg)
> +{
> +     int ret;
> +
> +     pthread_barrier_init(&t->barrier, NULL, 2);
> +     t->tid = 0;
> +     t->threadfn = threadfn;
> +     t->arg = arg;
> +
> +     ret = pthread_create(&t->thread, NULL, __futex_thread_fn, t);
> +     if (ret)
> +             return ret;
> +
> +     pthread_barrier_wait(&t->barrier);
> +     return 0;

Why aren't you waiting for the thread right here? There is absolutely no
point in doing that at the call site of futex_thread_create().

Thanks,

        tglx

Reply via email to