[libc-commits] [libc] [libc] Implement barriers for pthreads (PR #148948)

Uzair Nawaz via libc-commits libc-commits at lists.llvm.org
Tue Jul 22 14:46:45 PDT 2025


https://github.com/uzairnawaz updated https://github.com/llvm/llvm-project/pull/148948

>From 2d5b880393cbd430f088da8146a41f68d490c6dc Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Thu, 10 Jul 2025 21:01:39 +0000
Subject: [PATCH 01/10] Barrier class implemented; begin work on public
 functions

---
 libc/include/llvm-libc-types/CMakeLists.txt   |  2 +
 .../llvm-libc-types/pthread_barrier_t.h       | 16 +++++
 .../llvm-libc-types/pthread_barrierattr_t.h   | 16 +++++
 libc/src/__support/threads/barrier.cpp        | 70 +++++++++++++++++++
 libc/src/__support/threads/barrier.h          | 39 +++++++++++
 libc/src/pthread/pthread_barrier_destroy.cpp  | 24 +++++++
 libc/src/pthread/pthread_barrier_destroy.h    | 21 ++++++
 libc/src/pthread/pthread_barrier_init.cpp     | 32 +++++++++
 libc/src/pthread/pthread_barrier_init.h       | 23 ++++++
 libc/src/pthread/pthread_barrier_wait.cpp     | 27 +++++++
 libc/src/pthread/pthread_barrier_wait.h       | 21 ++++++
 .../src/pthread/pthread_barrier_test.cpp      | 35 ++++++++++
 12 files changed, 326 insertions(+)
 create mode 100644 libc/include/llvm-libc-types/pthread_barrier_t.h
 create mode 100644 libc/include/llvm-libc-types/pthread_barrierattr_t.h
 create mode 100644 libc/src/__support/threads/barrier.cpp
 create mode 100644 libc/src/__support/threads/barrier.h
 create mode 100644 libc/src/pthread/pthread_barrier_destroy.cpp
 create mode 100644 libc/src/pthread/pthread_barrier_destroy.h
 create mode 100644 libc/src/pthread/pthread_barrier_init.cpp
 create mode 100644 libc/src/pthread/pthread_barrier_init.h
 create mode 100644 libc/src/pthread/pthread_barrier_wait.cpp
 create mode 100644 libc/src/pthread/pthread_barrier_wait.h
 create mode 100644 libc/test/integration/src/pthread/pthread_barrier_test.cpp

diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index b24c97301668a..405c2cd26b863 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -53,6 +53,8 @@ add_header(pthread_condattr_t HDR pthread_condattr_t.h DEPENDS .clockid_t)
 add_header(pthread_key_t HDR pthread_key_t.h)
 add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type)
 add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h)
+add_header(pthread_barrier_t HDR pthread_barrier_t.h)
+add_header(pthread_barrierattr_t HDR pthread_barrierattr_t.h)
 add_header(pthread_once_t HDR pthread_once_t.h DEPENDS .__futex_word)
 add_header(pthread_rwlock_t HDR pthread_rwlock_t.h DEPENDS .__futex_word .pid_t)
 add_header(pthread_rwlockattr_t HDR pthread_rwlockattr_t.h)
diff --git a/libc/include/llvm-libc-types/pthread_barrier_t.h b/libc/include/llvm-libc-types/pthread_barrier_t.h
new file mode 100644
index 0000000000000..d95477afb226c
--- /dev/null
+++ b/libc/include/llvm-libc-types/pthread_barrier_t.h
@@ -0,0 +1,16 @@
+//===-- Definition of pthread_barrier_t type ------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
+#define LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
+
+typedef struct {
+  char padding[88];
+} pthread_barrier_t;
+
+#endif // LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
diff --git a/libc/include/llvm-libc-types/pthread_barrierattr_t.h b/libc/include/llvm-libc-types/pthread_barrierattr_t.h
new file mode 100644
index 0000000000000..064be5bfb6721
--- /dev/null
+++ b/libc/include/llvm-libc-types/pthread_barrierattr_t.h
@@ -0,0 +1,16 @@
+//===-- Definition of pthread_barrierattr_t type --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_PTHREAD_BARRIERATTR_T_H
+#define LLVM_LIBC_TYPES_PTHREAD_BARRIERATTR_T_H
+
+typedef struct {
+  bool pshared;
+} pthread_barrierattr_t;
+
+#endif // LLVM_LIBC_TYPES_PTHREAD_BARRIERATTR_T_H
diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
new file mode 100644
index 0000000000000..db0e38e9eb71e
--- /dev/null
+++ b/libc/src/__support/threads/barrier.cpp
@@ -0,0 +1,70 @@
+//===-- Linux implementation of the callonce 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/threads/barrier.h"
+#include "src/__support/threads/mutex.h"
+#include "hdr/errno_macros.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int Barrier::init(Barrier *b, const pthread_barrierattr_t* attr, unsigned count) {
+  if (count == 0)
+    return EINVAL;
+
+  b->expected = count;
+  b->waiting = 0;
+  b->blocking = true;
+
+  int err;
+  err = CndVar::init(&b->entering);
+  if (err != 0)
+    return err;
+
+  err = CndVar::init(&b->exiting);
+  if (err != 0)
+    return err;
+
+  Mutex::init(&b->m, false, false, false, false);
+  return 0;
+}
+
+int Barrier::wait() {
+  m.lock();
+
+  // if the barrier is emptying out threads, wait until it finishes
+  while (!blocking) {
+    entering.wait(&m);
+  }
+  waiting++;
+
+  if (waiting == expected) {
+    // this is the last thread to call wait(), so lets wake everyone up
+    blocking = false;
+    waiting--;
+    exiting.broadcast();
+  } else {
+    // block threads until waiting = expected
+    while (blocking) {
+      exiting.wait(&m);
+    }
+  }
+
+  // all threads have exited the barrier, lets let the ones waiting to enter
+  // continue
+  if (waiting == 0) {
+    blocking = true;
+    entering.broadcast();
+  }
+  m.unlock();
+}
+
+int Barrier::destroy(Barrier *b) {
+  
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/threads/barrier.h b/libc/src/__support/threads/barrier.h
new file mode 100644
index 0000000000000..e46d5b9773a4f
--- /dev/null
+++ b/libc/src/__support/threads/barrier.h
@@ -0,0 +1,39 @@
+//===-- A platform independent abstraction layer for barriers --*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
+#define LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/CndVar.h"
+#include "src/__support/threads/mutex.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// NOTE: if the size of this class changes, you must ensure that the size of
+// pthread_barrier_t (found in include/llvm-libc/types/pthread_barrier_t.h) is
+// the same size
+
+class Barrier {
+private:
+  unsigned expected;
+  unsigned waiting;
+  bool blocking;
+  CndVar entering;
+  CndVar exiting;
+  Mutex m;
+
+public:
+  static int init(Barrier *b, const pthread_barrierattr_t* attr, unsigned count);
+  static int destroy(Barrier *b);
+  int wait();
+};
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
diff --git a/libc/src/pthread/pthread_barrier_destroy.cpp b/libc/src/pthread/pthread_barrier_destroy.cpp
new file mode 100644
index 0000000000000..00863f8d6ff6b
--- /dev/null
+++ b/libc/src/pthread/pthread_barrier_destroy.cpp
@@ -0,0 +1,24 @@
+//===-- Linux implementation of the pthread_barrier_init 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "pthread_mutex_init.h"
+#include "pthread_mutexattr.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/barrier.h"
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pthread_barrier_destroy, (pthread_barrier_t * b)) {
+  return Barrier::destroy(reinterpret_cast<Barrier *>(b));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pthread/pthread_barrier_destroy.h b/libc/src/pthread/pthread_barrier_destroy.h
new file mode 100644
index 0000000000000..0b1d0f090ec26
--- /dev/null
+++ b/libc/src/pthread/pthread_barrier_destroy.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for pthread_barrier_destroy ----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_DESTROY_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_DESTROY_H
+
+#include "src/__support/macros/config.h"
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pthread_barrier_destroy(pthread_barrier_t *b);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_DESTROY_H
diff --git a/libc/src/pthread/pthread_barrier_init.cpp b/libc/src/pthread/pthread_barrier_init.cpp
new file mode 100644
index 0000000000000..234f58a6c7d62
--- /dev/null
+++ b/libc/src/pthread/pthread_barrier_init.cpp
@@ -0,0 +1,32 @@
+//===-- Linux implementation of the pthread_barrier_init 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "pthread_mutex_init.h"
+#include "pthread_mutexattr.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/barrier.h"
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+static_assert(
+    sizeof(Barrier) <= sizeof(pthread_barrier_t),
+    "The public pthread_barrier_t type cannot accommodate the internal "
+    "barrier type.");
+
+LLVM_LIBC_FUNCTION(int, pthread_barrier_init,
+                   (pthread_barrier_t * b,
+                    const pthread_barrierattr_t *__restrict attr,
+                    unsigned count)) {
+  return Barrier::init(reinterpret_cast<Barrier *>(b), attr, count);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pthread/pthread_barrier_init.h b/libc/src/pthread/pthread_barrier_init.h
new file mode 100644
index 0000000000000..ea79df6da7ea9
--- /dev/null
+++ b/libc/src/pthread/pthread_barrier_init.h
@@ -0,0 +1,23 @@
+//===-- Implementation header for pthread_barrier_init ----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_INIT_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_INIT_H
+
+#include "src/__support/macros/config.h"
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pthread_barrier_init(pthread_barrier_t *b,
+                         const pthread_barrierattr_t *__restrict attr,
+                         unsigned count);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_INIT_H
diff --git a/libc/src/pthread/pthread_barrier_wait.cpp b/libc/src/pthread/pthread_barrier_wait.cpp
new file mode 100644
index 0000000000000..ba23cc0f4e072
--- /dev/null
+++ b/libc/src/pthread/pthread_barrier_wait.cpp
@@ -0,0 +1,27 @@
+//===-- Linux implementation of the pthread_barrier_init 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "pthread_mutex_init.h"
+#include "pthread_mutexattr.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/barrier.h"
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pthread_barrier_wait,
+                   (pthread_barrier_t * b,
+                    const pthread_barrierattr_t *__restrict attr,
+                    unsigned count)) {
+  return reinterpret_cast<Barrier *>(b)->wait();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pthread/pthread_barrier_wait.h b/libc/src/pthread/pthread_barrier_wait.h
new file mode 100644
index 0000000000000..738ca56bd53e4
--- /dev/null
+++ b/libc/src/pthread/pthread_barrier_wait.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for pthread_barrier_wait ----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_WAIT_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_WAIT_H
+
+#include "src/__support/macros/config.h"
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pthread_barrier_wait(pthread_barrier_t *b);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_WAIT_H
diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
new file mode 100644
index 0000000000000..33d5945a6687d
--- /dev/null
+++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
@@ -0,0 +1,35 @@
+//===-- Tests for pthread_barrier_t ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/pthread/pthread_barrier_destroy.h"
+#include "src/pthread/pthread_barrier_init.h"
+#include "src/pthread/pthread_barrier_wait.h"
+
+#include "src/pthread/pthread_create.h"
+
+#include "test/IntegrationTest/test.h"
+
+#include <pthread.h>
+#include <stdint.h> // uintptr_t
+
+constexpr int START = 0;
+constexpr int MAX = 10000;
+
+pthread_barrier_t barrier;
+static int shared_int = START;
+
+void increment_shared_counter() {
+
+}
+
+
+
+TEST_MAIN() {
+  
+  return 0;
+}

>From cefd7de20b8877741b89c0410e4109e34f454ca7 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 15 Jul 2025 17:00:56 +0000
Subject: [PATCH 02/10] pthread test + public function

---
 libc/config/linux/x86_64/entrypoints.txt      |  3 +
 libc/include/CMakeLists.txt                   |  2 +
 libc/include/pthread.yaml                     | 22 +++++++
 libc/src/__support/threads/CMakeLists.txt     | 11 ++++
 libc/src/__support/threads/barrier.cpp        | 14 +++--
 libc/src/__support/threads/barrier.h          |  5 +-
 libc/src/pthread/CMakeLists.txt               | 34 ++++++++++
 libc/src/pthread/pthread_barrier_destroy.cpp  |  3 +-
 libc/src/pthread/pthread_barrier_init.cpp     |  3 +-
 libc/src/pthread/pthread_barrier_wait.cpp     |  7 +--
 .../integration/src/pthread/CMakeLists.txt    | 17 +++++
 .../src/pthread/pthread_barrier_test.cpp      | 63 +++++++++++++++++--
 12 files changed, 164 insertions(+), 20 deletions(-)

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 59c248871f83a..3a631c9056163 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1039,6 +1039,9 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.pthread.pthread_join
     libc.src.pthread.pthread_key_create
     libc.src.pthread.pthread_key_delete
+    libc.src.pthread.pthread_barrier_init
+    libc.src.pthread.pthread_barrier_wait
+    libc.src.pthread.pthread_barrier_destroy
     libc.src.pthread.pthread_mutex_destroy
     libc.src.pthread.pthread_mutex_init
     libc.src.pthread.pthread_mutex_lock
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 55268d19529c7..3c16468b8110e 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -390,6 +390,8 @@ add_header_macro(
     .llvm-libc-types.pthread_attr_t
     .llvm-libc-types.pthread_condattr_t
     .llvm-libc-types.pthread_key_t
+    .llvm-libc-types.pthread_barrier_t
+    .llvm-libc-types.pthread_barrierattr_t
     .llvm-libc-types.pthread_mutex_t
     .llvm-libc-types.pthread_mutexattr_t
     .llvm-libc-types.pthread_once_t
diff --git a/libc/include/pthread.yaml b/libc/include/pthread.yaml
index 5b27e68d2f2d8..8afce2098adde 100644
--- a/libc/include/pthread.yaml
+++ b/libc/include/pthread.yaml
@@ -6,6 +6,8 @@ types:
   - type_name: pthread_once_t
   - type_name: pthread_mutex_t
   - type_name: pthread_mutexattr_t
+  - type_name: pthread_barrier_t
+  - type_name: pthread_barrierattr_t
   - type_name: pthread_key_t
   - type_name: pthread_condattr_t
   - type_name: __pthread_tss_dtor_t
@@ -277,6 +279,26 @@ functions:
     arguments:
       - type: pthread_mutexattr_t *__restrict
       - type: int
+  - name: pthread_barrier_init
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: pthread_barrier_t *__restrict
+      - type: const pthread_barrierattr_t *__restrict
+      - type: int
+  - name: pthread_barrier_wait
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: pthread_barrier_t *
+  - name: pthread_barrier_destroy
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: pthread_barrier_t *
   - name: pthread_once
     standards:
       - POSIX
diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt
index bd49bbb5ad2fe..3cf50b6d3f8a9 100644
--- a/libc/src/__support/threads/CMakeLists.txt
+++ b/libc/src/__support/threads/CMakeLists.txt
@@ -90,6 +90,17 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.CndVar)
   )
 endif()
 
+add_object_library(
+  barrier
+  HDRS
+    barrier.h
+  SRCS
+    barrier.cpp
+  DEPENDS
+    .CndVar
+    .mutex
+)
+
 if (LLVM_LIBC_FULL_BUILD)
   set(identifier_dependency_on_thread libc.src.__support.threads.thread)
 endif()
diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
index db0e38e9eb71e..809898ac17ccf 100644
--- a/libc/src/__support/threads/barrier.cpp
+++ b/libc/src/__support/threads/barrier.cpp
@@ -7,12 +7,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/threads/barrier.h"
-#include "src/__support/threads/mutex.h"
+#include "barrier.h"
 #include "hdr/errno_macros.h"
+#include "src/__support/threads/mutex.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-int Barrier::init(Barrier *b, const pthread_barrierattr_t* attr, unsigned count) {
+int Barrier::init(Barrier *b, const pthread_barrierattr_t *attr,
+                  unsigned count) {
+  LIBC_ASSERT(attr == nullptr); // TODO implement barrierattr
   if (count == 0)
     return EINVAL;
 
@@ -45,7 +48,6 @@ int Barrier::wait() {
   if (waiting == expected) {
     // this is the last thread to call wait(), so lets wake everyone up
     blocking = false;
-    waiting--;
     exiting.broadcast();
   } else {
     // block threads until waiting = expected
@@ -53,6 +55,7 @@ int Barrier::wait() {
       exiting.wait(&m);
     }
   }
+  waiting--;
 
   // all threads have exited the barrier, lets let the ones waiting to enter
   // continue
@@ -61,10 +64,13 @@ int Barrier::wait() {
     entering.broadcast();
   }
   m.unlock();
+
+  return 0;
 }
 
 int Barrier::destroy(Barrier *b) {
-  
+  Mutex::destroy(&b->m);
+  return 0;
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/threads/barrier.h b/libc/src/__support/threads/barrier.h
index e46d5b9773a4f..d97aafe56d2cd 100644
--- a/libc/src/__support/threads/barrier.h
+++ b/libc/src/__support/threads/barrier.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
 #define LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
 
+#include "include/llvm-libc-types/pthread_barrier_t.h"
+#include "include/llvm-libc-types/pthread_barrierattr_t.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/threads/CndVar.h"
 #include "src/__support/threads/mutex.h"
@@ -29,7 +31,8 @@ class Barrier {
   Mutex m;
 
 public:
-  static int init(Barrier *b, const pthread_barrierattr_t* attr, unsigned count);
+  static int init(Barrier *b, const pthread_barrierattr_t *attr,
+                  unsigned count);
   static int destroy(Barrier *b);
   int wait();
 };
diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt
index c8c66805667fa..e5a0a34cf46a6 100644
--- a/libc/src/pthread/CMakeLists.txt
+++ b/libc/src/pthread/CMakeLists.txt
@@ -271,6 +271,40 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  pthread_barrier_init
+  SRCS
+    pthread_barrier_init.cpp
+  HDRS
+    pthread_barrier_init.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.pthread
+    libc.src.__support.threads.barrier
+)
+
+add_entrypoint_object(
+  pthread_barrier_destroy
+  SRCS
+    pthread_barrier_destroy.cpp
+  HDRS
+    pthread_barrier_destroy.h
+  DEPENDS
+    libc.include.pthread
+    libc.src.__support.threads.barrier
+)
+
+add_entrypoint_object(
+  pthread_barrier_wait
+  SRCS
+    pthread_barrier_wait.cpp
+  HDRS
+    pthread_barrier_wait.h
+  DEPENDS
+    libc.include.pthread
+    libc.src.__support.threads.barrier
+)
+
 add_entrypoint_object(
   pthread_mutex_init
   SRCS
diff --git a/libc/src/pthread/pthread_barrier_destroy.cpp b/libc/src/pthread/pthread_barrier_destroy.cpp
index 00863f8d6ff6b..389e1751ed3ee 100644
--- a/libc/src/pthread/pthread_barrier_destroy.cpp
+++ b/libc/src/pthread/pthread_barrier_destroy.cpp
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "pthread_mutex_init.h"
-#include "pthread_mutexattr.h"
+#include "pthread_barrier_destroy.h"
 
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/pthread/pthread_barrier_init.cpp b/libc/src/pthread/pthread_barrier_init.cpp
index 234f58a6c7d62..1d0d87342d823 100644
--- a/libc/src/pthread/pthread_barrier_init.cpp
+++ b/libc/src/pthread/pthread_barrier_init.cpp
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "pthread_mutex_init.h"
-#include "pthread_mutexattr.h"
+#include "pthread_barrier_init.h"
 
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/pthread/pthread_barrier_wait.cpp b/libc/src/pthread/pthread_barrier_wait.cpp
index ba23cc0f4e072..75bba94ba438f 100644
--- a/libc/src/pthread/pthread_barrier_wait.cpp
+++ b/libc/src/pthread/pthread_barrier_wait.cpp
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "pthread_mutex_init.h"
-#include "pthread_mutexattr.h"
+#include "pthread_barrier_wait.h"
 
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
@@ -18,9 +17,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, pthread_barrier_wait,
-                   (pthread_barrier_t * b,
-                    const pthread_barrierattr_t *__restrict attr,
-                    unsigned count)) {
+                   (pthread_barrier_t * b)) {
   return reinterpret_cast<Barrier *>(b)->wait();
 }
 
diff --git a/libc/test/integration/src/pthread/CMakeLists.txt b/libc/test/integration/src/pthread/CMakeLists.txt
index 208ba3fd43507..ce3bb9da9d58e 100644
--- a/libc/test/integration/src/pthread/CMakeLists.txt
+++ b/libc/test/integration/src/pthread/CMakeLists.txt
@@ -17,6 +17,23 @@ add_integration_test(
     libc.src.pthread.pthread_join
 )
 
+add_integration_test(
+  pthread_barrier_test
+  SUITE
+    libc-pthread-integration-tests
+  SRCS
+    pthread_barrier_test.cpp
+  DEPENDS
+    libc.include.pthread
+    libc.src.errno.errno
+    libc.src.pthread.pthread_barrier_destroy
+    libc.src.pthread.pthread_barrier_wait
+    libc.src.pthread.pthread_barrier_init
+    libc.src.pthread.pthread_create
+    libc.src.pthread.pthread_join
+    libc.src.stdio.printf
+)
+
 add_integration_test(
   pthread_rwlock_test
   SUITE
diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
index 33d5945a6687d..b87f21a2a2c51 100644
--- a/libc/test/integration/src/pthread/pthread_barrier_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
@@ -10,26 +10,77 @@
 #include "src/pthread/pthread_barrier_init.h"
 #include "src/pthread/pthread_barrier_wait.h"
 
+#include "src/__support/CPP/atomic.h"
 #include "src/pthread/pthread_create.h"
+#include "src/pthread/pthread_join.h"
+#include "src/pthread/pthread_mutex_destroy.h"
+#include "src/pthread/pthread_mutex_init.h"
+#include "src/pthread/pthread_mutex_lock.h"
+#include "src/pthread/pthread_mutex_unlock.h"
+#include "src/stdio/printf.h"
 
 #include "test/IntegrationTest/test.h"
 
 #include <pthread.h>
 #include <stdint.h> // uintptr_t
 
-constexpr int START = 0;
-constexpr int MAX = 10000;
-
 pthread_barrier_t barrier;
-static int shared_int = START;
 
-void increment_shared_counter() {
+void smoke_test() {
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, 1), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_wait(&barrier), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_destroy(&barrier), 0);
+}
 
+LIBC_NAMESPACE::cpp::Atomic<int> counter;
+void *increment_counter_and_wait(void *args) {
+  counter.fetch_add(1);
+  LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
+  return 0;
 }
 
+void shared_counter() {
+  counter.set(0);
+  const int NUM_THREADS = 30;
+  pthread_t threads[NUM_THREADS];
+  ASSERT_EQ(
+      LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1),
+      0);
 
+  for (int i = 0; i < NUM_THREADS; ++i)
+    LIBC_NAMESPACE::pthread_create(&threads[i], nullptr,
+                                   increment_counter_and_wait, nullptr);
+
+  LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
+  ASSERT_EQ(counter.load(), NUM_THREADS);
+}
+
+void reusable_shared_counter() {
+  counter.set(0);
+  const int NUM_THREADS = 30;
+  const int REPEAT = 10;
+  pthread_t threads[NUM_THREADS * REPEAT];
+  ASSERT_EQ(
+      LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1),
+      0);
+
+  for (int i = 0; i < REPEAT; ++i) {
+    for (int j = 0; j < NUM_THREADS; ++j) {
+      LIBC_NAMESPACE::pthread_create(&threads[NUM_THREADS * i + j], nullptr,
+                                     increment_counter_and_wait, nullptr);
+    }
+    LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
+    ASSERT_EQ(counter.load(), NUM_THREADS * (i + 1));
+  }
+
+  for (int i = 0; i < NUM_THREADS * REPEAT; ++i) {
+    LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
+  }
+}
 
 TEST_MAIN() {
-  
+  smoke_test();
+  shared_counter();
+  reusable_shared_counter();
   return 0;
 }

>From d645f954d8374d3cf3b4ba61dc18b16724c21717 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 15 Jul 2025 17:20:06 +0000
Subject: [PATCH 03/10] fix test to join threads

---
 .../src/pthread/pthread_barrier_test.cpp      | 21 ++++++++++---------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
index b87f21a2a2c51..8cf2aaf16acbe 100644
--- a/libc/test/integration/src/pthread/pthread_barrier_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
@@ -22,7 +22,6 @@
 #include "test/IntegrationTest/test.h"
 
 #include <pthread.h>
-#include <stdint.h> // uintptr_t
 
 pthread_barrier_t barrier;
 
@@ -39,7 +38,7 @@ void *increment_counter_and_wait(void *args) {
   return 0;
 }
 
-void shared_counter() {
+void single_use_barrier() {
   counter.set(0);
   const int NUM_THREADS = 30;
   pthread_t threads[NUM_THREADS];
@@ -53,34 +52,36 @@ void shared_counter() {
 
   LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
   ASSERT_EQ(counter.load(), NUM_THREADS);
+
+  for (int i = 0; i < NUM_THREADS; ++i)
+    LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
 }
 
-void reusable_shared_counter() {
+void reusable_barrier() {
   counter.set(0);
   const int NUM_THREADS = 30;
-  const int REPEAT = 10;
+  const int REPEAT = 20;
   pthread_t threads[NUM_THREADS * REPEAT];
   ASSERT_EQ(
       LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1),
       0);
 
   for (int i = 0; i < REPEAT; ++i) {
-    for (int j = 0; j < NUM_THREADS; ++j) {
+    for (int j = 0; j < NUM_THREADS; ++j)
       LIBC_NAMESPACE::pthread_create(&threads[NUM_THREADS * i + j], nullptr,
                                      increment_counter_and_wait, nullptr);
-    }
+
     LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
     ASSERT_EQ(counter.load(), NUM_THREADS * (i + 1));
   }
 
-  for (int i = 0; i < NUM_THREADS * REPEAT; ++i) {
+  for (int i = 0; i < NUM_THREADS * REPEAT; ++i)
     LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
-  }
 }
 
 TEST_MAIN() {
   smoke_test();
-  shared_counter();
-  reusable_shared_counter();
+  single_use_barrier();
+  reusable_barrier();
   return 0;
 }

>From 8cad8c0a4533c525c1a41b13821c41edaa2e3359 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 15 Jul 2025 18:00:24 +0000
Subject: [PATCH 04/10] implemented return value for barrier wait

---
 .../include/llvm-libc-macros/pthread-macros.h |  2 ++
 libc/src/__support/threads/barrier.cpp        |  6 ++++
 libc/src/__support/threads/barrier.h          |  2 ++
 libc/src/pthread/pthread_barrier_wait.cpp     |  9 ++++--
 .../src/pthread/pthread_barrier_test.cpp      | 32 ++++++++++++++++++-
 5 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/libc/include/llvm-libc-macros/pthread-macros.h b/libc/include/llvm-libc-macros/pthread-macros.h
index fcc6ef925e3f4..ce467b7cc4d07 100644
--- a/libc/include/llvm-libc-macros/pthread-macros.h
+++ b/libc/include/llvm-libc-macros/pthread-macros.h
@@ -22,6 +22,8 @@
 #define PTHREAD_MUTEX_STALLED 0
 #define PTHREAD_MUTEX_ROBUST 1
 
+#define PTHREAD_BARRIER_SERIAL_THREAD -1
+
 #define PTHREAD_ONCE_INIT {0}
 
 #define PTHREAD_PROCESS_PRIVATE 0
diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
index 809898ac17ccf..298cb17cb8d00 100644
--- a/libc/src/__support/threads/barrier.cpp
+++ b/libc/src/__support/threads/barrier.cpp
@@ -13,6 +13,8 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
+const int BARRIER_FIRST_EXITED = -1;
+
 int Barrier::init(Barrier *b, const pthread_barrierattr_t *attr,
                   unsigned count) {
   LIBC_ASSERT(attr == nullptr); // TODO implement barrierattr
@@ -62,6 +64,8 @@ int Barrier::wait() {
   if (waiting == 0) {
     blocking = true;
     entering.broadcast();
+    m.unlock();
+    return BARRIER_FIRST_EXITED;
   }
   m.unlock();
 
@@ -69,6 +73,8 @@ int Barrier::wait() {
 }
 
 int Barrier::destroy(Barrier *b) {
+  CndVar::destroy(&b->entering);
+  CndVar::destroy(&b->exiting);
   Mutex::destroy(&b->m);
   return 0;
 }
diff --git a/libc/src/__support/threads/barrier.h b/libc/src/__support/threads/barrier.h
index d97aafe56d2cd..b8b410ec1b35e 100644
--- a/libc/src/__support/threads/barrier.h
+++ b/libc/src/__support/threads/barrier.h
@@ -21,6 +21,8 @@ namespace LIBC_NAMESPACE_DECL {
 // pthread_barrier_t (found in include/llvm-libc/types/pthread_barrier_t.h) is
 // the same size
 
+extern const int BARRIER_FIRST_EXITED;
+
 class Barrier {
 private:
   unsigned expected;
diff --git a/libc/src/pthread/pthread_barrier_wait.cpp b/libc/src/pthread/pthread_barrier_wait.cpp
index 75bba94ba438f..617d91dd16f77 100644
--- a/libc/src/pthread/pthread_barrier_wait.cpp
+++ b/libc/src/pthread/pthread_barrier_wait.cpp
@@ -16,9 +16,12 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(int, pthread_barrier_wait,
-                   (pthread_barrier_t * b)) {
-  return reinterpret_cast<Barrier *>(b)->wait();
+LLVM_LIBC_FUNCTION(int, pthread_barrier_wait, (pthread_barrier_t * b)) {
+  int out = reinterpret_cast<Barrier *>(b)->wait();
+  if (out == BARRIER_FIRST_EXITED)
+    return PTHREAD_BARRIER_SERIAL_THREAD;
+  
+  return out;
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
index 8cf2aaf16acbe..d4d696ec82507 100644
--- a/libc/test/integration/src/pthread/pthread_barrier_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
@@ -27,7 +27,8 @@ pthread_barrier_t barrier;
 
 void smoke_test() {
   ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, 1), 0);
-  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_wait(&barrier), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_wait(&barrier),
+            PTHREAD_BARRIER_SERIAL_THREAD);
   ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_destroy(&barrier), 0);
 }
 
@@ -55,6 +56,8 @@ void single_use_barrier() {
 
   for (int i = 0; i < NUM_THREADS; ++i)
     LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
+
+  LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);
 }
 
 void reusable_barrier() {
@@ -77,11 +80,38 @@ void reusable_barrier() {
 
   for (int i = 0; i < NUM_THREADS * REPEAT; ++i)
     LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
+
+  LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);
+}
+
+void *barrier_wait(void* in) {
+  return reinterpret_cast<void *>(
+      LIBC_NAMESPACE::pthread_barrier_wait(&barrier));
+}
+
+// verify that only one of the wait() calls return PTHREAD_BARRIER_SERIAL_THREAD
+// with the rest returning 0
+void one_nonzero_wait_returnval() {
+  const int NUM_THREADS = 30;
+  pthread_t threads[NUM_THREADS];
+  LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1);
+  for (int i = 0; i < NUM_THREADS; ++i)
+    LIBC_NAMESPACE::pthread_create(&threads[i], nullptr, barrier_wait, nullptr);
+
+  uintptr_t retsum = LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
+  for (int i = 0; i < NUM_THREADS; ++i) {
+    void* ret;
+    LIBC_NAMESPACE::pthread_join(threads[i], &ret);
+    retsum += reinterpret_cast<uintptr_t>(ret);
+  }
+
+  ASSERT_EQ(static_cast<int>(retsum), PTHREAD_BARRIER_SERIAL_THREAD);
 }
 
 TEST_MAIN() {
   smoke_test();
   single_use_barrier();
   reusable_barrier();
+  one_nonzero_wait_returnval();
   return 0;
 }

>From 7adf56a5ed4705dca4816e7c889d42df6478a8d9 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 15 Jul 2025 20:13:06 +0000
Subject: [PATCH 05/10] formatting

---
 libc/src/__support/threads/barrier.cpp                     | 2 +-
 libc/src/pthread/pthread_barrier_destroy.h                 | 2 +-
 libc/src/pthread/pthread_barrier_wait.cpp                  | 2 +-
 libc/test/integration/src/pthread/pthread_barrier_test.cpp | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
index 298cb17cb8d00..050abb3391446 100644
--- a/libc/src/__support/threads/barrier.cpp
+++ b/libc/src/__support/threads/barrier.cpp
@@ -1,4 +1,4 @@
-//===-- Linux implementation of the callonce function ---------------------===//
+//===-- Implementation of Barrier class ------------- ---------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/pthread/pthread_barrier_destroy.h b/libc/src/pthread/pthread_barrier_destroy.h
index 0b1d0f090ec26..58ac08862d90c 100644
--- a/libc/src/pthread/pthread_barrier_destroy.h
+++ b/libc/src/pthread/pthread_barrier_destroy.h
@@ -1,4 +1,4 @@
-//===-- Implementation header for pthread_barrier_destroy ----------*- C++ -*-===//
+//===-- Implementation header for pthread_barrier_destroy --------*- C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/pthread/pthread_barrier_wait.cpp b/libc/src/pthread/pthread_barrier_wait.cpp
index 617d91dd16f77..7b12c907f4fb1 100644
--- a/libc/src/pthread/pthread_barrier_wait.cpp
+++ b/libc/src/pthread/pthread_barrier_wait.cpp
@@ -20,7 +20,7 @@ LLVM_LIBC_FUNCTION(int, pthread_barrier_wait, (pthread_barrier_t * b)) {
   int out = reinterpret_cast<Barrier *>(b)->wait();
   if (out == BARRIER_FIRST_EXITED)
     return PTHREAD_BARRIER_SERIAL_THREAD;
-  
+
   return out;
 }
 
diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
index d4d696ec82507..bde1230f5b86d 100644
--- a/libc/test/integration/src/pthread/pthread_barrier_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
@@ -84,7 +84,7 @@ void reusable_barrier() {
   LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);
 }
 
-void *barrier_wait(void* in) {
+void *barrier_wait(void *in) {
   return reinterpret_cast<void *>(
       LIBC_NAMESPACE::pthread_barrier_wait(&barrier));
 }
@@ -100,7 +100,7 @@ void one_nonzero_wait_returnval() {
 
   uintptr_t retsum = LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
   for (int i = 0; i < NUM_THREADS; ++i) {
-    void* ret;
+    void *ret;
     LIBC_NAMESPACE::pthread_join(threads[i], &ret);
     retsum += reinterpret_cast<uintptr_t>(ret);
   }

>From a349e6f20cb8d4058c8f0247d48bd8e837129420 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 15 Jul 2025 20:22:42 +0000
Subject: [PATCH 06/10] mark attr param as unused

---
 libc/src/__support/threads/barrier.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
index 050abb3391446..e63467d88b2bf 100644
--- a/libc/src/__support/threads/barrier.cpp
+++ b/libc/src/__support/threads/barrier.cpp
@@ -15,7 +15,8 @@ namespace LIBC_NAMESPACE_DECL {
 
 const int BARRIER_FIRST_EXITED = -1;
 
-int Barrier::init(Barrier *b, const pthread_barrierattr_t *attr,
+int Barrier::init(Barrier *b,
+                  const pthread_barrierattr_t *attr __attribute__((unused)),
                   unsigned count) {
   LIBC_ASSERT(attr == nullptr); // TODO implement barrierattr
   if (count == 0)

>From d901a3712e797e8a464e967cb99209e3fd000e62 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Fri, 18 Jul 2025 16:47:38 +0000
Subject: [PATCH 07/10] reorganized for readability

---
 libc/src/__support/threads/barrier.cpp    | 17 +++++++++--------
 libc/src/__support/threads/barrier.h      |  9 +++++++++
 libc/src/pthread/pthread_barrier_init.cpp |  5 -----
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
index e63467d88b2bf..a9253d8c91611 100644
--- a/libc/src/__support/threads/barrier.cpp
+++ b/libc/src/__support/threads/barrier.cpp
@@ -9,6 +9,7 @@
 #include "src/__support/threads/barrier.h"
 #include "barrier.h"
 #include "hdr/errno_macros.h"
+#include "src/__support/threads/CndVar.h"
 #include "src/__support/threads/mutex.h"
 
 namespace LIBC_NAMESPACE_DECL {
@@ -16,7 +17,7 @@ namespace LIBC_NAMESPACE_DECL {
 const int BARRIER_FIRST_EXITED = -1;
 
 int Barrier::init(Barrier *b,
-                  const pthread_barrierattr_t *attr __attribute__((unused)),
+                  [[maybe_unused]] const pthread_barrierattr_t *attr,
                   unsigned count) {
   LIBC_ASSERT(attr == nullptr); // TODO implement barrierattr
   if (count == 0)
@@ -48,21 +49,21 @@ int Barrier::wait() {
   }
   waiting++;
 
-  if (waiting == expected) {
-    // this is the last thread to call wait(), so lets wake everyone up
-    blocking = false;
-    exiting.broadcast();
-  } else {
+  if (waiting < expected) {
     // block threads until waiting = expected
     while (blocking) {
       exiting.wait(&m);
     }
+  } else {
+    // this is the last thread to call wait(), so lets wake everyone up
+    blocking = false;
+    exiting.broadcast();
   }
   waiting--;
 
-  // all threads have exited the barrier, lets let the ones waiting to enter
-  // continue
   if (waiting == 0) {
+    // all threads have exited the barrier, let's let the ones waiting to enter
+    // continue
     blocking = true;
     entering.broadcast();
     m.unlock();
diff --git a/libc/src/__support/threads/barrier.h b/libc/src/__support/threads/barrier.h
index b8b410ec1b35e..5aa99fe405cda 100644
--- a/libc/src/__support/threads/barrier.h
+++ b/libc/src/__support/threads/barrier.h
@@ -39,6 +39,15 @@ class Barrier {
   int wait();
 };
 
+static_assert(
+    sizeof(Barrier) <= sizeof(pthread_barrier_t),
+    "The public pthread_barrier_t type cannot accommodate the internal "
+    "barrier type.");
+
+static_assert(alignof(Barrier) == alignof(pthread_barrier_t),
+              "The public pthread_barrier_t type has a different alignment "
+              "than the internal barrier type.");
+
 } // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
diff --git a/libc/src/pthread/pthread_barrier_init.cpp b/libc/src/pthread/pthread_barrier_init.cpp
index 1d0d87342d823..f17885432bf31 100644
--- a/libc/src/pthread/pthread_barrier_init.cpp
+++ b/libc/src/pthread/pthread_barrier_init.cpp
@@ -16,11 +16,6 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-static_assert(
-    sizeof(Barrier) <= sizeof(pthread_barrier_t),
-    "The public pthread_barrier_t type cannot accommodate the internal "
-    "barrier type.");
-
 LLVM_LIBC_FUNCTION(int, pthread_barrier_init,
                    (pthread_barrier_t * b,
                     const pthread_barrierattr_t *__restrict attr,

>From 0512e7f596583298f89bd702c9d45b34f2554ea6 Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Fri, 18 Jul 2025 19:23:06 +0000
Subject: [PATCH 08/10] used internal pthread header

---
 libc/hdr/types/pthread_barrier_t.h           | 22 ++++++++++++++++++++
 libc/hdr/types/pthread_barrierattr_t.h       | 22 ++++++++++++++++++++
 libc/src/pthread/pthread_barrier_destroy.cpp |  3 +--
 libc/src/pthread/pthread_barrier_destroy.h   |  2 +-
 libc/src/pthread/pthread_barrier_init.cpp    |  4 ++--
 libc/src/pthread/pthread_barrier_init.h      |  3 ++-
 libc/src/pthread/pthread_barrier_wait.cpp    |  3 +--
 libc/src/pthread/pthread_barrier_wait.h      |  2 +-
 8 files changed, 52 insertions(+), 9 deletions(-)
 create mode 100644 libc/hdr/types/pthread_barrier_t.h
 create mode 100644 libc/hdr/types/pthread_barrierattr_t.h

diff --git a/libc/hdr/types/pthread_barrier_t.h b/libc/hdr/types/pthread_barrier_t.h
new file mode 100644
index 0000000000000..57bcdfc6a9901
--- /dev/null
+++ b/libc/hdr/types/pthread_barrier_t.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from pthread_barrier_t.h ---------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_PTHREAD_BARRIER_T_H
+#define LLVM_LIBC_HDR_TYPES_PTHREAD_BARRIER_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/pthread_barrier_t.h"
+
+#else // Overlay mode
+
+#error "Cannot overlay pthread_barrier_t"
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_PTHREAD_BARRIER_T_H
diff --git a/libc/hdr/types/pthread_barrierattr_t.h b/libc/hdr/types/pthread_barrierattr_t.h
new file mode 100644
index 0000000000000..d08dda1c2f36d
--- /dev/null
+++ b/libc/hdr/types/pthread_barrierattr_t.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from pthread_barrier_t.h ---------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_PTHREAD_BARRIERATTR_T_H
+#define LLVM_LIBC_HDR_TYPES_PTHREAD_BARRIERATTR_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/pthread_barrierattr_t.h"
+
+#else // Overlay mode
+
+#error "Cannot overlay pthread_barrierattr_t"
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_PTHREAD_BARRIERATTR_T_H
diff --git a/libc/src/pthread/pthread_barrier_destroy.cpp b/libc/src/pthread/pthread_barrier_destroy.cpp
index 389e1751ed3ee..6c9ae8d57ab2f 100644
--- a/libc/src/pthread/pthread_barrier_destroy.cpp
+++ b/libc/src/pthread/pthread_barrier_destroy.cpp
@@ -8,12 +8,11 @@
 
 #include "pthread_barrier_destroy.h"
 
+#include "hdr/types/pthread_barrier_t.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/threads/barrier.h"
 
-#include <pthread.h>
-
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, pthread_barrier_destroy, (pthread_barrier_t * b)) {
diff --git a/libc/src/pthread/pthread_barrier_destroy.h b/libc/src/pthread/pthread_barrier_destroy.h
index 58ac08862d90c..e27552ce7e5ae 100644
--- a/libc/src/pthread/pthread_barrier_destroy.h
+++ b/libc/src/pthread/pthread_barrier_destroy.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_DESTROY_H
 #define LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_DESTROY_H
 
+#include "hdr/types/pthread_barrier_t.h"
 #include "src/__support/macros/config.h"
-#include <pthread.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/pthread/pthread_barrier_init.cpp b/libc/src/pthread/pthread_barrier_init.cpp
index f17885432bf31..4317d82bc935f 100644
--- a/libc/src/pthread/pthread_barrier_init.cpp
+++ b/libc/src/pthread/pthread_barrier_init.cpp
@@ -8,12 +8,12 @@
 
 #include "pthread_barrier_init.h"
 
+#include "hdr/types/pthread_barrier_t.h"
+#include "hdr/types/pthread_barrierattr_t.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/threads/barrier.h"
 
-#include <pthread.h>
-
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, pthread_barrier_init,
diff --git a/libc/src/pthread/pthread_barrier_init.h b/libc/src/pthread/pthread_barrier_init.h
index ea79df6da7ea9..bb17f3f5664da 100644
--- a/libc/src/pthread/pthread_barrier_init.h
+++ b/libc/src/pthread/pthread_barrier_init.h
@@ -9,8 +9,9 @@
 #ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_INIT_H
 #define LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_INIT_H
 
+#include "hdr/types/pthread_barrier_t.h"
+#include "hdr/types/pthread_barrierattr_t.h"
 #include "src/__support/macros/config.h"
-#include <pthread.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/pthread/pthread_barrier_wait.cpp b/libc/src/pthread/pthread_barrier_wait.cpp
index 7b12c907f4fb1..7e34babdb2579 100644
--- a/libc/src/pthread/pthread_barrier_wait.cpp
+++ b/libc/src/pthread/pthread_barrier_wait.cpp
@@ -8,12 +8,11 @@
 
 #include "pthread_barrier_wait.h"
 
+#include "hdr/types/pthread_barrier_t.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/threads/barrier.h"
 
-#include <pthread.h>
-
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, pthread_barrier_wait, (pthread_barrier_t * b)) {
diff --git a/libc/src/pthread/pthread_barrier_wait.h b/libc/src/pthread/pthread_barrier_wait.h
index 738ca56bd53e4..52eb172d6264c 100644
--- a/libc/src/pthread/pthread_barrier_wait.h
+++ b/libc/src/pthread/pthread_barrier_wait.h
@@ -10,7 +10,7 @@
 #define LLVM_LIBC_SRC_PTHREAD_PTHREAD_BARRIER_WAIT_H
 
 #include "src/__support/macros/config.h"
-#include <pthread.h>
+#include "hdr/types/pthread_barrier_t.h"
 
 namespace LIBC_NAMESPACE_DECL {
 

>From ecf9f6c5ddcda1a717eca30286d103f394ed7c4b Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 22 Jul 2025 21:40:56 +0000
Subject: [PATCH 09/10] fix pthread_barrier_t public struct
 opaqueness/alignment + test cleanup

---
 libc/hdr/CMakeLists.txt                       |   9 ++
 libc/hdr/pthread_macros.h                     |  22 ++++
 libc/hdr/types/CMakeLists.txt                 |  16 +++
 libc/include/llvm-libc-types/CMakeLists.txt   |   1 +
 libc/include/llvm-libc-types/__barrier_type.h |  21 ++++
 .../llvm-libc-types/pthread_barrier_t.h       |   7 +-
 libc/src/__support/threads/barrier.cpp        |  12 +-
 libc/src/__support/threads/barrier.h          |   5 +-
 libc/src/pthread/pthread_barrier_wait.cpp     |   6 +-
 .../src/pthread/pthread_barrier_test.cpp      | 107 +++++++++---------
 10 files changed, 136 insertions(+), 70 deletions(-)
 create mode 100644 libc/hdr/pthread_macros.h
 create mode 100644 libc/include/llvm-libc-types/__barrier_type.h

diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index 052a773a4fcec..0aa79e98446c1 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -72,6 +72,15 @@ add_proxy_header_library(
     libc.include.fenv
 )
 
+add_proxy_header_library(
+  pthread_macros
+  HDRS
+    pthread_macros.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-macros.pthread_macros
+    libc.include.pthread
+)
+
 add_proxy_header_library(
   sched_macros
   HDRS
diff --git a/libc/hdr/pthread_macros.h b/libc/hdr/pthread_macros.h
new file mode 100644
index 0000000000000..b0bab73687e3b
--- /dev/null
+++ b/libc/hdr/pthread_macros.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from pthread.h ----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_PTHREAD_MACROS_H
+#define LLVM_LIBC_HDR_PTHREAD_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/pthread-macros.h"
+
+#else // Overlay mode
+
+#include <pthread.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_PTHREAD_MACROS_H
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index e4b3cb0faa820..2f2d6e8f0f985 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -237,6 +237,22 @@ add_proxy_header_library(
     libc.include.llvm-libc-types.pid_t
 )
 
+add_proxy_header_library(
+  pthread_barrier_t
+  HDRS
+    pthread_barrier_t.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.pthread_barrier_t
+)
+
+add_proxy_header_library(
+  pthread_barrierattr_t
+  HDRS
+    pthread_barrierattr_t.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.pthread_barrierattr_t
+)
+
 add_proxy_header_library(
   atexithandler_t
   HDRS
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 405c2cd26b863..ba621757a31ed 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -10,6 +10,7 @@ add_header(__exec_envp_t HDR __exec_envp_t.h)
 add_header(__futex_word HDR __futex_word.h)
 add_header(pid_t HDR pid_t.h)
 add_header(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word .pid_t)
+add_header(__barrier_type HDR __barrier_type.h)
 add_header(__pthread_once_func_t HDR __pthread_once_func_t.h)
 add_header(__pthread_start_t HDR __pthread_start_t.h)
 add_header(__pthread_tss_dtor_t HDR __pthread_tss_dtor_t.h)
diff --git a/libc/include/llvm-libc-types/__barrier_type.h b/libc/include/llvm-libc-types/__barrier_type.h
new file mode 100644
index 0000000000000..97406b8843ee5
--- /dev/null
+++ b/libc/include/llvm-libc-types/__barrier_type.h
@@ -0,0 +1,21 @@
+//===-- Definition of pthread_barrier_t type ------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES__BARRIER_TYPE_H
+#define LLVM_LIBC_TYPES__BARRIER_TYPE_H
+
+typedef struct __attribute__((aligned(8 /* alignof (Barrier) */))) {
+  unsigned expected;
+  unsigned waiting;
+  bool blocking;
+  char entering[24 /* sizeof (CndVar) */];
+  char exiting[24 /* sizeof (CndVar) */];
+  char mutex[24 /* sizeof (Mutex) */];
+} __barrier_type;
+
+#endif // LLVM_LIBC_TYPES__BARRIER_TYPE_H
diff --git a/libc/include/llvm-libc-types/pthread_barrier_t.h b/libc/include/llvm-libc-types/pthread_barrier_t.h
index d95477afb226c..3a3d4706d43e6 100644
--- a/libc/include/llvm-libc-types/pthread_barrier_t.h
+++ b/libc/include/llvm-libc-types/pthread_barrier_t.h
@@ -1,4 +1,4 @@
-//===-- Definition of pthread_barrier_t type ------------------------------===//
+//===-- Definition of pthread_barrier_t type --------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,8 +9,7 @@
 #ifndef LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
 #define LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
 
-typedef struct {
-  char padding[88];
-} pthread_barrier_t;
+#include "include/llvm-libc-types/__barrier_type.h"
+typedef __barrier_type pthread_barrier_t;
 
 #endif // LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
diff --git a/libc/src/__support/threads/barrier.cpp b/libc/src/__support/threads/barrier.cpp
index a9253d8c91611..e39fb17637633 100644
--- a/libc/src/__support/threads/barrier.cpp
+++ b/libc/src/__support/threads/barrier.cpp
@@ -14,8 +14,6 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-const int BARRIER_FIRST_EXITED = -1;
-
 int Barrier::init(Barrier *b,
                   [[maybe_unused]] const pthread_barrierattr_t *attr,
                   unsigned count) {
@@ -36,7 +34,10 @@ int Barrier::init(Barrier *b,
   if (err != 0)
     return err;
 
-  Mutex::init(&b->m, false, false, false, false);
+  auto mutex_err = Mutex::init(&b->m, false, false, false, false);
+  if (mutex_err != MutexError::NONE)
+    return EAGAIN;
+
   return 0;
 }
 
@@ -67,7 +68,10 @@ int Barrier::wait() {
     blocking = true;
     entering.broadcast();
     m.unlock();
-    return BARRIER_FIRST_EXITED;
+
+    // POSIX dictates that the barrier should return a special value to just one
+    // thread, so we can arbitrarily choose this thread
+    return PTHREAD_BARRIER_SERIAL_THREAD;
   }
   m.unlock();
 
diff --git a/libc/src/__support/threads/barrier.h b/libc/src/__support/threads/barrier.h
index 5aa99fe405cda..aae811a70e41c 100644
--- a/libc/src/__support/threads/barrier.h
+++ b/libc/src/__support/threads/barrier.h
@@ -9,9 +9,9 @@
 #ifndef LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
 #define LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_BARRIER_H
 
+#include "hdr/pthread_macros.h"
 #include "include/llvm-libc-types/pthread_barrier_t.h"
 #include "include/llvm-libc-types/pthread_barrierattr_t.h"
-#include "src/__support/macros/config.h"
 #include "src/__support/threads/CndVar.h"
 #include "src/__support/threads/mutex.h"
 
@@ -20,9 +20,6 @@ namespace LIBC_NAMESPACE_DECL {
 // NOTE: if the size of this class changes, you must ensure that the size of
 // pthread_barrier_t (found in include/llvm-libc/types/pthread_barrier_t.h) is
 // the same size
-
-extern const int BARRIER_FIRST_EXITED;
-
 class Barrier {
 private:
   unsigned expected;
diff --git a/libc/src/pthread/pthread_barrier_wait.cpp b/libc/src/pthread/pthread_barrier_wait.cpp
index 7e34babdb2579..3d68c4f8938c9 100644
--- a/libc/src/pthread/pthread_barrier_wait.cpp
+++ b/libc/src/pthread/pthread_barrier_wait.cpp
@@ -16,11 +16,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, pthread_barrier_wait, (pthread_barrier_t * b)) {
-  int out = reinterpret_cast<Barrier *>(b)->wait();
-  if (out == BARRIER_FIRST_EXITED)
-    return PTHREAD_BARRIER_SERIAL_THREAD;
-
-  return out;
+  return reinterpret_cast<Barrier *>(b)->wait();
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
index bde1230f5b86d..2ba4d3ac22897 100644
--- a/libc/test/integration/src/pthread/pthread_barrier_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp
@@ -18,68 +18,87 @@
 #include "src/pthread/pthread_mutex_lock.h"
 #include "src/pthread/pthread_mutex_unlock.h"
 #include "src/stdio/printf.h"
+#include "src/string/memset.h"
 
 #include "test/IntegrationTest/test.h"
 
 #include <pthread.h>
 
 pthread_barrier_t barrier;
-
-void smoke_test() {
-  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, 1), 0);
-  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_wait(&barrier),
-            PTHREAD_BARRIER_SERIAL_THREAD);
-  ASSERT_EQ(LIBC_NAMESPACE::pthread_barrier_destroy(&barrier), 0);
-}
-
 LIBC_NAMESPACE::cpp::Atomic<int> counter;
+
 void *increment_counter_and_wait(void *args) {
   counter.fetch_add(1);
-  LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
-  return 0;
+  return reinterpret_cast<void *>(
+      LIBC_NAMESPACE::pthread_barrier_wait(&barrier));
 }
 
-void single_use_barrier() {
+void single_use_barrier_test(int num_threads) {
   counter.set(0);
-  const int NUM_THREADS = 30;
-  pthread_t threads[NUM_THREADS];
+  // create n - 1 ADDITIONAL threads since the current thread will also wait at
+  // the barrier
+  pthread_t threads[num_threads - 1];
+  LIBC_NAMESPACE::memset(&barrier, 0, sizeof(pthread_barrier_t));
   ASSERT_EQ(
-      LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1),
-      0);
+      LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, num_threads), 0);
 
-  for (int i = 0; i < NUM_THREADS; ++i)
+  for (int i = 0; i < num_threads - 1; ++i)
     LIBC_NAMESPACE::pthread_create(&threads[i], nullptr,
                                    increment_counter_and_wait, nullptr);
 
-  LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
-  ASSERT_EQ(counter.load(), NUM_THREADS);
+  uintptr_t return_val_sum =
+      reinterpret_cast<uintptr_t>(increment_counter_and_wait(nullptr));
+  ASSERT_EQ(counter.load(), num_threads);
 
-  for (int i = 0; i < NUM_THREADS; ++i)
-    LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
+  // verify only one thread got the PTHREAD_BARRIER_SERIAL_THREAD return value
+  for (int i = 0; i < num_threads - 1; ++i) {
+    void *ret;
+    LIBC_NAMESPACE::pthread_join(threads[i], &ret);
+    if (reinterpret_cast<uintptr_t>(ret) ==
+        static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)) {
+      return_val_sum += reinterpret_cast<uintptr_t>(ret);
+    } else {
+      ASSERT_EQ(ret, 0);
+    }
+  }
+  ASSERT_EQ(return_val_sum,
+            static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD));
 
   LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);
 }
 
-void reusable_barrier() {
+void reused_barrier_test() {
   counter.set(0);
   const int NUM_THREADS = 30;
   const int REPEAT = 20;
-  pthread_t threads[NUM_THREADS * REPEAT];
+  pthread_t threads[NUM_THREADS - 1]; // subtract 1 for main thread
+  LIBC_NAMESPACE::memset(&barrier, 0, sizeof(pthread_barrier_t));
   ASSERT_EQ(
-      LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1),
-      0);
+      LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS), 0);
 
   for (int i = 0; i < REPEAT; ++i) {
-    for (int j = 0; j < NUM_THREADS; ++j)
-      LIBC_NAMESPACE::pthread_create(&threads[NUM_THREADS * i + j], nullptr,
+    for (int j = 0; j < NUM_THREADS - 1; ++j)
+      LIBC_NAMESPACE::pthread_create(&threads[j], nullptr,
                                      increment_counter_and_wait, nullptr);
 
-    LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
+    uintptr_t return_val_sum =
+        reinterpret_cast<uintptr_t>(increment_counter_and_wait(nullptr));
     ASSERT_EQ(counter.load(), NUM_THREADS * (i + 1));
-  }
 
-  for (int i = 0; i < NUM_THREADS * REPEAT; ++i)
-    LIBC_NAMESPACE::pthread_join(threads[i], nullptr);
+    // verify only one thread got the PTHREAD_BARRIER_SERIAL_THREAD return value
+    for (int i = 0; i < NUM_THREADS - 1; ++i) {
+      void *ret;
+      LIBC_NAMESPACE::pthread_join(threads[i], &ret);
+      if (reinterpret_cast<uintptr_t>(ret) ==
+          static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)) {
+        return_val_sum += reinterpret_cast<uintptr_t>(ret);
+      } else {
+        ASSERT_EQ(ret, 0);
+      }
+    }
+    ASSERT_EQ(return_val_sum,
+              static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD));
+  }
 
   LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);
 }
@@ -89,29 +108,11 @@ void *barrier_wait(void *in) {
       LIBC_NAMESPACE::pthread_barrier_wait(&barrier));
 }
 
-// verify that only one of the wait() calls return PTHREAD_BARRIER_SERIAL_THREAD
-// with the rest returning 0
-void one_nonzero_wait_returnval() {
-  const int NUM_THREADS = 30;
-  pthread_t threads[NUM_THREADS];
-  LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS + 1);
-  for (int i = 0; i < NUM_THREADS; ++i)
-    LIBC_NAMESPACE::pthread_create(&threads[i], nullptr, barrier_wait, nullptr);
-
-  uintptr_t retsum = LIBC_NAMESPACE::pthread_barrier_wait(&barrier);
-  for (int i = 0; i < NUM_THREADS; ++i) {
-    void *ret;
-    LIBC_NAMESPACE::pthread_join(threads[i], &ret);
-    retsum += reinterpret_cast<uintptr_t>(ret);
-  }
-
-  ASSERT_EQ(static_cast<int>(retsum), PTHREAD_BARRIER_SERIAL_THREAD);
-}
-
 TEST_MAIN() {
-  smoke_test();
-  single_use_barrier();
-  reusable_barrier();
-  one_nonzero_wait_returnval();
+  // don't create any additional threads; only use main thread
+  single_use_barrier_test(1);
+
+  single_use_barrier_test(30);
+  reused_barrier_test();
   return 0;
 }

>From 1a828f403477d63b986bae8fd1deb9c3f269270b Mon Sep 17 00:00:00 2001
From: Uzair Nawaz <uzairnawaz at google.com>
Date: Tue, 22 Jul 2025 21:46:16 +0000
Subject: [PATCH 10/10] formatting

---
 libc/hdr/pthread_macros.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/hdr/pthread_macros.h b/libc/hdr/pthread_macros.h
index b0bab73687e3b..f913015abd31c 100644
--- a/libc/hdr/pthread_macros.h
+++ b/libc/hdr/pthread_macros.h
@@ -1,4 +1,4 @@
-//===-- Definition of macros from pthread.h ----------------------------------===//
+//===-- Definition of macros from pthread.h -------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.



More information about the libc-commits mailing list