[libc-commits] [libc] [libc] Remove cross-entrypoint dependencies from pthread_create (PR #225383)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Tue Sep 22 05:27:27 PDT 2026


https://github.com/labath created https://github.com/llvm/llvm-project/pull/225383

pthread_create was previously calling public entrypoints (pthread_attr_init, pthread_attr_destroy, pthread_attr_getstack, pthread_attr_getguardsize, pthread_attr_getdetachstate), which violates the rule against internal cross-entrypoint dependencies.

To fix this, I create an internal header (src/pthread/pthread_attr.h) defining DEFAULT_PTHREAD_ATTR, modeled after DEFAULT_MUTEXATTR in the mutex code.

pthread_create now defaults to &DEFAULT_PTHREAD_ATTR when the attr pointer is null, and accesses the struct members directly instead of going through getter functions. This also makes it clear that getting the values cannot fail. I also update pthread_attr_init to reuse DEFAULT_PTHREAD_ATTR to avoid duplicating the default values.

While in there, update the includes to use proxy headers instead of including <pthread.h> directly, and drop the dependency on errno since pthread_create returns errors directly rather than setting errno.

Assisted-by: Gemini

>From fdac303ee150fd8842f4c934c2b5bd21255e8413 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Tue, 22 Sep 2026 12:26:05 +0000
Subject: [PATCH] [libc] Remove cross-entrypoint dependencies from
 pthread_create

pthread_create was previously calling public entrypoints
(pthread_attr_init, pthread_attr_destroy, pthread_attr_getstack,
pthread_attr_getguardsize, pthread_attr_getdetachstate), which violates
the rule against internal cross-entrypoint dependencies.

To fix this, I create an internal header (src/pthread/pthread_attr.h)
defining DEFAULT_PTHREAD_ATTR, modeled after DEFAULT_MUTEXATTR in the
mutex code.

pthread_create now defaults to &DEFAULT_PTHREAD_ATTR when the attr
pointer is null, and accesses the struct members directly instead of
going through getter functions. This also makes it clear that getting
the values cannot fail. I also update pthread_attr_init to reuse
DEFAULT_PTHREAD_ATTR to avoid duplicating the default values.

While in there, update the includes to use proxy headers instead of
including <pthread.h> directly, and drop the dependency on errno since
pthread_create returns errors directly rather than setting errno.

Assisted-by: Gemini
---
 libc/src/pthread/CMakeLists.txt        | 31 ++++++++-----
 libc/src/pthread/pthread_attr.h        | 38 ++++++++++++++++
 libc/src/pthread/pthread_attr_init.cpp | 14 +-----
 libc/src/pthread/pthread_create.cpp    | 61 ++++++++------------------
 4 files changed, 79 insertions(+), 65 deletions(-)
 create mode 100644 libc/src/pthread/pthread_attr.h

diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt
index cfbcb152ecc48..dcff91a5e935d 100644
--- a/libc/src/pthread/CMakeLists.txt
+++ b/libc/src/pthread/CMakeLists.txt
@@ -1,3 +1,16 @@
+add_header_library(
+  pthread_attr
+  HDRS
+    pthread_attr.h
+  DEPENDS
+    libc.hdr.pthread_macros
+    libc.hdr.sched_macros
+    libc.hdr.types.pthread_attr_t
+    libc.src.__support.macros.attributes
+    libc.src.__support.macros.config
+    libc.src.__support.threads.thread
+)
+
 add_entrypoint_object(
   pthread_attr_init
   SRCS
@@ -5,13 +18,10 @@ add_entrypoint_object(
   HDRS
     pthread_attr_init.h
   DEPENDS
-    libc.hdr.pthread_macros
-    libc.hdr.sched_macros
-    libc.hdr.types.pthread_attr_t
+    .pthread_attr
     libc.src.__support.common
     libc.src.__support.macros.config
     libc.src.__support.macros.null_check
-    libc.src.__support.threads.thread
 )
 
 add_entrypoint_object(
@@ -599,14 +609,15 @@ add_entrypoint_object(
   HDRS
     pthread_create.h
   DEPENDS
+    .pthread_attr
+    libc.hdr.errno_macros
+    libc.hdr.pthread_macros
+    libc.hdr.types.pthread_attr_t
+    libc.hdr.types.pthread_t
     libc.include.pthread
+    libc.src.__support.common
+    libc.src.__support.macros.config
     libc.src.__support.threads.thread
-    libc.src.pthread.pthread_attr_destroy
-    libc.src.pthread.pthread_attr_init
-    libc.src.pthread.pthread_attr_getdetachstate
-    libc.src.pthread.pthread_attr_getguardsize
-    libc.src.pthread.pthread_attr_getstack
-    libc.src.errno.errno
   COMPILE_OPTIONS
     ${libc_opt_high_flag}
     -fno-omit-frame-pointer
diff --git a/libc/src/pthread/pthread_attr.h b/libc/src/pthread/pthread_attr.h
new file mode 100644
index 0000000000000..09eb61fc9fd6d
--- /dev/null
+++ b/libc/src/pthread/pthread_attr.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Internal definitions for pthread_attr_t.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_H
+
+#include "hdr/pthread_macros.h"
+#include "hdr/sched_macros.h"
+#include "hdr/types/pthread_attr_t.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/thread.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LIBC_INLINE_VAR constexpr pthread_attr_t DEFAULT_PTHREAD_ATTR = {
+    PTHREAD_CREATE_JOINABLE,   // Not detached
+    PTHREAD_INHERIT_SCHED,     // Default inherit scheduler
+    SCHED_OTHER,               // Default scheduling policy
+    {},                        // Default scheduling parameters
+    nullptr,                   // Let the thread manage its stack
+    Thread::DEFAULT_STACKSIZE, // stack size.
+    Thread::DEFAULT_GUARDSIZE, // Default page size for the guard size.
+};
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_H
diff --git a/libc/src/pthread/pthread_attr_init.cpp b/libc/src/pthread/pthread_attr_init.cpp
index f2e22e10d60e4..bb9676ce3941a 100644
--- a/libc/src/pthread/pthread_attr_init.cpp
+++ b/libc/src/pthread/pthread_attr_init.cpp
@@ -12,27 +12,17 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/pthread/pthread_attr_init.h"
-#include "hdr/pthread_macros.h"
-#include "hdr/sched_macros.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/null_check.h"
-#include "src/__support/threads/thread.h" // For thread::DEFAULT_*
+#include "src/pthread/pthread_attr.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, pthread_attr_init, (pthread_attr_t * attr)) {
   LIBC_CRASH_ON_NULLPTR(attr);
 
-  *attr = pthread_attr_t{
-      PTHREAD_CREATE_JOINABLE,   // Not detached
-      PTHREAD_INHERIT_SCHED,     // Default inherit scheduler
-      SCHED_OTHER,               // Default scheduling policy
-      {},                        // Default scheduling parameters
-      nullptr,                   // Let the thread manage its stack
-      Thread::DEFAULT_STACKSIZE, // stack size.
-      Thread::DEFAULT_GUARDSIZE, // Default page size for the guard size.
-  };
+  *attr = DEFAULT_PTHREAD_ATTR;
   return 0;
 }
 
diff --git a/libc/src/pthread/pthread_create.cpp b/libc/src/pthread/pthread_create.cpp
index 45be2807fa832..247a80c8c2c4a 100644
--- a/libc/src/pthread/pthread_create.cpp
+++ b/libc/src/pthread/pthread_create.cpp
@@ -1,27 +1,26 @@
-//===-- Linux implementation of the pthread_create function ---------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of the pthread_create function.
+///
+//===----------------------------------------------------------------------===//
 
-#include "pthread_create.h"
-
-#include "pthread_attr_destroy.h"
-#include "pthread_attr_init.h"
-
-#include "pthread_attr_getdetachstate.h"
-#include "pthread_attr_getguardsize.h"
-#include "pthread_attr_getstack.h"
+#include "src/pthread/pthread_create.h"
 
+#include "hdr/errno_macros.h"
+#include "hdr/pthread_macros.h"
+#include "hdr/types/pthread_attr_t.h"
+#include "hdr/types/pthread_t.h"
 #include "src/__support/common.h"
-#include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
 #include "src/__support/threads/thread.h"
-
-#include <pthread.h> // For pthread_* type definitions.
+#include "src/pthread/pthread_attr.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -32,37 +31,13 @@ LLVM_LIBC_FUNCTION(int, pthread_create,
                    (pthread_t *__restrict th,
                     const pthread_attr_t *__restrict attr,
                     __pthread_start_t func, void *arg)) {
-  pthread_attr_t default_attr;
-  if (attr == nullptr) {
-    // We failed to initialize attributes (should be impossible)
-    if (LIBC_UNLIKELY(LIBC_NAMESPACE::pthread_attr_init(&default_attr) != 0))
-      return EINVAL;
-
-    attr = &default_attr;
-  }
-
-  void *stack;
-  size_t stacksize, guardsize;
-  int detachstate;
-
-  // As of writing this all the `pthread_attr_get*` functions always succeed.
-  if (LIBC_UNLIKELY(
-          LIBC_NAMESPACE::pthread_attr_getstack(attr, &stack, &stacksize) != 0))
-    return EINVAL;
-
-  if (LIBC_UNLIKELY(
-          LIBC_NAMESPACE::pthread_attr_getguardsize(attr, &guardsize) != 0))
-    return EINVAL;
-
-  if (LIBC_UNLIKELY(
-          LIBC_NAMESPACE::pthread_attr_getdetachstate(attr, &detachstate) != 0))
-    return EINVAL;
+  if (attr == nullptr)
+    attr = &DEFAULT_PTHREAD_ATTR;
 
-  if (attr == &default_attr)
-    // Should we fail here? Its non-issue as the moment as pthread_attr_destroy
-    // can only succeed.
-    if (LIBC_UNLIKELY(LIBC_NAMESPACE::pthread_attr_destroy(&default_attr) != 0))
-      return EINVAL;
+  void *stack = attr->__stack;
+  size_t stacksize = attr->__stacksize;
+  size_t guardsize = attr->__guardsize;
+  int detachstate = attr->__detachstate;
 
   if (stacksize && stacksize < PTHREAD_STACK_MIN)
     return EINVAL;



More information about the libc-commits mailing list