Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
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
2 changes: 2 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 16 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,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
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/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
83 changes: 83 additions & 0 deletions libc/src/__support/threads/barrier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//===-- 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/barrier.h"
#include "barrier.h"
#include "hdr/errno_macros.h"
#include "src/__support/threads/mutex.h"

namespace LIBC_NAMESPACE_DECL {

const int BARRIER_FIRST_EXITED = -1;

int Barrier::init(Barrier *b,
const pthread_barrierattr_t *attr __attribute__((unused)),
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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The answer might be "no", but: Isn't there a macro for this "check error and return it if it's nonzero" construct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe there is something for this specific pattern, or at least I haven't encountered one yet (also skimmed through the __support/macros folder and I don't see anything like this unfortunately).


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;
exiting.broadcast();
} else {
// block threads until waiting = expected
while (blocking) {
exiting.wait(&m);
}
}
waiting--;

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

return 0;
}

int Barrier::destroy(Barrier *b) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this have a return value?

Copy link
Contributor Author

@uzairnawaz uzairnawaz Jul 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to have pthread_barrier_destroy forward the return value from this function.

According to the standard (https://pubs.opengroup.org/onlinepubs/9799919799/): "The results are undefined if pthread_barrier_destroy() is called when any thread is blocked on the barrier, or if this function is called with an uninitialized barrier."

However:
"If an implementation detects that the value specified by the barrier argument to pthread_barrier_destroy() does not refer to an initialized barrier object, it is recommended that the function should fail and report an [EINVAL] error.

If an implementation detects that the value specified by the attr argument to pthread_barrier_init() does not refer to an initialized barrier attributes object, it is recommended that the function should fail and report an [EINVAL] error."

Since the standard doesn't actually require these error codes, I choose to just always return 0, but a future patch could include these error codes, so I think it makes sense to keep the return value.

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

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

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;
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
34 changes: 34 additions & 0 deletions libc/src/pthread/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions libc/src/pthread/pthread_barrier_destroy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- 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_barrier_destroy.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
21 changes: 21 additions & 0 deletions libc/src/pthread/pthread_barrier_destroy.h
Original file line number Diff line number Diff line change
@@ -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
31 changes: 31 additions & 0 deletions libc/src/pthread/pthread_barrier_init.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- 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_barrier_init.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
23 changes: 23 additions & 0 deletions libc/src/pthread/pthread_barrier_init.h
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading