From patchwork Wed Jul 29 17:46:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 140184 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 105A04BB58E7 for ; Wed, 29 Jul 2026 17:50:10 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 105A04BB58E7 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=s6YUOuzB X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id CBF884BB24F9 for ; Wed, 29 Jul 2026 17:49:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CBF884BB24F9 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CBF884BB24F9 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785347362; cv=none; b=ZIXMIGDYVwYHmIbih4E2/MpujUS0cBtCt1H4kS4fvHRb5Blg9LdMHNLzChrW63YjW5+DY3kJ+Szq3ePE3ZH/wIber9npZxyWQVbsg6iOD8SjAML4+AZ1bUEl9RqMdBZYXgOGv40Bj1IlbWb+95LSEcSPYz7NgzKv5/iBgAQDDck= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785347362; c=relaxed/simple; bh=t3vfDl+Ie8+Pf6MW0VFjQmYe0v7KdGJiLkybN0h6J4k=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=h6c/W/NhmART0AcQ9pyOm3H2o4gPnn2aLzwGED0abw06kq7W8mvxPuG/sdP1ltvcSnuhozGPErzJdY0m+qB/l86gfnuS8tFlEdv17nj3/noqGzwZoYHHDzgdxbd44bS6gpTFzQfm6TNCBb9mOkT6iFWGh5egHblHXD04s7JG+Wg= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=s6YUOuzB DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CBF884BB24F9 Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-2caed617615so15718885ad.3 for ; Wed, 29 Jul 2026 10:49:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785347361; x=1785952161; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=RfflKnJN9Oglq4oX/oR+siE9mPDPuSAEbDB9IGy4f8I=; b=s6YUOuzBwYNLG6z86Gct7X2uu3Q696fz3QyHg6zwXORsWqqSc3GVL3yh4MYFOBZ5LF 5dR6QFKMZpp4bhg4JYhEjqfxRpoS1773YC5YuhIGj6devxm9sw7m777EqmV0hODNjLTJ o6Hv7J3IHt1cb5aZ+uT4gZaKVi2yOgPDyfoT4gyMX75Y9xnbiTwzM1iiYOsKR06J0LR8 eeBjSdkIufSasBa5sEIeixcQFnoJB6qGlLPnSPgRFYFCFJt0J/xjA9IVgW+e8N2aS7iC kIKwk/+8uK+OX0yj65VfV/6fiUMEZzvUoqZk6V7Pkhm7FUJBGYOIBliEHmVzeZMrNnU3 qYVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785347361; x=1785952161; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=RfflKnJN9Oglq4oX/oR+siE9mPDPuSAEbDB9IGy4f8I=; b=R8cnK1e1xbhIM23RzjnrudSYRP8YODhOKvRbPyYLq9nxVkGENUzIV4X/cGpZJ4iebY a1Ens0a/ojg1/SYxdMt1EiyIxn8LLvJcSsQEMl6nktqs7m5NlFPr/XjoTjyYdcGQOZg1 NqxufIT5CcD0UCwdN2ZlHXnoWWSTcohoPdEGTwRnDiNWdgq70HRAgoXOQUQBjWIk5sDX /Hoxv7zVOLH8Bq6iDQFiIgKBA7ZmYcisyP2Pt6yO2PHhFb9aRR1s8eP1+eSKb0JwvBKU 5F2SAxLSRPbYbHvhCGuxCMTth0ON3nd6v92weL47SwzVlMvPGiKvPe6h9tjSQL5FgQAE 0xjw== X-Gm-Message-State: AOJu0YyU2HVGH3DCrhnlKakrmvvCDgXFdRMUa0ooJDIWxX9lMsFZn3ok H0DslCVDkVDx2ihLZGROZstwnML4fuuCi5H7BBrWP+qRL6RtPkev6xOwRji3NE5oaTdPlkF225J nNtM7 X-Gm-Gg: AR+sD13PV14ryMGnFnmDIPguE+YfolUs2T81FY5c21V+8xhb8okGzRvtXNcg8xccBI/ Y22a6jOdrIr/aqnNE5jLfoxKkBP7++8lIYG9jY0mC6EQZCBon1t9PS/UlKjbO9hmoPR7CM6rRuU /u5OB8uWsGTo5JpU8QE1tn7MUMbAAbdfhByK5qEY6N04aArjh5g3uK4uwHk6haXdmZ70Y3KCYFZ bbsQemZawn6MWQsglkO1pyN/iuAO3IfyVu/D4QoeMnjgCqP1p0cGCbZmAj2Cd5c+qPmGI8kUIkn 20wKokerWUtkHRnv1YjjYj6EdX45zYLbxmapt5KfWOgISpofJBu8nrUUd+iu/EiYhNM0UpppiJA qz2iCE+JHHmX87zPMHTyOJmgvbNSpPQh9TWjgBUnor1i6UC+BvqquL/4vPVDGXwahzxrTJ/sii/ /Uk+qIfnD7mUphXW2Ez1EVll6AksSx46PnW4RP4EhurZXR00W9/V/L1UgNrpEJYHg7DS4U0Q== X-Received: by 2002:a17:903:230f:b0:2cc:89ce:2ef8 with SMTP id d9443c01a7336-2d015d983b3mr90129615ad.40.1785347360665; Wed, 29 Jul 2026 10:49:20 -0700 (PDT) Received: from mandiga ([2804:1b3:a7c0:11bd:a7a:802d:593d:3a74]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-31504cc63fesm11058104eec.15.2026.07.29.10.49.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2026 10:49:20 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 1/3] support: Add support_process_shared_robust_mutex Date: Wed, 29 Jul 2026 14:46:36 -0300 Message-ID: <20260729174915.2819065-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260729174915.2819065-1-adhemerval.zanella@linaro.org> References: <20260729174915.2819065-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Returns whether process-shared robust mutexes are supported. --- support/Makefile | 1 + support/support_mutex_robust.c | 34 ++++++++++++++++++++++++++++++++++ support/xthread.h | 3 +++ 3 files changed, 38 insertions(+) create mode 100644 support/support_mutex_robust.c diff --git a/support/Makefile b/support/Makefile index 87eeb8199f6..159b21a329f 100644 --- a/support/Makefile +++ b/support/Makefile @@ -88,6 +88,7 @@ libsupport-routines = \ support_isolate_in_subprocess \ support_mem_access \ support_mutex_pi_monotonic \ + support_mutex_robust \ support_need_proc \ support_nscd \ support_open_and_compare_file_bytes \ diff --git a/support/support_mutex_robust.c b/support/support_mutex_robust.c new file mode 100644 index 00000000000..37fd0f6ce80 --- /dev/null +++ b/support/support_mutex_robust.c @@ -0,0 +1,34 @@ +/* Returns whether process-shared robust mutexes are supported. + Copyright (C) 2026 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 + . */ + +#include +#include +#include + +bool +support_process_shared_robust_mutex (void) +{ +#ifdef __linux__ + void *head; + size_t len; + int r = syscall (__NR_get_robust_list, 0, &head, &len); + return r == 0; +#else + return true; +#endif +} diff --git a/support/xthread.h b/support/xthread.h index 3bdc6907aab..0bbaa0f074a 100644 --- a/support/xthread.h +++ b/support/xthread.h @@ -36,6 +36,9 @@ void delayed__exit (int seconds); /* Returns true if Priority Inheritance support CLOCK_MONOTONIC. */ bool support_mutex_pi_monotonic (void); +/* Returns true if process-shared robust mutexes are supported. */ +bool support_process_shared_robust_mutex (void); + /* Terminate the process (with exit status 1) if VALUE is not zero. In that case, print a failure message to standard output mentioning FUNCTION. The process is terminated with the exit function, so From patchwork Wed Jul 29 17:46:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 140183 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D1CBA4BB5921 for ; Wed, 29 Jul 2026 17:50:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D1CBA4BB5921 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=skISA8FC X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by sourceware.org (Postfix) with ESMTPS id A0F7C4BB3BC1 for ; Wed, 29 Jul 2026 17:49:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A0F7C4BB3BC1 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A0F7C4BB3BC1 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::633 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785347363; cv=none; b=EOUINTvmPFF9be7gUnQMcCqH3h79/AUQBAmaKqDx3N3mIeGZU/kV6iMxh/eqixJKU9GPfQhgp0ie5bZCLAodBg0f/YAf/mcggXXTez8dcf+aos3Xc1eV7vfqwHEpgJbdja/teyTtQc346XIGaGiNS49q7phny/Ph5caB2YI6ezw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785347363; c=relaxed/simple; bh=XxbQGWxORlEK7MZsStiggC0x30ZDoD18hDJcwFAc95w=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=xFNfN3xAo3FuhHW6bHKXBhFKJpPibD6pkeV3QiKlSSe6v3Ur2N6HQBSHC6rx65Xlsc6MKoyK3P48UDyK/AuMjXTrY+ZIrq2wUZIrf0riwkbpoSWjzg3+y8UzJsB+82rSDYLOmHhM38GPm3oKC2kwGRRBFxKinQZUMDLcpUyomL4= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=skISA8FC DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A0F7C4BB3BC1 Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-2ce7d2adef4so18851405ad.3 for ; Wed, 29 Jul 2026 10:49:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785347363; x=1785952163; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=maZ6Bel1daBdLP2hXJwJTyZWmRxy5y6hEUApLw8BDW4=; b=skISA8FCnTjnhAzy9Yw+21V+fqXUCrpHxBLOiqSlhILQq74hKkg/lWeoGGFK2S0DXz yyvNjflD+GKLL+1P7GOnrE8j4LH+qVGDExqvHYix1YFlkB6qeTbhTAHRaRGyTBakrB6I mudIpdqnjnXItY6Hmx4V/3lT1olcK3nK22GPlrxM0vOa9/xAV1n6H6ohBMc2zEgxd/CR Uxs8QLJk1SNN3EaO5JuBq1zecwQBBtF/NGz0ofzLcADyyHZnrSqeHtS2Pn58VBr5svq1 zPaK9qHhFJD8z0anluL54qECMi/q55+QgXwO5/FH5limoSsI9VTR6tzVhVotfZEhtR5p Fj9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785347363; x=1785952163; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=maZ6Bel1daBdLP2hXJwJTyZWmRxy5y6hEUApLw8BDW4=; b=kctca2bv+kNBTghKQW5aSSHlKlXGSNLhghZ0MDJmlkB42bGRlmasrn/sMbT+rfHbpA OQlOkt4UXmDl54Ecl44Pm+r1CJEct2SAUcKPSp+l3E/zyxOVfeRVKH+97SfLWTdqv0uu 1z8XtHoK8eLtTvFgW9TZG4umPjCVg7feexxqyKTi8lFuD8EWAzYYL6lbk1maNEMuhmBZ NzNXI/Fj/MdOmcTKboIxIAh6zdHtMCOwiaK7wJzWZPMMlxpW15u4MfBCu0EQubTB4jqP X+xAKmEaINXnEAHmfwtNyE7toGmV7LGFe0XdPtzAGXwKS9HnHItZPsurKXXix5mDg0Y3 jULA== X-Gm-Message-State: AOJu0YxZtP6ZQ030Vval/HGH7mDzkNKSUgSHOZUoLrK9VbLH3pU4Q9D/ EbM34w9y4Sw4PLsthJK7f53U+D3S35/P9Pq5766C/R/bHy5KShFnCA0FmJ7Nwlk/JsbPI3odgHe 1aP8f X-Gm-Gg: AR+sD11qI6kN4J0yGES2TxKYdbntGHF9UmcIOYTBqjHKgNNJcvcXgSH/nEhsHKRkdc3 DgNheDbinu9RXMxRKq1cA0a/r94T3FPUbNDBdNDpw7KbFr4Ao1AvQRquY5eL4sFe1JTcGNmO5ee 5UW5hj/2DBogM/3SmI62hboXoEjDmuD8qp/TgECbIeMcUDEFBt8nK0zDx+2snxwF7Q//74DibSY LRL9FlVcfRrvuMITmGvMT9SC+XjkS9FAHfAUZlMrqyp7HgQIJEBjSWS0VpuS2kq+AXQyT9bPVw8 7DcY1UhHpT06Zsy+0uBaNkOHc+lwTCicFuAzEoDW2UWO3Z0+rbIbaPtNPpHpRz2suG7qNdkODe6 bB+GBYmQG/OL97lKDS1tBmAbj+MHWi3wSKcA4hQfkGjjUaatVPPO/9e2Vb/Oucwx3QooNIthxqu RZvk1L+N1FiRBcar82KCDnNhvcvOHDgifmyb0dYqk5x9z2AOZaFgmAoUa/f6okHMmSRRTa1g== X-Received: by 2002:a05:6a21:6cc4:b0:3bf:6c08:2844 with SMTP id adf61e73a8af0-3c8ba61303cmr9434207637.51.1785347362233; Wed, 29 Jul 2026 10:49:22 -0700 (PDT) Received: from mandiga ([2804:1b3:a7c0:11bd:a7a:802d:593d:3a74]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-31504cc63fesm11058104eec.15.2026.07.29.10.49.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2026 10:49:21 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 2/3] nptl: Do not always assume set_robust_list availability (BZ 33225) Date: Wed, 29 Jul 2026 14:46:37 -0300 Message-ID: <20260729174915.2819065-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260729174915.2819065-1-adhemerval.zanella@linaro.org> References: <20260729174915.2819065-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org The __ASSUME_SET_ROBUST_LIST macro gates the definition of __nptl_set_robust_list_avail, which advertises process-shared robust mutex support and is set by __tls_init_tp if the initial set_robust_list call succeeds. Some kernel configurations, and qemu-user (for all ABIs), do not implement set_robust_list. With __ASSUME_SET_ROBUST_LIST defined the missing support is not detected, and pthread_mutex_init succeeds where it should fail. For instance, the sequence below returns 0 on qemu-user even though 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); Remove __ASSUME_SET_ROBUST_LIST and always rely on the runtime __nptl_set_robust_list_avail detection. The userspace robust list cleanup in start_thread is now built for all targets, so it also needs a fix: it assumed that a target without set_robust_list also lacks priority-inheritance futexes, and dereferenced the list entries directly. qemu-user implements the PI futex operations while returning ENOSYS for set_robust_list, and bit 0 of an entry is set for PI mutexes. Checked on x86_64-linux-gnu, and on x86_64-linux-gnu under qemu-user where set_robust_list returns ENOSYS. --- nptl/Makefile | 1 + nptl/pthread_create.c | 57 +++++++++++------ nptl/pthread_mutex_init.c | 3 - nptl/tst-mutexpi10.c | 7 ++- nptl/tst-robust-fork.c | 21 +++++++ nptl/tst-robust-pshared.c | 63 +++++++++++++++++++ sysdeps/nptl/dl-tls_init_tp.c | 8 +-- sysdeps/nptl/pthreadP.h | 2 - sysdeps/pthread/tst-robust8.c | 6 ++ 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 -- 16 files changed, 135 insertions(+), 70 deletions(-) create mode 100644 nptl/tst-robust-pshared.c diff --git a/nptl/Makefile b/nptl/Makefile index 97a0fb7f658..01aa3619932 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -326,6 +326,7 @@ tests = \ tst-pthread_exit-nothreads-static \ tst-pthread_gettid_np \ tst-robust-fork \ + tst-robust-pshared \ tst-robustpi1 \ tst-robustpi2 \ tst-robustpi3 \ diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index fcb06c68c71..f8220c22208 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -333,6 +333,21 @@ static int create_thread (struct pthread *pd, const struct pthread_attr *attr, return 0; } +/* Bit 0 of a robust list entry marks a priority-inheritance mutex, so it has + to be masked off before ENTRY is dereferenced. */ +static inline void * +robust_list_entry (void *entry) +{ + return (void *) ((uintptr_t) entry & ~1ul); +} + +/* Return true if ENTRY refers to a mutex on the robust list within HEAD. */ +static inline bool +robust_list_has_entry (void *entry, void *head) +{ + return robust_list_entry (entry) != head; +} + /* Local function to start thread and handle cleanup. */ static int _Noreturn start_thread (void *arg) @@ -386,9 +401,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. */ @@ -536,38 +549,42 @@ 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 +#if __PTHREAD_MUTEX_HAVE_PREV void *robust = pd->robust_head.list; -# else +#else __pthread_slist_t *robust = pd->robust_list.__next; -# endif - /* We let the kernel do the notification if it is able to do so. - If we have to do it here there for sure are no PI mutexes involved - since the kernel support for them is even more recent. */ +#endif + /* We let the kernel do the notification if it is able to do so. */ if (!__nptl_set_robust_list_avail - && __builtin_expect (robust != (void *) &pd->robust_head, 0)) + && __glibc_unlikely (robust_list_has_entry (robust, &pd->robust_head))) { do { + void *entry = robust_list_entry (robust); + bool is_pi = ((uintptr_t) robust & 1) != 0; struct __pthread_mutex_s *this = (struct __pthread_mutex_s *) - ((char *) robust - offsetof (struct __pthread_mutex_s, - __list.__next)); - robust = *((void **) robust); + ((char *) entry - offsetof (struct __pthread_mutex_s, + __list.__next)); + robust = *((void **) entry); -# if __PTHREAD_MUTEX_HAVE_PREV +#if __PTHREAD_MUTEX_HAVE_PREV this->__list.__prev = NULL; -# endif +#endif this->__list.__next = NULL; - atomic_fetch_or_acquire (&this->__lock, FUTEX_OWNER_DIED); - futex_wake ((unsigned int *) &this->__lock, 1, - /* XYZ */ FUTEX_SHARED); + /* PI mutexes are handled by the kernel even without the robust + list, FUTEX_LOCK_PI reports EOWNERDEAD once the recorded owner + is gone, and a plain FUTEX_WAKE on a PI futex is invalid. */ + if (!is_pi) + { + atomic_fetch_or_acquire (&this->__lock, FUTEX_OWNER_DIED); + futex_wake ((unsigned int *) &this->__lock, 1, + /* XYZ */ FUTEX_SHARED); + } } - while (robust != (void *) &pd->robust_head); + while (robust_list_has_entry (robust, &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 8a5450bcb08..9be08332f1f 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 3978fb25fdf..c7db0ba1be8 100644 --- a/nptl/tst-mutexpi10.c +++ b/nptl/tst-mutexpi10.c @@ -58,7 +58,12 @@ do_test (void) xpthread_mutexattr_setrobust (&attr, robust[r]); pthread_mutex_t mtx; - xpthread_mutex_init (&mtx, &attr); + /* ENOTSUP is returned if the kernel does not support priority + inheritance futexes, in which case there is nothing to check. */ + int ret = pthread_mutex_init (&mtx, &attr); + if (ret == ENOTSUP) + continue; + TEST_COMPARE (ret, 0); /* 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 be9c6d3cc41..6e235bbd979 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_process_shared_robust_mutex (); + 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 (!robust_support + && (is_robust_pshared (parent_bits) + || is_robust_pshared (child_bits) + || is_robust_pshared (nonshared_bits))) + { + if (test_verbose) + printf ("info: skipping test due to missing" + " process-shared robust mutex support\n"); + continue; + } one_test (parent_bits, child_bits, nonshared_bits, lock_nonshared, lock_child); } diff --git a/nptl/tst-robust-pshared.c b/nptl/tst-robust-pshared.c new file mode 100644 index 00000000000..3edbabadf91 --- /dev/null +++ b/nptl/tst-robust-pshared.c @@ -0,0 +1,63 @@ +/* Check that process-shared robust mutex creation follows kernel + support (BZ #33225). + Copyright (C) 2026 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 + . */ + +#include +#include +#include + +#include +#include + +static int +do_test (void) +{ + bool robust_support = support_process_shared_robust_mutex (); + + for (int pshared = 0; pshared < 2; pshared++) + for (int robust = 0; robust < 2; robust++) + { + pthread_mutexattr_t attr; + xpthread_mutexattr_init (&attr); + if (pshared) + xpthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED); + if (robust) + xpthread_mutexattr_setrobust (&attr, PTHREAD_MUTEX_ROBUST); + + /* Only process-shared robust mutexes require the kernel to walk the + robust list on process exit, robust mutexes private to the process + are handled by pthread_create itself. Non-robust mutexes do not + need the robust list at all. */ + int expected = pshared && robust && !robust_support ? ENOTSUP : 0; + + pthread_mutex_t mtx; + TEST_COMPARE (pthread_mutex_init (&mtx, &attr), expected); + if (expected == 0) + { + TEST_COMPARE (pthread_mutex_lock (&mtx), 0); + TEST_COMPARE (pthread_mutex_unlock (&mtx), 0); + xpthread_mutex_destroy (&mtx); + } + + xpthread_mutexattr_destroy (&attr); + } + + return 0; +} + +#include diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c index 72cc4087c91..75e3712a6d8 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 -#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) @@ -95,11 +93,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 de432d40324..c62c8982905 100644 --- a/sysdeps/nptl/pthreadP.h +++ b/sysdeps/nptl/pthreadP.h @@ -192,12 +192,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-robust8.c b/sysdeps/pthread/tst-robust8.c index 65f37feddfa..3b3ca161905 100644 --- a/sysdeps/pthread/tst-robust8.c +++ b/sysdeps/pthread/tst-robust8.c @@ -10,6 +10,8 @@ #include +#include +#include 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_process_shared_robust_mutex ()) + FAIL_UNSUPPORTED ("process-shared robust mutexes not supported"); + if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0) { puts ("cannot size new file"); diff --git a/sysdeps/unix/sysv/linux/arm/kernel-features.h b/sysdeps/unix/sysv/linux/arm/kernel-features.h index d169bf58946..1511de1c843 100644 --- a/sysdeps/unix/sysv/linux/arm/kernel-features.h +++ b/sysdeps/unix/sysv/linux/arm/kernel-features.h @@ -20,13 +20,6 @@ #include #include_next -/* 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 1b46336e4a0..45ef64bb1f9 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 85f6e888dba..33f3c2d2c58 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 d66fe16fa8d..db90d8a8c07 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 7790f0d14b5..0d30d4d8284 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 -/* 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 32087c0602c..9172373e989 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 eb293411135..dad512cec35 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 -/* 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. From patchwork Wed Jul 29 17:46:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 140185 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BD8184BB58AD for ; Wed, 29 Jul 2026 17:51:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BD8184BB58AD Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=dpcC5w1V X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pg1-x52a.google.com (mail-pg1-x52a.google.com [IPv6:2607:f8b0:4864:20::52a]) by sourceware.org (Postfix) with ESMTPS id 85EFB4BB5899 for ; Wed, 29 Jul 2026 17:49:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 85EFB4BB5899 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 85EFB4BB5899 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785347365; cv=none; b=KgAzgvWfVB5JmSrIvOX6lrIP9Vm0G/6pmvpwL+45SG672StmSE027sRiKeTm4FhcEK3ZyAwm3o7TFTCGWFcx59g+VVuooQdGmO4vQ4Ko4T+uqpfSwNvxbwRI2atlsTgxOhXQF485SxJypIpvkKXRhLpU4YVTWMBiKJQRDqg4cgc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785347365; c=relaxed/simple; bh=AsjtKgND7CYRZVdmfBdUm+OeoI2HfVtXGp6iJVEtr+o=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=P4PD68z3HTtnfAhR1f90QFTfrlBdidaWk1vQTo7hmuqkStWm5TPCGy0ATXNeySZb1jQBy1UjQFp9aql0vy/TPzEI/I3YNTD2V+xSsLh4u53sXKficDFAxaeZdtaj9BIBqZhsevxKEHJCRfbGhx2qs1btmJOSyI9sKB5oj1SnSNY= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=dpcC5w1V DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 85EFB4BB5899 Received: by mail-pg1-x52a.google.com with SMTP id 41be03b00d2f7-ca00f126b7eso770558a12.2 for ; Wed, 29 Jul 2026 10:49:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785347364; x=1785952164; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=dViGF2LUTAWKP1DlZyUG+lbm0lTMIb4aNPgwBuZ6vIk=; b=dpcC5w1V2jFtfmu2XM015Xr3VLMmRwdbaZsYSc0LjAGDHqjusVg0SyKjaY6BMl7ZDh 0fxTY3piGbsuYx1DmsgBw5jJdqaNAqs/jGdb7wLWEXXl4FsjLOc2GYTgMY6139i7GX+x fxRrHWnDCteKheQnj2bzl8UmB0L7sr/genhJOe71lS+OYxChlm5VwgEi4+FUEWjBdJM0 A4cNt4wYWUMnPcfpkRp+lqCX641K0BLYuKrx5SnXjPHrHkS2kfgp+FniKs7eoVDSn8Fs UfxO6YGSv9RNZwOSoz/oYuKTgB98qGU7runYY3rZMMc6eaCWT1ADRa0pBWM3py7xsdti ffzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785347364; x=1785952164; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=dViGF2LUTAWKP1DlZyUG+lbm0lTMIb4aNPgwBuZ6vIk=; b=Kq2cY9yp8QIrpjsAY82ntms33wsYLZuhHMxoZbfAXq4iqy2lWO98iz++sAop1E7gPg nBBm2HYQ5e35LdjWD2E5Ym4ti4CNdJSUHxCDTkga5aBD+KEWQ39FZgGKv+ozweQNn1Tp XyzXBkNF+Li5CI5zq6Q8xeZKE1pJoqqA5GpshFBrwHOXv8ZrdHGRFbBS/cnFwBG5EXKZ aFWmJpw1/rSIzf/yUdEcWwZPmdmgf/7QxiHRYgSFExR26tPhGmc2+ZQVNY4bMTO+8neO uzUYahNy5Z+F4ym59QNOK6wgbyY3ThmVAADDG7kfr3X9D5y+zbz+zOp+yGhc0BEef+f1 Ur0Q== X-Gm-Message-State: AOJu0YxZCMgf6tHQP5B6KHbqL3nmBOaC23iHfsMYejJJAMiFo+biLpzw +3uGfitILgrsViSsHLCODF1+g4wIR2WRzUuQjaFtlSKtQjSLJMR2wsPNnSe/zQfpk1Q+gKoEI02 UGhNb X-Gm-Gg: AR+sD10eO51jW0EY4ge0DHv6fT1TXfk0SfirN2LbhrPt/8Oqj1/iWaEjM8CmAs6krPF Isj4irMbe6XXo17YE9VALQwo2gcErqzluI5QqTBam2l/Ila1Y2x7PYX/5QPuxhI8OYXj4OQveMw jcYyscmt+kT489lM62fXNWlm0ZHu64vhS6LkHpddxFR+hJgpvnFoWilKZqbpdGMx6BPAN73xpJe cuX/QBPRnZHejsqJEtmoZcbr1gLWP9kHwj1lur2MfaMnSn0WV2Ds02at6XX5EyUoQddkz+JCGPY /iG2PXr5lzYkCgan0/rcR1YVRt6qKqn8/oU6RITTg5FbZRukOeGis4QrmnnHJm8roqkdHrRm6wf /0k2/4lyjUM/AB3De5MO6KGIj9sbXi9TkJp9BZL8PrFQBd0Eowcu3Ue/PEV8U1m/Cis8mbnxFg/ sSxT2+fWcxnobhhcvJHKviqEf7DXs6NYo3ouBW5DLUPv2XhO6mmg9QegVfSASM5GCUg5L3Ewnz0 0Re3YsV X-Received: by 2002:a05:6a20:1d98:b0:3c6:566d:edf2 with SMTP id adf61e73a8af0-3c8ba5f537dmr9100028637.51.1785347363910; Wed, 29 Jul 2026 10:49:23 -0700 (PDT) Received: from mandiga ([2804:1b3:a7c0:11bd:a7a:802d:593d:3a74]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-31504cc63fesm11058104eec.15.2026.07.29.10.49.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2026 10:49:23 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 3/3] nptl: Only initialize robust list at mutex usage Date: Wed, 29 Jul 2026 14:46:38 -0300 Message-ID: <20260729174915.2819065-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260729174915.2819065-1-adhemerval.zanella@linaro.org> References: <20260729174915.2819065-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org The set_robust_list syscall is called unconditionally at process startup (__tls_init_tp) and on every thread creation (pthread_create), even in programs that never use robust mutexes. Defer the call to the first time a robust mutex is actually locked, or initialized with PTHREAD_PROCESS_SHARED. The new helper robust_list_setup() performs the registration and is called from pthread_mutex_init (for pshared+robust), pthread_mutex_lock, pthread_mutex_trylock, and pthread_mutex_timedlock. The robust_head.futex_offset field acts as the sentinel for whether the list has been registered with the kernel. _Fork re-registers the list with the kernel only when the parent had already registered it. If the parent never used robust mutexes, the first robust mutex lock in the child calls robust_list_setup() itself. The __nptl_set_robust_list_avail variable moves from ld.so to libc.so, since it no longer needs to be set during pthread startup. Checked on x86_64-linux-gnu and aarch64-linux-gnu. --- nptl/Makefile | 1 + nptl/Versions | 1 - nptl/allocatestack.c | 9 +------ nptl/descr.h | 46 ++++++++++++++++++++++++++++++++++ nptl/nptl_robust_setup.c | 38 ++++++++++++++++++++++++++++ nptl/pthread_create.c | 10 +------- nptl/pthread_mutex_init.c | 2 +- nptl/pthread_mutex_lock.c | 2 ++ nptl/pthread_mutex_timedlock.c | 2 ++ nptl/pthread_mutex_trylock.c | 2 ++ nptl/tst-robust-pshared.c | 28 +++++++++++++++++++++ sysdeps/nptl/_Fork.c | 24 +++++++++--------- sysdeps/nptl/dl-tls_init_tp.c | 17 +------------ sysdeps/nptl/pthreadP.h | 5 ---- 14 files changed, 135 insertions(+), 52 deletions(-) create mode 100644 nptl/nptl_robust_setup.c diff --git a/nptl/Makefile b/nptl/Makefile index 01aa3619932..c9987d23384 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -50,6 +50,7 @@ routines = \ nptl_deallocate_tsd \ nptl_free_tcb \ nptl_nthreads \ + nptl_robust_setup \ nptl_setxid \ nptlfreeres \ old_pthread_cond_broadcast \ diff --git a/nptl/Versions b/nptl/Versions index b813b675b91..94a567bd609 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -535,6 +535,5 @@ libpthread { ld { GLIBC_PRIVATE { __nptl_initial_report_events; - __nptl_set_robust_list_avail; } } diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index b2ecb001136..fcccc75ddb8 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -631,14 +631,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, /* The robust mutex lists also need to be initialized unconditionally because the cleanup for the previous stack owner might have happened in the kernel. */ - pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) - - offsetof (pthread_mutex_t, - __data.__list.__next)); - pd->robust_head.list_op_pending = NULL; -#if __PTHREAD_MUTEX_HAVE_PREV - pd->robust_prev = &pd->robust_head; -#endif - pd->robust_head.list = &pd->robust_head; + robust_list_init (pd); /* We place the thread descriptor at the end of the stack. */ *pdp = pd; diff --git a/nptl/descr.h b/nptl/descr.h index 627cc3980f0..da877d6b18d 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -458,6 +459,51 @@ cancel_enabled_and_canceled_and_async (int value) == (CANCELTYPE_BITMASK | CANCELED_BITMASK); } +static inline void +robust_list_init (struct pthread *pd) +{ + pd->robust_head.list_op_pending = NULL; +#if __PTHREAD_MUTEX_HAVE_PREV + pd->robust_prev = &pd->robust_head; +#endif + pd->robust_head.list = &pd->robust_head; + pd->robust_head.futex_offset = 0; +} + +/* Set if the set_robust_list system call works. It is cleared the first + time the call fails, and never set again. */ +extern int __nptl_set_robust_list_avail attribute_hidden; + +extern bool __nptl_robust_setup (struct robust_list_head *robust_head) + attribute_hidden; + +/* Register PD's robust mutex list with the kernel unless that has already + been done, and return whether the list is registered. + + robust_head.futex_offset works as the sentinel for this, where a zero + value means registration is already done for the thread (kernel requires + it to be non zero). */ +static inline bool +robust_list_setup (struct pthread *pd) +{ + /* The current thread already registered its list. */ + if (pd->robust_head.futex_offset != 0) + return true; + + /* Avoid the futex_offset dance once set_robust_list is known to fail. */ + if (!atomic_load_relaxed (&__nptl_set_robust_list_avail)) + return false; + + pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) + - offsetof (pthread_mutex_t, + __data.__list.__next)); + if (__nptl_robust_setup (&pd->robust_head)) + return true; + + pd->robust_head.futex_offset = 0; + return false; +} + /* This yields the pointer that TLS support code calls the thread pointer. */ #if TLS_TCB_AT_TP # define TLS_TPADJ(pd) (pd) diff --git a/nptl/nptl_robust_setup.c b/nptl/nptl_robust_setup.c new file mode 100644 index 00000000000..0c14432afb8 --- /dev/null +++ b/nptl/nptl_robust_setup.c @@ -0,0 +1,38 @@ +/* Linux robust mutex setup. + Copyright (C) 2026 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 + . */ + +#include +#include +#include + +int __nptl_set_robust_list_avail = 1; + +bool +__nptl_robust_setup (struct robust_list_head *robust_head) +{ + if (atomic_load_relaxed (&__nptl_set_robust_list_avail)) + { + int res = INTERNAL_SYSCALL_CALL (set_robust_list, robust_head, + sizeof (struct robust_list_head)); + if (!INTERNAL_SYSCALL_ERROR_P (res)) + return true; + + atomic_store_relaxed (&__nptl_set_robust_list_avail, 0); + } + return false; +} diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index f8220c22208..35202c0ef12 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -401,14 +401,6 @@ start_thread (void *arg) __libc_fatal ("Fatal glibc error: rseq registration failed\n"); } - if (__nptl_set_robust_list_avail) - { - /* This call should never fail because the initial call in init.c - succeeded. */ - INTERNAL_SYSCALL_CALL (set_robust_list, &pd->robust_head, - sizeof (struct robust_list_head)); - } - /* This is where the try/finally block should be created. For compilers without that support we do use setjmp. */ struct pthread_unwind_buf unwind_buf; @@ -556,7 +548,7 @@ start_thread (void *arg) __pthread_slist_t *robust = pd->robust_list.__next; #endif /* We let the kernel do the notification if it is able to do so. */ - if (!__nptl_set_robust_list_avail + if (!atomic_load_relaxed (&__nptl_set_robust_list_avail) && __glibc_unlikely (robust_list_has_entry (robust, &pd->robust_head))) { do diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c index 9be08332f1f..2f0bb84c557 100644 --- a/nptl/pthread_mutex_init.c +++ b/nptl/pthread_mutex_init.c @@ -94,7 +94,7 @@ ___pthread_mutex_init (pthread_mutex_t *mutex, if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0) { if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0 - && !__nptl_set_robust_list_avail) + && !robust_list_setup (THREAD_SELF)) return ENOTSUP; mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; } diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index a697f2b6ca8..f649036d954 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -177,6 +177,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: case PTHREAD_MUTEX_ROBUST_NORMAL_NP: case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + robust_list_setup (THREAD_SELF); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, &mutex->__data.__list.__next); /* We need to set op_pending before starting the operation. Also @@ -361,6 +362,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) if (robust) { + robust_list_setup (THREAD_SELF); /* Note: robust PI futexes are signaled by setting bit 0. */ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, (void *) (((uintptr_t) &mutex->__data.__list.__next) diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c index 9efca2c7791..a52ed795df0 100644 --- a/nptl/pthread_mutex_timedlock.c +++ b/nptl/pthread_mutex_timedlock.c @@ -111,6 +111,7 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex, case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: case PTHREAD_MUTEX_ROBUST_NORMAL_NP: case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + robust_list_setup (THREAD_SELF); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, &mutex->__data.__list.__next); /* We need to set op_pending before starting the operation. Also @@ -295,6 +296,7 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex, if (robust) { + robust_list_setup (THREAD_SELF); /* Note: robust PI futexes are signaled by setting bit 0. */ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, (void *) (((uintptr_t) &mutex->__data.__list.__next) diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c index 236b3228ddb..09c5dc983b2 100644 --- a/nptl/pthread_mutex_trylock.c +++ b/nptl/pthread_mutex_trylock.c @@ -77,6 +77,7 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex) case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: case PTHREAD_MUTEX_ROBUST_NORMAL_NP: case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + robust_list_setup (THREAD_SELF); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, &mutex->__data.__list.__next); /* We need to set op_pending before starting the operation. Also @@ -219,6 +220,7 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex) if (robust) { + robust_list_setup (THREAD_SELF); /* Note: robust PI futexes are signaled by setting bit 0. */ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, (void *) (((uintptr_t) &mutex->__data.__list.__next) diff --git a/nptl/tst-robust-pshared.c b/nptl/tst-robust-pshared.c index 3edbabadf91..01044f4e628 100644 --- a/nptl/tst-robust-pshared.c +++ b/nptl/tst-robust-pshared.c @@ -24,6 +24,16 @@ #include #include +/* Lock the mutex and exit without unlocking it, so that the owner-died + notification has to be delivered to the next locker. */ +static void * +owner_thread (void *arg) +{ + pthread_mutex_t *mutex = arg; + TEST_COMPARE (pthread_mutex_lock (mutex), 0); + return NULL; +} + static int do_test (void) { @@ -57,6 +67,24 @@ do_test (void) xpthread_mutexattr_destroy (&attr); } + /* Have a thread lock a robust mutex and exit without unlocking it. This + exercises the deferred robust_list_setup path in pthread_mutex_lock. */ + { + pthread_mutexattr_t attr; + xpthread_mutexattr_init (&attr); + xpthread_mutexattr_setrobust (&attr, PTHREAD_MUTEX_ROBUST); + pthread_mutex_t mutex; + TEST_COMPARE (pthread_mutex_init (&mutex, &attr), 0); + xpthread_mutexattr_destroy (&attr); + + xpthread_join (xpthread_create (NULL, owner_thread, &mutex)); + + TEST_COMPARE (pthread_mutex_lock (&mutex), EOWNERDEAD); + TEST_COMPARE (pthread_mutex_consistent (&mutex), 0); + TEST_COMPARE (pthread_mutex_unlock (&mutex), 0); + TEST_COMPARE (pthread_mutex_destroy (&mutex), 0); + } + return 0; } diff --git a/sysdeps/nptl/_Fork.c b/sysdeps/nptl/_Fork.c index 907b3fef876..ba6912aa346 100644 --- a/sysdeps/nptl/_Fork.c +++ b/sysdeps/nptl/_Fork.c @@ -35,22 +35,22 @@ _Fork (void) { struct pthread *self = THREAD_SELF; - /* Initialize the robust mutex list setting in the kernel which has - been reset during the fork. We do not check for errors because if - it fails here, it must have failed at process startup as well and - nobody could have used robust mutexes. - Before we do that, we have to clear the list of robust mutexes - because we do not inherit ownership of mutexes from the parent. - We do not have to set self->robust_head.futex_offset since we do - inherit the correct value from the parent. We do not need to clear - the pending operation because it must have been zero when fork was - called. */ + /* Clear the list of robust mutexes because we do not inherit ownership + of mutexes from the parent. We do not need to clear the pending + operation because it must have been zero when fork was called. + futex_offset is inherited from the parent unchanged. */ #if __PTHREAD_MUTEX_HAVE_PREV self->robust_prev = &self->robust_head; #endif self->robust_head.list = &self->robust_head; - INTERNAL_SYSCALL_CALL (set_robust_list, &self->robust_head, - sizeof (struct robust_list_head)); + /* Re-register the robust list with the kernel only if the parent had + already initialized it. futex_offset is the sentinel: zero means + lazy initialization has not happened yet, so there is nothing to + re-register and the first robust mutex lock in the child will call + set_robust_list itself. */ + if (self->robust_head.futex_offset != 0) + INTERNAL_SYSCALL_CALL (set_robust_list, &self->robust_head, + sizeof (struct robust_list_head)); call_function_static_weak (__getrandom_fork_subprocess); } diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c index 75e3712a6d8..77f2e341822 100644 --- a/sysdeps/nptl/dl-tls_init_tp.c +++ b/sysdeps/nptl/dl-tls_init_tp.c @@ -28,9 +28,6 @@ #define TUNABLE_NAMESPACE pthread #include -bool __nptl_set_robust_list_avail; -rtld_hidden_data_def (__nptl_set_robust_list_avail) - bool __nptl_initial_report_events; rtld_hidden_def (__nptl_initial_report_events) @@ -82,19 +79,7 @@ __tls_init_tp (void) THREAD_SETMEM (pd, report_events, __nptl_initial_report_events); /* Initialize the robust mutex data. */ - { -#if __PTHREAD_MUTEX_HAVE_PREV - pd->robust_prev = &pd->robust_head; -#endif - pd->robust_head.list = &pd->robust_head; - pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) - - offsetof (pthread_mutex_t, - __data.__list.__next)); - int res = INTERNAL_SYSCALL_CALL (set_robust_list, &pd->robust_head, - sizeof (struct robust_list_head)); - if (!INTERNAL_SYSCALL_ERROR_P (res)) - __nptl_set_robust_list_avail = true; - } + robust_list_init (pd); { /* If the registration fails or is disabled by tunable, the public diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h index c62c8982905..7d4dd077c74 100644 --- a/sysdeps/nptl/pthreadP.h +++ b/sysdeps/nptl/pthreadP.h @@ -192,11 +192,6 @@ libc_hidden_proto (__pthread_keys) extern unsigned int __nptl_nthreads; libc_hidden_proto (__nptl_nthreads) -/* 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) - /* Thread Priority Protection. */ extern int __sched_fifo_min_prio; libc_hidden_proto (__sched_fifo_min_prio)