[PATCH 2/3] nptl: Do not always assume set_robust_list availability (BZ 33225)

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Mon Sep 8 16:08:49 GMT 2025


Ping. I still think that the incostency between some arches (ARM/x86 and
RISC-V) wrt robust support in qemu it still work to fix.

On 29/07/25 15:21, Adhemerval Zanella wrote:
> The __ASSUME_SET_ROBUST_LIST is used to define and set
> __nptl_set_robust_list_avail to advertise process shared robust mutex
> support, done at __tls_init_tp (during pthread initialization).
> 
> Some specific kernel configurations and the qemu-user (for all ABIs) do
> not implement the set_robust_list syscal.  Therefore, for the default case
> (__ASSUME_SET_ROBUST_LIST being true), the missing support is not
> detected, and pthread_mutex_init succeeds where it should fail.  For
> instance, the sequence succeeds on qemu-user even when set_robust_list
> fails with ENOSYS.
> 
>   pthread_mutexattr_init(&attr);
>   pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
>   pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
> 
>   pthread_mutex_init(&mutex, &attr);
> 
> This patch removes __ASSUME_SET_ROBUST_LIST and always enables
> __nptl_set_robust_list_avail detection.
> 
> Checked on x86_64-linux-gnu.
> 
> Reported-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  nptl/pthread_create.c                         |  4 ----
>  nptl/pthread_mutex_init.c                     |  3 ---
>  nptl/tst-mutexpi10.c                          |  4 +++-
>  nptl/tst-robust-fork.c                        | 21 +++++++++++++++++++
>  sysdeps/nptl/dl-tls_init_tp.c                 |  8 +------
>  sysdeps/nptl/pthreadP.h                       |  2 --
>  sysdeps/pthread/tst-mutex7.c                  |  3 +++
>  sysdeps/pthread/tst-robust1.c                 |  3 +++
>  sysdeps/pthread/tst-robust10.c                |  3 +++
>  sysdeps/pthread/tst-robust7.c                 |  2 ++
>  sysdeps/pthread/tst-robust8.c                 |  6 ++++++
>  sysdeps/pthread/tst-robust9.c                 |  2 ++
>  sysdeps/unix/sysv/linux/arm/kernel-features.h |  7 -------
>  .../unix/sysv/linux/hppa/kernel-features.h    |  3 ---
>  sysdeps/unix/sysv/linux/kernel-features.h     |  5 -----
>  .../unix/sysv/linux/m68k/kernel-features.h    |  5 -----
>  .../unix/sysv/linux/mips/kernel-features.h    |  6 ------
>  .../unix/sysv/linux/riscv/kernel-features.h   |  5 -----
>  .../unix/sysv/linux/sparc/kernel-features.h   |  6 ------
>  19 files changed, 44 insertions(+), 54 deletions(-)
> 
> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index e1033d4ee6..04b8f27b99 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -380,9 +380,7 @@ start_thread (void *arg)
>        __libc_fatal ("Fatal glibc error: rseq registration failed\n");
>    }
>  
> -#ifndef __ASSUME_SET_ROBUST_LIST
>    if (__nptl_set_robust_list_avail)
> -#endif
>      {
>        /* This call should never fail because the initial call in init.c
>  	 succeeded.  */
> @@ -517,7 +515,6 @@ start_thread (void *arg)
>    pd->exiting = true;
>    __libc_lock_unlock (pd->exit_lock);
>  
> -#ifndef __ASSUME_SET_ROBUST_LIST
>    /* If this thread has any robust mutexes locked, handle them now.  */
>  # if __PTHREAD_MUTEX_HAVE_PREV
>    void *robust = pd->robust_head.list;
> @@ -548,7 +545,6 @@ start_thread (void *arg)
>  	}
>        while (robust != (void *) &pd->robust_head);
>      }
> -#endif
>  
>    /* Release the vDSO getrandom per-thread buffer with all signal blocked,
>       to avoid creating a new free-state block during thread release.  */
> diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
> index 1639935202..35b55576c4 100644
> --- a/nptl/pthread_mutex_init.c
> +++ b/nptl/pthread_mutex_init.c
> @@ -93,12 +93,9 @@ ___pthread_mutex_init (pthread_mutex_t *mutex,
>  
>    if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
>      {
> -#ifndef __ASSUME_SET_ROBUST_LIST
>        if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0
>  	  && !__nptl_set_robust_list_avail)
>  	return ENOTSUP;
> -#endif
> -
>        mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
>      }
>  
> diff --git a/nptl/tst-mutexpi10.c b/nptl/tst-mutexpi10.c
> index 6d2bbbb308..92bd82ebb7 100644
> --- a/nptl/tst-mutexpi10.c
> +++ b/nptl/tst-mutexpi10.c
> @@ -58,7 +58,9 @@ do_test (void)
>  	  xpthread_mutexattr_setrobust (&attr, robust[r]);
>  
>  	  pthread_mutex_t mtx;
> -	  xpthread_mutex_init (&mtx, &attr);
> +	  if (pthread_mutex_init (&mtx, &attr) == ENOTSUP
> +	      && robust[r] == PTHREAD_MUTEX_ROBUST)
> +	    continue;
>  
>  	  /* Uncontended case does not trigger any futex call.  */
>  	  struct timespec tmo = timespec_add (xclock_now (clocks[c].clk),
> diff --git a/nptl/tst-robust-fork.c b/nptl/tst-robust-fork.c
> index 8144b3de3d..375dad768a 100644
> --- a/nptl/tst-robust-fork.c
> +++ b/nptl/tst-robust-fork.c
> @@ -159,9 +159,20 @@ one_test (int parent_bits, int child_bits, int nonshared_bits,
>    xmunmap (shared, sizeof (*shared));
>  }
>  
> +static inline bool
> +is_robust_pshared (int bits)
> +{
> +  return (bits & (mutex_robust | mutex_pshared))
> +    == (mutex_robust | mutex_pshared);
> +}
> +
>  static int
>  do_test (void)
>  {
> +  bool robust_support = support_mutex_robust ();
> +  if (test_verbose)
> +    printf ("info: robust_support=%d\n", robust_support);
> +
>    for (int parent_bits = 0; parent_bits <= mutex_all_bits; ++parent_bits)
>      for (int child_bits = 0; child_bits <= mutex_all_bits; ++child_bits)
>        for (int nonshared_bits = 0; nonshared_bits <= mutex_all_bits;
> @@ -175,6 +186,16 @@ do_test (void)
>                          parent_bits, child_bits, nonshared_bits,
>                          lock_nonshared ? " lock_nonshared" : "",
>                          lock_child ? " lock_child" : "");
> +	      if ((is_robust_pshared (parent_bits)
> +		   || is_robust_pshared (child_bits)
> +		   || is_robust_pshared (nonshared_bits))
> +		  && !robust_support)
> +		{
> +		  if (test_verbose)
> +		    printf ("info:   skipping tests due missing robust mutex"
> +			    "support");
> +		  continue;
> +		}
>                one_test (parent_bits, child_bits, nonshared_bits,
>                          lock_nonshared, lock_child);
>              }
> diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
> index 47566dce4f..8bf3c7f14b 100644
> --- a/sysdeps/nptl/dl-tls_init_tp.c
> +++ b/sysdeps/nptl/dl-tls_init_tp.c
> @@ -28,10 +28,8 @@
>  #define TUNABLE_NAMESPACE pthread
>  #include <dl-tunables.h>
>  
> -#ifndef __ASSUME_SET_ROBUST_LIST
>  bool __nptl_set_robust_list_avail;
>  rtld_hidden_data_def (__nptl_set_robust_list_avail)
> -#endif
>  
>  bool __nptl_initial_report_events;
>  rtld_hidden_def (__nptl_initial_report_events)
> @@ -94,11 +92,7 @@ __tls_init_tp (void)
>      int res = INTERNAL_SYSCALL_CALL (set_robust_list, &pd->robust_head,
>                                       sizeof (struct robust_list_head));
>      if (!INTERNAL_SYSCALL_ERROR_P (res))
> -      {
> -#ifndef __ASSUME_SET_ROBUST_LIST
> -        __nptl_set_robust_list_avail = true;
> -#endif
> -      }
> +      __nptl_set_robust_list_avail = true;
>    }
>  
>    {
> diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
> index 8f256967e2..0822a437da 100644
> --- a/sysdeps/nptl/pthreadP.h
> +++ b/sysdeps/nptl/pthreadP.h
> @@ -210,12 +210,10 @@ libc_hidden_proto (__pthread_keys)
>  extern unsigned int __nptl_nthreads;
>  libc_hidden_proto (__nptl_nthreads)
>  
> -#ifndef __ASSUME_SET_ROBUST_LIST
>  /* True if the set_robust_list system call works.  Initialized in
>     __tls_init_tp.  */
>  extern bool __nptl_set_robust_list_avail;
>  rtld_hidden_proto (__nptl_set_robust_list_avail)
> -#endif
>  
>  /* Thread Priority Protection.  */
>  extern int __sched_fifo_min_prio;
> diff --git a/sysdeps/pthread/tst-mutex7.c b/sysdeps/pthread/tst-mutex7.c
> index fc8220eec7..d56a7f4dbb 100644
> --- a/sysdeps/pthread/tst-mutex7.c
> +++ b/sysdeps/pthread/tst-mutex7.c
> @@ -21,6 +21,9 @@
>  #include <stdlib.h>
>  #include <time.h>
>  
> +#include <support/check.h>
> +#include <support/xthread.h>
> +
>  /* This test is a template for other tests to use.  Other tests define
>     the following macros to change the behaviour of the template test.
>     The test is very simple, it configures N threads given the parameters
> diff --git a/sysdeps/pthread/tst-robust1.c b/sysdeps/pthread/tst-robust1.c
> index bd659cc494..638cb705c8 100644
> --- a/sysdeps/pthread/tst-robust1.c
> +++ b/sysdeps/pthread/tst-robust1.c
> @@ -20,6 +20,9 @@
>  #include <stdio.h>
>  #include <stdlib.h>
>  
> +#include <support/check.h>
> +#include <support/xthread.h>
> +
>  
>  static pthread_mutex_t m1;
>  static pthread_mutex_t m2;
> diff --git a/sysdeps/pthread/tst-robust10.c b/sysdeps/pthread/tst-robust10.c
> index ef1e3113f0..813d785ed7 100644
> --- a/sysdeps/pthread/tst-robust10.c
> +++ b/sysdeps/pthread/tst-robust10.c
> @@ -22,6 +22,9 @@
>  #include <string.h>
>  #include <errno.h>
>  
> +#include <support/check.h>
> +#include <support/xthread.h>
> +
>  pthread_mutex_t mutex;
>  
>  static void *
> diff --git a/sysdeps/pthread/tst-robust7.c b/sysdeps/pthread/tst-robust7.c
> index bf660e8cb0..f73363de96 100644
> --- a/sysdeps/pthread/tst-robust7.c
> +++ b/sysdeps/pthread/tst-robust7.c
> @@ -21,6 +21,8 @@
>  #include <stdio.h>
>  #include <stdlib.h>
>  
> +#include <support/check.h>
> +#include <support/xthread.h>
>  
>  static pthread_barrier_t b;
>  static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
> diff --git a/sysdeps/pthread/tst-robust8.c b/sysdeps/pthread/tst-robust8.c
> index 4c8a20e916..dd6230168d 100644
> --- a/sysdeps/pthread/tst-robust8.c
> +++ b/sysdeps/pthread/tst-robust8.c
> @@ -10,6 +10,8 @@
>  
>  #include <pthreadP.h>
>  
> +#include <support/check.h>
> +#include <support/xthread.h>
>  
>  
>  static void prepare (void);
> @@ -143,6 +145,10 @@ child (int round)
>  static int
>  do_test (void)
>  {
> +  /* Process shared robust mutexes requires kernel support.  */
> +  if (!support_mutex_robust ())
> +    FAIL_UNSUPPORTED ("robust mutexes not supported");
> +
>    if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0)
>      {
>        puts ("cannot size new file");
> diff --git a/sysdeps/pthread/tst-robust9.c b/sysdeps/pthread/tst-robust9.c
> index ca24f24282..de675259da 100644
> --- a/sysdeps/pthread/tst-robust9.c
> +++ b/sysdeps/pthread/tst-robust9.c
> @@ -5,6 +5,8 @@
>  #include <unistd.h>
>  #include <sys/time.h>
>  
> +#include <support/check.h>
> +#include <support/xthread.h>
>  
>  static pthread_mutex_t m;
>  
> diff --git a/sysdeps/unix/sysv/linux/arm/kernel-features.h b/sysdeps/unix/sysv/linux/arm/kernel-features.h
> index 10caae8b91..a1f8611160 100644
> --- a/sysdeps/unix/sysv/linux/arm/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/arm/kernel-features.h
> @@ -20,13 +20,6 @@
>  #include <endian.h>
>  #include_next <kernel-features.h>
>  
> -/* The ARM kernel before 3.14.3 may or may not support
> -   futex_atomic_cmpxchg_inatomic, depending on kernel
> -   configuration.  */
> -#if __LINUX_KERNEL_VERSION < 0x030E03
> -# undef __ASSUME_SET_ROBUST_LIST
> -#endif
> -
>  /* ARM fadvise64_64 reorganize the syscall arguments.  */
>  #define __ASSUME_FADVISE64_64_6ARG	1
>  
> diff --git a/sysdeps/unix/sysv/linux/hppa/kernel-features.h b/sysdeps/unix/sysv/linux/hppa/kernel-features.h
> index 102714166e..e9b3bcaa1a 100644
> --- a/sysdeps/unix/sysv/linux/hppa/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/hppa/kernel-features.h
> @@ -30,6 +30,3 @@
>  
>  #undef __ASSUME_CLONE_DEFAULT
>  #define __ASSUME_CLONE_BACKWARDS 1
> -
> -/* QEMU does not support set_robust_list.  */
> -#undef __ASSUME_SET_ROBUST_LIST
> diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
> index a49a9159cf..f203d038da 100644
> --- a/sysdeps/unix/sysv/linux/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/kernel-features.h
> @@ -49,11 +49,6 @@
>     SH this appeared first in 2.6.19-rc1.  */
>  #define __ASSUME_PSELECT	1
>  
> -/* Support for inter-process robust mutexes was added in 2.6.17 (but
> -   some architectures lack futex_atomic_cmpxchg_inatomic in some
> -   configurations).  */
> -#define __ASSUME_SET_ROBUST_LIST	1
> -
>  /* The termios2 interface was introduced across all architectures except
>     Alpha in kernel 2.6.22. */
>  #define __ASSUME_TERMIOS2	1
> diff --git a/sysdeps/unix/sysv/linux/m68k/kernel-features.h b/sysdeps/unix/sysv/linux/m68k/kernel-features.h
> index 3515b20433..ba0cc0844f 100644
> --- a/sysdeps/unix/sysv/linux/m68k/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/m68k/kernel-features.h
> @@ -42,11 +42,6 @@
>  # undef __ASSUME_GETPEERNAME_SYSCALL
>  #endif
>  
> -/* No support for PI futexes or robust mutexes before 3.10 for m68k.  */
> -#if __LINUX_KERNEL_VERSION < 0x030a00
> -# undef __ASSUME_SET_ROBUST_LIST
> -#endif
> -
>  /* m68k only supports ipc syscall before 5.1.  */
>  #if __LINUX_KERNEL_VERSION < 0x050100
>  # undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
> diff --git a/sysdeps/unix/sysv/linux/mips/kernel-features.h b/sysdeps/unix/sysv/linux/mips/kernel-features.h
> index d86ac92352..c9bba743ac 100644
> --- a/sysdeps/unix/sysv/linux/mips/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/mips/kernel-features.h
> @@ -21,12 +21,6 @@
>  
>  #include_next <kernel-features.h>
>  
> -/* The MIPS kernel does not support futex_atomic_cmpxchg_inatomic if
> -   emulating LL/SC.  */
> -#if __mips == 1 || defined _MIPS_ARCH_R5900
> -# undef __ASSUME_SET_ROBUST_LIST
> -#endif
> -
>  /* Define this if your 32-bit syscall API requires 64-bit register
>     pairs to start with an even-number register.  */
>  #if _MIPS_SIM == _ABIO32
> diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
> index dce50835d1..83e0c69ee3 100644
> --- a/sysdeps/unix/sysv/linux/riscv/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
> @@ -21,8 +21,3 @@
>  
>  #undef __ASSUME_CLONE_DEFAULT
>  #define __ASSUME_CLONE_BACKWARDS 1
> -
> -/* No support for PI mutexes or robust futexes before 4.20.  */
> -#if __LINUX_KERNEL_VERSION < 0x041400
> -# undef __ASSUME_SET_ROBUST_LIST
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/sparc/kernel-features.h b/sysdeps/unix/sysv/linux/sparc/kernel-features.h
> index 24423db127..8e7ee91eeb 100644
> --- a/sysdeps/unix/sysv/linux/sparc/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/sparc/kernel-features.h
> @@ -19,12 +19,6 @@
>  
>  #include_next <kernel-features.h>
>  
> -/* 32-bit SPARC kernels do not support
> -   futex_atomic_cmpxchg_inatomic.  */
> -#if !defined __arch64__ && !defined __sparc_v9__
> -# undef __ASSUME_SET_ROBUST_LIST
> -#endif
> -
>  /* These syscalls were added for 32-bit in 4.4 (but present for 64-bit
>     in all supported kernel versions); the architecture-independent
>     kernel-features.h assumes some of them to be present by default.



More information about the Libc-alpha mailing list