get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2233154/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2233154,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2233154/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/20260505190809.3898686-4-adhemerval.zanella@linaro.org/",
    "project": {
        "id": 41,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/41/?format=api",
        "name": "GNU C Library",
        "link_name": "glibc",
        "list_id": "libc-alpha.sourceware.org",
        "list_email": "libc-alpha@sourceware.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260505190809.3898686-4-adhemerval.zanella@linaro.org>",
    "list_archive_url": null,
    "date": "2026-05-05T19:06:52",
    "name": "[v2,3/3] nptl: Only initialize robust list at mutex usage",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "52bf4a6557218aa73514edab01a909125658b617",
    "submitter": {
        "id": 66065,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/66065/?format=api",
        "name": "Adhemerval Zanella Netto",
        "email": "adhemerval.zanella@linaro.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/20260505190809.3898686-4-adhemerval.zanella@linaro.org/mbox/",
    "series": [
        {
            "id": 502884,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/502884/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=502884",
            "date": "2026-05-05T19:06:49",
            "name": "nptl: Fix robust mutex support detection and defer robust list initialization",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/502884/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2233154/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2233154/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=AMFu/y49;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=AMFu/y49",
            "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=linaro.org",
            "sourceware.org; spf=pass smtp.mailfrom=linaro.org",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=2607:f8b0:4864:20::e2b"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g97Nc0QCjz1yJx\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 06 May 2026 05:08:59 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 27FF84BAD142\n\tfor <incoming@patchwork.ozlabs.org>; Tue,  5 May 2026 19:08:58 +0000 (GMT)",
            "from mail-vs1-xe2b.google.com (mail-vs1-xe2b.google.com\n [IPv6:2607:f8b0:4864:20::e2b])\n by sourceware.org (Postfix) with ESMTPS id 5E9E74BA79A2\n for <libc-alpha@sourceware.org>; Tue,  5 May 2026 19:08:26 +0000 (GMT)",
            "by mail-vs1-xe2b.google.com with SMTP id\n ada2fe7eead31-62f390b8df7so1606684137.1\n for <libc-alpha@sourceware.org>; Tue, 05 May 2026 12:08:26 -0700 (PDT)",
            "from mandiga.. ([2804:1b3:a7c1:364:abee:44ff:b045:5a7])\n by smtp.gmail.com with ESMTPSA id\n a1e0cc1a2514c-95ce08f4a7asm7504046241.5.2026.05.05.12.08.22\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 05 May 2026 12:08:23 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 27FF84BAD142",
            "OpenDKIM Filter v2.11.0 sourceware.org 5E9E74BA79A2"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 5E9E74BA79A2",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 5E9E74BA79A2",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1778008106; cv=none;\n b=dVJYK8BKXSkPK4kyQb0jnarin35M0V6cKwpFmsBdsTgrWhwhDnlape9LCqdCezbauGgwj9A1sAE3p3X73QOAhzo6OQbwYodUZLygwrG5I1AeTd5UW6rlqWZgcl2z9YOPbegnuMGKAKB3d19mRLmrYhZkxJMWJ+tn+xZCN99zI+4=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1778008106; c=relaxed/simple;\n bh=L3pZ5rrC4x2yTQdRKpOevEtZJizWu1R5GAEmoIUUrFo=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=FTR99biuxUvJ/NtiCe0L2zitXtKzC8nloRIpOkxHxyR4af3pT5a6+McCC1D/h0LhC7f0u56DHM+LGFpF4aJYruUriCSzwms/H1Xlwp7O9JZKjjkzXF51JZhuu7g+zKuWQvcIsAhudjT768q5l1BU1HQMWjPHaQ2a99HO6F36Xc8=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1778008105; x=1778612905; darn=sourceware.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=jxFmbu9+XBXAKdKF0W4t5VOJl29THVzXXkcLcNbj4Ss=;\n b=AMFu/y49PzX1z6nfB0l9IE/2A1aAOeRDyV7pz3vReF0/0DyjDUIzgOUPohw8DYvPBL\n mqdgEf0DQN1kteKhUTE/kaoDYYJSAkyGBBK3GTxXqbNhNvcNAGhwiNHBQNZgvTJcpJKM\n RmeY0JF3GlAvnF8FpPgZ45oS4e31kGmqlDtX+MTVZn6q5E+EgI9vqkcAczKGPGjF22SI\n T8Zi9+pjmc4/g+cTUJ9UiSb8+xeMVufPBGLEE9UmVaZQanTAxQA/k2eV6K2wpWlXUAYg\n klRvp9DO4b/IPlveJxzb79Jka2uTQq41a/9Dn9rAg5FF7QtIz7AGMMt5dG1LsT4MqIhq\n FWdw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1778008105; x=1778612905;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=jxFmbu9+XBXAKdKF0W4t5VOJl29THVzXXkcLcNbj4Ss=;\n b=s9/rG3HV4P1l1k3pwzdQjOV/9+ZLybuz8iWJoc/rLRLzIJN7adLzQ6Q9XzutjcMvX2\n vRiwKoAFGhhlGzBF3qz0gQI7FWc7JecFX1ZZ6tgEaMoxnBHhJTlm/549UPrtZsD9XCJR\n yq+tS5JV4BJabVuw8I2OciJwyn1ipTJmSyDEHV80sEsO3eBdt9Zrof15IiZbwt8IoT+N\n nnXehISBFsrn6/aYQ+fo9OlB7y91Y2twLSSeD4oDPVgBabg4Vc9Xi6YMwF9u22gjsCTw\n IS33ulvhLeYwwtYPCQAW+GH68SZhPyweYb5w7OZYiQ6gk1agQZPjjn/MwH/Tk2tI5Ez5\n xwXg==",
        "X-Gm-Message-State": "AOJu0Yw6xPaXNtiMlREfhD6FANXVTnb7KKSTpQrUyC14mhHRJIhkdcQ/\n NN5RAy+utO+cSJRMKtFMCmRAcmcLsSobAx08zH7KIF22gETv0cIBcS2Di+XHGL60ZFZV1dT4cMA\n DAGEc",
        "X-Gm-Gg": "AeBDieseoYIbU1romLIXF+HLbw/G4iBsMnIWGCKlg/EsHeiEACSXnAd0f7Q7hfj2bnV\n e7Olw8bItrzFd9GWtBQi0DOM6gmxvNIH2gr0fXY7/TdJqYfOktL4zg2ASSaFArit+3sxKX31uyh\n xr2MfM7kj4xJGZQ9P6B/css43Ld43zaMQYhlUb1tPSoJ1X/ugpCP79Kzv60PH9L0R0/ZF/Cyc9K\n Ywg4mKtvW967O/vWATeVx0ne+sF3gGtESiQ4LEFGC1zP3jGBaE3qLwngJVTxchdrXNqBXhtnaW6\n isZWqkBFZB1DtIcre9WoNm5T6WX6BoXl/z0ghxjI/K9DaCDDG9qA8MugVvHxqVOCGVeMhWoupeq\n 9K+BAOx9bcP115tseE4iqJyW9RDdVjCzhLEpHz9j0Kk8JhoVAh3ieVN52vQw5UFSgbdST7WDh3T\n AQ1sG31ZD/jPsiHPrnj+zVLeHYDSKlAfp8MmYozPNP8Ac=",
        "X-Received": "by 2002:a05:6102:802a:b0:618:3503:5659 with SMTP id\n ada2fe7eead31-62f591dbcfemr3622245137.14.1778008104395;\n Tue, 05 May 2026 12:08:24 -0700 (PDT)",
        "From": "Adhemerval Zanella <adhemerval.zanella@linaro.org>",
        "To": "libc-alpha@sourceware.org",
        "Cc": "Florian Weimer <fweimer@redhat.com>",
        "Subject": "[PATCH v2 3/3] nptl: Only initialize robust list at mutex usage",
        "Date": "Tue,  5 May 2026 16:06:52 -0300",
        "Message-ID": "<20260505190809.3898686-4-adhemerval.zanella@linaro.org>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260505190809.3898686-1-adhemerval.zanella@linaro.org>",
        "References": "<20260505190809.3898686-1-adhemerval.zanella@linaro.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "libc-alpha@sourceware.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Libc-alpha mailing list <libc-alpha.sourceware.org>",
        "List-Unsubscribe": "<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>",
        "List-Archive": "<https://sourceware.org/pipermail/libc-alpha/>",
        "List-Post": "<mailto:libc-alpha@sourceware.org>",
        "List-Help": "<mailto:libc-alpha-request@sourceware.org?subject=help>",
        "List-Subscribe": "<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>",
        "Errors-To": "libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"
    },
    "content": "The set_robust_list syscall is currently called unconditionally at\nprocess startup (__tls_init_tp) and on every thread creation\n(pthread_create), even in programs that never use robust mutexes.\n\nThis patch defers the call to the first time a robust mutex is actually\nlocked or initialized with PTHREAD_PROCESS_SHARED.  The new helper\nrobust_list_setup() performs the deferred registration and is called\nfrom pthread_mutex_init (for pshared+robust), pthread_mutex_lock,\npthread_mutex_trylock, and pthread_mutex_timedlock.\n\nThe field robust_head.futex_offset serves as a sentinel: zero means the\nlist has not been registered with the kernel; non-zero means it has.\nrobust_list_setup() sets futex_offset to its correct value before\ncalling set_robust_list, so the kernel always reads a valid offset when\nit walks the list on thread death.  On syscall failure futex_offset is\nreset to zero.\n\n_Fork is updated to re-register the list with the kernel only when the\nparent had already initialized it (futex_offset != 0).  If the parent\nnever used robust mutexes, the child's first robust mutex lock calls\nrobust_list_setup() itself.\n\nThe __nptl_set_robust_list_avail variable moves from ld.so to libc.so,\nsince it no longer needs to be set during pthread startup.\n\nChecked on x86_64-linux-gnu and aarch64-linux-gnu.\n---\n nptl/Makefile                  |  2 +\n nptl/Versions                  |  1 -\n nptl/allocatestack.c           |  9 +---\n nptl/descr.h                   | 31 ++++++++++++\n nptl/nptl_robust_setup.c       | 38 +++++++++++++++\n nptl/pthread_create.c          |  8 ---\n nptl/pthread_mutex_init.c      |  2 +-\n nptl/pthread_mutex_lock.c      |  2 +\n nptl/pthread_mutex_timedlock.c |  2 +\n nptl/pthread_mutex_trylock.c   |  2 +\n nptl/tst-robust-pshared.c      | 89 ++++++++++++++++++++++++++++++++++\n sysdeps/nptl/_Fork.c           | 24 ++++-----\n sysdeps/nptl/dl-tls_init_tp.c  | 17 +------\n sysdeps/nptl/pthreadP.h        |  6 +--\n 14 files changed, 183 insertions(+), 50 deletions(-)\n create mode 100644 nptl/nptl_robust_setup.c\n create mode 100644 nptl/tst-robust-pshared.c",
    "diff": "diff --git a/nptl/Makefile b/nptl/Makefile\nindex 02862d1c04b..c9c7fc00f55 100644\n--- a/nptl/Makefile\n+++ b/nptl/Makefile\n@@ -50,6 +50,7 @@ routines = \\\n   nptl_deallocate_tsd \\\n   nptl_free_tcb \\\n   nptl_nthreads \\\n+  nptl_robust_setup \\\n   nptl_setxid \\\n   nptlfreeres \\\n   old_pthread_cond_broadcast \\\n@@ -326,6 +327,7 @@ tests = \\\n   tst-pthread_exit-nothreads-static \\\n   tst-pthread_gettid_np \\\n   tst-robust-fork \\\n+  tst-robust-pshared \\\n   tst-robustpi1 \\\n   tst-robustpi2 \\\n   tst-robustpi3 \\\ndiff --git a/nptl/Versions b/nptl/Versions\nindex b813b675b91..94a567bd609 100644\n--- a/nptl/Versions\n+++ b/nptl/Versions\n@@ -535,6 +535,5 @@ libpthread {\n ld {\n   GLIBC_PRIVATE {\n      __nptl_initial_report_events;\n-     __nptl_set_robust_list_avail;\n   }\n }\ndiff --git a/nptl/allocatestack.c b/nptl/allocatestack.c\nindex b2ecb001136..fcccc75ddb8 100644\n--- a/nptl/allocatestack.c\n+++ b/nptl/allocatestack.c\n@@ -631,14 +631,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,\n   /* The robust mutex lists also need to be initialized\n      unconditionally because the cleanup for the previous stack owner\n      might have happened in the kernel.  */\n-  pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock)\n-\t\t\t\t  - offsetof (pthread_mutex_t,\n-\t\t\t\t\t      __data.__list.__next));\n-  pd->robust_head.list_op_pending = NULL;\n-#if __PTHREAD_MUTEX_HAVE_PREV\n-  pd->robust_prev = &pd->robust_head;\n-#endif\n-  pd->robust_head.list = &pd->robust_head;\n+  robust_list_init (pd);\n \n   /* We place the thread descriptor at the end of the stack.  */\n   *pdp = pd;\ndiff --git a/nptl/descr.h b/nptl/descr.h\nindex 627cc3980f0..308100c0c30 100644\n--- a/nptl/descr.h\n+++ b/nptl/descr.h\n@@ -458,6 +458,37 @@ cancel_enabled_and_canceled_and_async (int value)\n     == (CANCELTYPE_BITMASK | CANCELED_BITMASK);\n }\n \n+static inline void\n+robust_list_init (struct pthread *pd)\n+{\n+  pd->robust_head.list_op_pending = NULL;\n+#if __PTHREAD_MUTEX_HAVE_PREV\n+  pd->robust_prev = &pd->robust_head;\n+#endif\n+  pd->robust_head.list = &pd->robust_head;\n+  pd->robust_head.futex_offset = 0;\n+}\n+\n+extern bool __nptl_robust_setup (struct robust_list_head *robust_head)\n+     attribute_hidden;\n+\n+static inline bool\n+robust_list_setup (struct pthread *pd)\n+{\n+  /* The current thread was already initialized.  */\n+  if (pd->robust_head.futex_offset != 0)\n+    return true;\n+\n+  pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock)\n+\t\t\t\t  - offsetof (pthread_mutex_t,\n+\t\t\t\t\t      __data.__list.__next));\n+  if (__nptl_robust_setup (&pd->robust_head))\n+    return true;\n+\n+  pd->robust_head.futex_offset = 0;\n+  return false;\n+}\n+\n /* This yields the pointer that TLS support code calls the thread pointer.  */\n #if TLS_TCB_AT_TP\n # define TLS_TPADJ(pd) (pd)\ndiff --git a/nptl/nptl_robust_setup.c b/nptl/nptl_robust_setup.c\nnew file mode 100644\nindex 00000000000..0b95de22009\n--- /dev/null\n+++ b/nptl/nptl_robust_setup.c\n@@ -0,0 +1,38 @@\n+/* Linux robust mutex setup.\n+   Copyright (C) 2025 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <https://www.gnu.org/licenses/>.  */\n+\n+#include <descr.h>\n+#include <atomic.h>\n+#include <pthreadP.h>\n+\n+int __nptl_set_robust_list_avail = 1;\n+\n+bool\n+__nptl_robust_setup (struct robust_list_head *robust_head)\n+{\n+  if (atomic_load_relaxed (&__nptl_set_robust_list_avail))\n+    {\n+      int res = INTERNAL_SYSCALL_CALL (set_robust_list, robust_head,\n+\t\t\t\t       sizeof (struct robust_list_head));\n+      if (!INTERNAL_SYSCALL_ERROR_P (res))\n+        return true;\n+\n+      atomic_store_relaxed (&__nptl_set_robust_list_avail, 0);\n+    }\n+  return false;\n+}\ndiff --git a/nptl/pthread_create.c b/nptl/pthread_create.c\nindex 72f77d1914e..d7aed06efda 100644\n--- a/nptl/pthread_create.c\n+++ b/nptl/pthread_create.c\n@@ -386,14 +386,6 @@ start_thread (void *arg)\n       __libc_fatal (\"Fatal glibc error: rseq registration failed\\n\");\n   }\n \n-  if (__nptl_set_robust_list_avail)\n-    {\n-      /* This call should never fail because the initial call in init.c\n-\t succeeded.  */\n-      INTERNAL_SYSCALL_CALL (set_robust_list, &pd->robust_head,\n-\t\t\t     sizeof (struct robust_list_head));\n-    }\n-\n   /* This is where the try/finally block should be created.  For\n      compilers without that support we do use setjmp.  */\n   struct pthread_unwind_buf unwind_buf;\ndiff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c\nindex 9be08332f1f..2f0bb84c557 100644\n--- a/nptl/pthread_mutex_init.c\n+++ b/nptl/pthread_mutex_init.c\n@@ -94,7 +94,7 @@ ___pthread_mutex_init (pthread_mutex_t *mutex,\n   if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)\n     {\n       if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0\n-\t  && !__nptl_set_robust_list_avail)\n+\t  && !robust_list_setup (THREAD_SELF))\n \treturn ENOTSUP;\n       mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;\n     }\ndiff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c\nindex a697f2b6ca8..f649036d954 100644\n--- a/nptl/pthread_mutex_lock.c\n+++ b/nptl/pthread_mutex_lock.c\n@@ -177,6 +177,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)\n     case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:\n     case PTHREAD_MUTEX_ROBUST_NORMAL_NP:\n     case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:\n+      robust_list_setup (THREAD_SELF);\n       THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,\n \t\t     &mutex->__data.__list.__next);\n       /* We need to set op_pending before starting the operation.  Also\n@@ -361,6 +362,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)\n \n \tif (robust)\n \t  {\n+\t    robust_list_setup (THREAD_SELF);\n \t    /* Note: robust PI futexes are signaled by setting bit 0.  */\n \t    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,\n \t\t\t   (void *) (((uintptr_t) &mutex->__data.__list.__next)\ndiff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c\nindex 9efca2c7791..a52ed795df0 100644\n--- a/nptl/pthread_mutex_timedlock.c\n+++ b/nptl/pthread_mutex_timedlock.c\n@@ -111,6 +111,7 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,\n     case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:\n     case PTHREAD_MUTEX_ROBUST_NORMAL_NP:\n     case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:\n+      robust_list_setup (THREAD_SELF);\n       THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,\n \t\t     &mutex->__data.__list.__next);\n       /* We need to set op_pending before starting the operation.  Also\n@@ -295,6 +296,7 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,\n \n \tif (robust)\n \t  {\n+\t    robust_list_setup (THREAD_SELF);\n \t    /* Note: robust PI futexes are signaled by setting bit 0.  */\n \t    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,\n \t\t\t   (void *) (((uintptr_t) &mutex->__data.__list.__next)\ndiff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c\nindex 236b3228ddb..09c5dc983b2 100644\n--- a/nptl/pthread_mutex_trylock.c\n+++ b/nptl/pthread_mutex_trylock.c\n@@ -77,6 +77,7 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)\n     case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:\n     case PTHREAD_MUTEX_ROBUST_NORMAL_NP:\n     case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:\n+      robust_list_setup (THREAD_SELF);\n       THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,\n \t\t     &mutex->__data.__list.__next);\n       /* We need to set op_pending before starting the operation.  Also\n@@ -219,6 +220,7 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)\n \n \tif (robust)\n \t  {\n+\t    robust_list_setup (THREAD_SELF);\n \t    /* Note: robust PI futexes are signaled by setting bit 0.  */\n \t    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,\n \t\t\t   (void *) (((uintptr_t) &mutex->__data.__list.__next)\ndiff --git a/nptl/tst-robust-pshared.c b/nptl/tst-robust-pshared.c\nnew file mode 100644\nindex 00000000000..4074ffa494b\n--- /dev/null\n+++ b/nptl/tst-robust-pshared.c\n@@ -0,0 +1,89 @@\n+/* Test process-shared robust mutex support and lazy initialization (BZ 33225).\n+   Copyright (C) 2025 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <https://www.gnu.org/licenses/>.  */\n+\n+/* Verify that pthread_mutex_init returns ENOTSUP for a process-shared robust\n+   mutex when the set_robust_list syscall is not available (e.g., qemu-user),\n+   and that the lazy robust list initialization works correctly when the\n+   syscall is available.  */\n+\n+#include <errno.h>\n+#include <pthread.h>\n+#include <stdbool.h>\n+#include <stdio.h>\n+#include <support/check.h>\n+#include <support/test-driver.h>\n+#include <support/xthread.h>\n+\n+/* Lock the mutex and exit without unlocking to trigger EOWNERDEAD.  */\n+static void *\n+owner_thread (void *arg)\n+{\n+  pthread_mutex_t *mutex = arg;\n+  TEST_COMPARE (pthread_mutex_lock (mutex), 0);\n+  /* Thread exits here without unlocking.  The kernel walks the robust\n+     list registered via set_robust_list and marks the mutex owner-dead.\n+     This verifies that lazy robust_list_setup correctly set futex_offset\n+     and called set_robust_list before the first lock.  */\n+  return NULL;\n+}\n+\n+static int\n+do_test (void)\n+{\n+  bool robust_support = support_process_shared_robust_mutex ();\n+  if (test_verbose)\n+    printf (\"info: process-shared robust mutex support: %d\\n\", robust_support);\n+\n+  pthread_mutexattr_t attr;\n+  TEST_COMPARE (pthread_mutexattr_init (&attr), 0);\n+  TEST_COMPARE (pthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED),\n+\t\t0);\n+  TEST_COMPARE (pthread_mutexattr_setrobust (&attr, PTHREAD_MUTEX_ROBUST), 0);\n+\n+  pthread_mutex_t mutex;\n+  int ret = pthread_mutex_init (&mutex, &attr);\n+  TEST_COMPARE (pthread_mutexattr_destroy (&attr), 0);\n+\n+  if (!robust_support)\n+    {\n+      /* When set_robust_list is unavailable, pshared+robust mutex init\n+\t must fail with ENOTSUP rather than silently succeeding.  */\n+      TEST_COMPARE (ret, ENOTSUP);\n+      return 0;\n+    }\n+\n+  TEST_COMPARE (ret, 0);\n+\n+  /* Have a thread lock the mutex and exit without unlocking.\n+     This exercises the lazy robust_list_setup path in\n+     pthread_mutex_lock: futex_offset must be set before set_robust_list\n+     is called so the kernel can correctly compute the lock address on\n+     thread death.  */\n+  pthread_t thread;\n+  TEST_COMPARE (pthread_create (&thread, NULL, owner_thread, &mutex), 0);\n+  TEST_COMPARE (pthread_join (thread, NULL), 0);\n+\n+  TEST_COMPARE (pthread_mutex_lock (&mutex), EOWNERDEAD);\n+  TEST_COMPARE (pthread_mutex_consistent (&mutex), 0);\n+  TEST_COMPARE (pthread_mutex_unlock (&mutex), 0);\n+  TEST_COMPARE (pthread_mutex_destroy (&mutex), 0);\n+\n+  return 0;\n+}\n+\n+#include <support/test-driver.c>\ndiff --git a/sysdeps/nptl/_Fork.c b/sysdeps/nptl/_Fork.c\nindex 907b3fef876..ba6912aa346 100644\n--- a/sysdeps/nptl/_Fork.c\n+++ b/sysdeps/nptl/_Fork.c\n@@ -35,22 +35,22 @@ _Fork (void)\n     {\n       struct pthread *self = THREAD_SELF;\n \n-      /* Initialize the robust mutex list setting in the kernel which has\n-\t been reset during the fork.  We do not check for errors because if\n-\t it fails here, it must have failed at process startup as well and\n-\t nobody could have used robust mutexes.\n-\t Before we do that, we have to clear the list of robust mutexes\n-\t because we do not inherit ownership of mutexes from the parent.\n-\t We do not have to set self->robust_head.futex_offset since we do\n-\t inherit the correct value from the parent.  We do not need to clear\n-\t the pending operation because it must have been zero when fork was\n-\t called.  */\n+      /* Clear the list of robust mutexes because we do not inherit ownership\n+\t of mutexes from the parent.  We do not need to clear the pending\n+\t operation because it must have been zero when fork was called.\n+\t futex_offset is inherited from the parent unchanged.  */\n #if __PTHREAD_MUTEX_HAVE_PREV\n       self->robust_prev = &self->robust_head;\n #endif\n       self->robust_head.list = &self->robust_head;\n-      INTERNAL_SYSCALL_CALL (set_robust_list, &self->robust_head,\n-\t\t\t     sizeof (struct robust_list_head));\n+      /* Re-register the robust list with the kernel only if the parent had\n+\t already initialized it.  futex_offset is the sentinel: zero means\n+\t lazy initialization has not happened yet, so there is nothing to\n+\t re-register and the first robust mutex lock in the child will call\n+\t set_robust_list itself.  */\n+      if (self->robust_head.futex_offset != 0)\n+\tINTERNAL_SYSCALL_CALL (set_robust_list, &self->robust_head,\n+\t\t\t       sizeof (struct robust_list_head));\n       call_function_static_weak (__getrandom_fork_subprocess);\n     }\n \ndiff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c\nindex 75e3712a6d8..77f2e341822 100644\n--- a/sysdeps/nptl/dl-tls_init_tp.c\n+++ b/sysdeps/nptl/dl-tls_init_tp.c\n@@ -28,9 +28,6 @@\n #define TUNABLE_NAMESPACE pthread\n #include <dl-tunables.h>\n \n-bool __nptl_set_robust_list_avail;\n-rtld_hidden_data_def (__nptl_set_robust_list_avail)\n-\n bool __nptl_initial_report_events;\n rtld_hidden_def (__nptl_initial_report_events)\n \n@@ -82,19 +79,7 @@ __tls_init_tp (void)\n   THREAD_SETMEM (pd, report_events, __nptl_initial_report_events);\n \n   /* Initialize the robust mutex data.  */\n-  {\n-#if __PTHREAD_MUTEX_HAVE_PREV\n-    pd->robust_prev = &pd->robust_head;\n-#endif\n-    pd->robust_head.list = &pd->robust_head;\n-    pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock)\n-                                    - offsetof (pthread_mutex_t,\n-                                                __data.__list.__next));\n-    int res = INTERNAL_SYSCALL_CALL (set_robust_list, &pd->robust_head,\n-                                     sizeof (struct robust_list_head));\n-    if (!INTERNAL_SYSCALL_ERROR_P (res))\n-      __nptl_set_robust_list_avail = true;\n-  }\n+  robust_list_init (pd);\n \n   {\n     /* If the registration fails or is disabled by tunable, the public\ndiff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h\nindex c62c8982905..38a1383c3fe 100644\n--- a/sysdeps/nptl/pthreadP.h\n+++ b/sysdeps/nptl/pthreadP.h\n@@ -192,10 +192,8 @@ libc_hidden_proto (__pthread_keys)\n extern unsigned int __nptl_nthreads;\n libc_hidden_proto (__nptl_nthreads)\n \n-/* True if the set_robust_list system call works.  Initialized in\n-   __tls_init_tp.  */\n-extern bool __nptl_set_robust_list_avail;\n-rtld_hidden_proto (__nptl_set_robust_list_avail)\n+/* Set if the set_robust_list system call works.  */\n+extern int __nptl_set_robust_list_avail attribute_hidden;\n \n /* Thread Priority Protection.  */\n extern int __sched_fifo_min_prio;\n",
    "prefixes": [
        "v2",
        "3/3"
    ]
}