Skip to content

[libc] Implement barriers for pthreads #148948

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jul 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions libc/hdr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions libc/hdr/pthread_macros.h
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions libc/hdr/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions libc/hdr/types/pthread_barrier_t.h
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions libc/hdr/types/pthread_barrierattr_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Definition of macros from pthread_barrierattr_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
2 changes: 2 additions & 0 deletions libc/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions libc/include/llvm-libc-macros/pthread-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -53,6 +54,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)
Expand Down
21 changes: 21 additions & 0 deletions libc/include/llvm-libc-types/__barrier_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Definition of __barrier_type 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
15 changes: 15 additions & 0 deletions libc/include/llvm-libc-types/pthread_barrier_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//===-- 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

#include "include/llvm-libc-types/__barrier_type.h"
typedef __barrier_type pthread_barrier_t;

#endif // LLVM_LIBC_TYPES_PTHREAD_BARRIER_T_H
16 changes: 16 additions & 0 deletions libc/include/llvm-libc-types/pthread_barrierattr_t.h
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions libc/include/pthread.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions libc/src/__support/threads/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,14 @@ add_object_library(
libc.src.__support.threads.linux.raw_mutex
libc.src.__support.CPP.mutex
)

add_object_library(
barrier
HDRS
barrier.h
SRCS
barrier.cpp
DEPENDS
libc.src.__support.threads.CndVar
libc.src.__support.threads.mutex
)
85 changes: 85 additions & 0 deletions libc/src/__support/threads/linux/barrier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//===-- 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.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/__support/threads/linux/barrier.h"
#include "hdr/errno_macros.h"
#include "src/__support/threads/CndVar.h"
#include "src/__support/threads/mutex.h"

namespace LIBC_NAMESPACE_DECL {

int Barrier::init(Barrier *b,
[[maybe_unused]] const pthread_barrierattr_t *attr,
unsigned count) {
LIBC_ASSERT(attr == nullptr); // TODO implement barrierattr
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;

auto mutex_err = Mutex::init(&b->m, false, false, false, false);
if (mutex_err != MutexError::NONE)
return EAGAIN;

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) {
// 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--;

if (waiting == 0) {
// all threads have exited the barrier, let's let the ones waiting to enter
// continue
blocking = true;
entering.broadcast();
m.unlock();

// 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();

return 0;
}

int Barrier::destroy(Barrier *b) {
CndVar::destroy(&b->entering);
CndVar::destroy(&b->exiting);
Mutex::destroy(&b->m);
return 0;
}

} // namespace LIBC_NAMESPACE_DECL
50 changes: 50 additions & 0 deletions libc/src/__support/threads/linux/barrier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//===-- 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 "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/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();
};

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
Loading
Loading