[libc-commits] [libc] [libc][pthreads] pthread_cond_{destroy|init|signal|wait} (PR #88583)
Nick Desaulniers via libc-commits
libc-commits at lists.llvm.org
Fri Apr 12 14:30:10 PDT 2024
https://github.com/nickdesaulniers created https://github.com/llvm/llvm-project/pull/88583
Basic support for pthread condition variables. Does not support:
- pthread_cond_{timedwait|broadcast}
- non-nullptr pthread_condattr_t values for pthread_cond_init
Relies on the existing CndVar, which should be moved from
libc/src/threads/linux/CndVar.h to libc/src/__support/threads/.
Link: #85282
Link: #88580
Link: #88581
Link: #88582
>From ad27cf171f1604a526a406ce8fb6840b9023c781 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Fri, 12 Apr 2024 11:40:06 -0700
Subject: [PATCH] [libc][pthreads] pthread_cond_{destroy|init|signal|wait}
Basic support for pthread condition variables. Does not support:
- pthread_cond_{timedwait|broadcast}
- non-nullptr pthread_condattr_t values for pthread_cond_init
Relies on the existing CndVar, which should be moved from
libc/src/threads/linux/CndVar.h to libc/src/__support/threads/.
Link: #85282
Link: #88580
Link: #88581
Link: #88582
---
libc/config/linux/api.td | 31 +++++++--
libc/config/linux/x86_64/entrypoints.txt | 4 ++
libc/include/CMakeLists.txt | 2 +
libc/include/llvm-libc-types/CMakeLists.txt | 2 +
libc/include/llvm-libc-types/pthread_cond_t.h | 19 ++++++
.../llvm-libc-types/pthread_condattr_t.h | 15 ++++
libc/spec/posix.td | 52 +++++++++++++-
libc/src/pthread/CMakeLists.txt | 48 +++++++++++++
libc/src/pthread/pthread_cond_destroy.cpp | 30 ++++++++
libc/src/pthread/pthread_cond_destroy.h | 20 ++++++
libc/src/pthread/pthread_cond_init.cpp | 37 ++++++++++
libc/src/pthread/pthread_cond_init.h | 20 ++++++
libc/src/pthread/pthread_cond_signal.cpp | 35 ++++++++++
libc/src/pthread/pthread_cond_signal.h | 20 ++++++
libc/src/pthread/pthread_cond_wait.cpp | 37 ++++++++++
libc/src/pthread/pthread_cond_wait.h | 20 ++++++
.../integration/src/pthread/CMakeLists.txt | 20 ++++++
.../src/pthread/pthread_cond_test.cpp | 68 +++++++++++++++++++
18 files changed, 473 insertions(+), 7 deletions(-)
create mode 100644 libc/include/llvm-libc-types/pthread_cond_t.h
create mode 100644 libc/include/llvm-libc-types/pthread_condattr_t.h
create mode 100644 libc/src/pthread/pthread_cond_destroy.cpp
create mode 100644 libc/src/pthread/pthread_cond_destroy.h
create mode 100644 libc/src/pthread/pthread_cond_init.cpp
create mode 100644 libc/src/pthread/pthread_cond_init.h
create mode 100644 libc/src/pthread/pthread_cond_signal.cpp
create mode 100644 libc/src/pthread/pthread_cond_signal.h
create mode 100644 libc/src/pthread/pthread_cond_wait.cpp
create mode 100644 libc/src/pthread/pthread_cond_wait.h
create mode 100644 libc/test/integration/src/pthread/pthread_cond_test.cpp
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 9964971f191b75..c9d562a37f2dfc 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -175,6 +175,8 @@ def PThreadAPI : PublicAPI<"pthread.h"> {
"__pthread_start_t",
"__pthread_tss_dtor_t",
"pthread_attr_t",
+ "pthread_cond_t",
+ "pthread_condattr_t",
"pthread_mutex_t",
"pthread_mutexattr_t",
"pthread_t",
@@ -241,10 +243,31 @@ def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> {
}
def SysTypesAPI : PublicAPI<"sys/types.h"> {
- let Types = ["blkcnt_t", "blksize_t", "clockid_t", "dev_t", "gid_t", "ino_t",
- "mode_t", "nlink_t", "off_t", "pid_t", "pthread_attr_t", "pthread_key_t",
- "pthread_mutex_t", "pthread_mutexattr_t", "pthread_once_t", "pthread_t",
- "size_t", "ssize_t", "suseconds_t", "time_t", "uid_t"];
+ let Types = [
+ "blkcnt_t",
+ "blksize_t",
+ "clockid_t",
+ "dev_t",
+ "gid_t",
+ "ino_t",
+ "mode_t",
+ "nlink_t",
+ "off_t",
+ "pid_t",
+ "pthread_attr_t",
+ "pthread_cond_t",
+ "pthread_condattr_t",
+ "pthread_key_t",
+ "pthread_mutex_t",
+ "pthread_mutexattr_t",
+ "pthread_once_t",
+ "pthread_t",
+ "size_t",
+ "ssize_t",
+ "suseconds_t",
+ "time_t",
+ "uid_t",
+ ];
}
def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> {
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 6bb53cb76220fc..45e92ece6da6b4 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -634,6 +634,10 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_attr_setguardsize
libc.src.pthread.pthread_attr_setstack
libc.src.pthread.pthread_attr_setstacksize
+ libc.src.pthread.pthread_cond_destroy
+ libc.src.pthread.pthread_cond_init
+ libc.src.pthread.pthread_cond_signal
+ libc.src.pthread.pthread_cond_wait
libc.src.pthread.pthread_create
libc.src.pthread.pthread_detach
libc.src.pthread.pthread_equal
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 02c7dc8fbc0b33..c0cbb752f694c0 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -321,6 +321,8 @@ add_gen_header(
.llvm-libc-types.__pthread_start_t
.llvm-libc-types.__pthread_tss_dtor_t
.llvm-libc-types.pthread_attr_t
+ .llvm-libc-types.pthread_cond_t
+ .llvm-libc-types.pthread_condattr_t
.llvm-libc-types.pthread_mutex_t
.llvm-libc-types.pthread_mutexattr_t
.llvm-libc-types.pthread_t
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 93a79e1477b337..90239ccf9c10f9 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -51,6 +51,8 @@ add_header(posix_spawnattr_t HDR posix_spawnattr_t.h)
add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_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_cond_t HDR pthread_cond_t.h DEPENDS .pthread_mutex_t)
+add_header(pthread_condattr_t HDR pthread_condattr_t.h)
add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h)
add_header(pthread_once_t HDR pthread_once_t.h DEPENDS .__futex_word)
diff --git a/libc/include/llvm-libc-types/pthread_cond_t.h b/libc/include/llvm-libc-types/pthread_cond_t.h
new file mode 100644
index 00000000000000..60ca0ca6164c61
--- /dev/null
+++ b/libc/include/llvm-libc-types/pthread_cond_t.h
@@ -0,0 +1,19 @@
+//===-- Definition of pthread_cond_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_COND_T_H
+#define LLVM_LIBC_TYPES_PTHREAD_COND_T_H
+
+#include "pthread_mutex_t.h"
+
+typedef struct {
+ void *__qfront;
+ void *__qback;
+ pthread_mutex_t __mtx;
+} pthread_cond_t;
+
+#endif // LLVM_LIBC_TYPES_PTHREAD_COND_T_H
diff --git a/libc/include/llvm-libc-types/pthread_condattr_t.h b/libc/include/llvm-libc-types/pthread_condattr_t.h
new file mode 100644
index 00000000000000..19d5f9ecf6f7cb
--- /dev/null
+++ b/libc/include/llvm-libc-types/pthread_condattr_t.h
@@ -0,0 +1,15 @@
+//===-- Definition of pthread_condattr_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_CONDATTR_T_H
+#define LLVM_LIBC_TYPES_PTHREAD_CONDATTR_T_H
+
+typedef struct {
+ int pshared;
+} pthread_condattr_t;
+
+#endif // LLVM_LIBC_TYPES_PTHREAD_CONDATTR_T_H
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 45f7ecfe84e98e..fe0c90239d613d 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -117,6 +117,11 @@ def POSIX : StandardSpec<"POSIX"> {
ConstType ConstPThreadMutexTPtr = ConstType<PThreadMutexTPtr>;
ConstType ConstRestrictedPThreadMutexTPtr = ConstType<RestrictedPThreadMutexTPtr>;
+ NamedType PThreadCondTType = NamedType<"pthread_cond_t">;
+ PtrType PThreadCondTPtr = PtrType<PThreadCondTType>;
+ NamedType PThreadCondAttrTType = NamedType<"pthread_condattr_t">;
+ PtrType PThreadCondAttrTPtr = PtrType<PThreadCondAttrTType>;
+
PtrType PThreadTPtr = PtrType<PThreadTType>;
RestrictedPtrType RestrictedPThreadTPtr = RestrictedPtrType<PThreadTType>;
@@ -976,6 +981,8 @@ def POSIX : StandardSpec<"POSIX"> {
[
AtForkCallbackT,
PThreadAttrTType,
+ PThreadCondTType,
+ PThreadCondAttrTType,
PThreadKeyT,
PThreadMutexAttrTType,
PThreadMutexTType,
@@ -1042,6 +1049,23 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<IntType>,
[ArgSpec<PThreadAttrTPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
>,
+ FunctionSpec<
+ "pthread_cond_destroy",
+ RetValSpec<IntType>,
+ [ArgSpec<PThreadCondTPtr>]
+ >,
+ FunctionSpec<"pthread_cond_init",
+ RetValSpec<IntType>,
+ [ArgSpec<PThreadCondTPtr>, ArgSpec<PThreadCondAttrTPtr>]
+ >,
+ FunctionSpec<"pthread_cond_signal",
+ RetValSpec<IntType>,
+ [ArgSpec<PThreadCondTPtr>]
+ >,
+ FunctionSpec<"pthread_cond_wait",
+ RetValSpec<IntType>,
+ [ArgSpec<PThreadCondTPtr>, ArgSpec<PThreadMutexTPtr>]
+ >,
FunctionSpec<
"pthread_create",
RetValSpec<IntType>,
@@ -1517,9 +1541,31 @@ def POSIX : StandardSpec<"POSIX"> {
HeaderSpec SysTypes = HeaderSpec<
"sys/types.h",
[], // Macros
- [BlkCntT, BlkSizeT, ClockIdT, DevT, GidT, InoT, ModeTType, NLinkT, OffTType, PidT,
- PThreadAttrTType, PThreadKeyT, PThreadMutexTType, PThreadMutexAttrTType, PThreadOnceT, PThreadTType,
- SizeTType, SSizeTType, SuSecondsT, TimeTType, UidT],
+ [
+ BlkCntT,
+ BlkSizeT,
+ ClockIdT,
+ DevT,
+ GidT,
+ InoT,
+ ModeTType,
+ NLinkT,
+ OffTType,
+ PThreadAttrTType,
+ PThreadCondAttrTType,
+ PThreadCondTType,
+ PThreadKeyT,
+ PThreadMutexAttrTType,
+ PThreadMutexTType,
+ PThreadOnceT,
+ PThreadTType,
+ PidT,
+ SSizeTType,
+ SizeTType,
+ SuSecondsT,
+ TimeTType,
+ UidT
+ ], // Types
[], // Enumerations
[] // Functions
>;
diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt
index d5e6c802a84523..c467803d5ca044 100644
--- a/libc/src/pthread/CMakeLists.txt
+++ b/libc/src/pthread/CMakeLists.txt
@@ -266,6 +266,54 @@ add_entrypoint_object(
-fno-omit-frame-pointer
)
+add_entrypoint_object(
+ pthread_cond_destroy
+ SRCS
+ pthread_cond_destroy.cpp
+ HDRS
+ pthread_cond_destroy.h
+ DEPENDS
+ libc.include.errno
+ libc.include.pthread
+ libc.include.threads
+)
+
+add_entrypoint_object(
+ pthread_cond_init
+ SRCS
+ pthread_cond_init.cpp
+ HDRS
+ pthread_cond_init.h
+ DEPENDS
+ libc.include.errno
+ libc.include.pthread
+ libc.include.threads
+)
+
+add_entrypoint_object(
+ pthread_cond_signal
+ SRCS
+ pthread_cond_signal.cpp
+ HDRS
+ pthread_cond_signal.h
+ DEPENDS
+ libc.include.errno
+ libc.include.pthread
+ libc.include.threads
+)
+
+add_entrypoint_object(
+ pthread_cond_wait
+ SRCS
+ pthread_cond_wait.cpp
+ HDRS
+ pthread_cond_wait.h
+ DEPENDS
+ libc.include.errno
+ libc.include.pthread
+ libc.include.threads
+)
+
add_entrypoint_object(
pthread_join
SRCS
diff --git a/libc/src/pthread/pthread_cond_destroy.cpp b/libc/src/pthread/pthread_cond_destroy.cpp
new file mode 100644
index 00000000000000..f2038df1a64fe6
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_destroy.cpp
@@ -0,0 +1,30 @@
+//===-- Linux implementation of the pthread_cond_wait 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_cond_destroy.h"
+
+#include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL
+#include "src/__support/common.h"
+#include "src/threads/linux/CndVar.h"
+
+#include <pthread.h> // pthread_cond_t
+// TODO: https://github.com/llvm/llvm-project/issues/88580
+#include <threads.h> // thrd_success
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, pthread_cond_destroy, (pthread_cond_t * cond)) {
+ if (!cond)
+ return EINVAL;
+
+ CndVar *C = reinterpret_cast<CndVar *>(cond);
+ CndVar::destroy(C);
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/pthread/pthread_cond_destroy.h b/libc/src/pthread/pthread_cond_destroy.h
new file mode 100644
index 00000000000000..5a987e3f8b3c17
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_destroy.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_cond_destroy function -*- 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_COND_DESTROY_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_DESTROY_H
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE {
+
+int pthread_cond_destroy(pthread_cond_t *cond);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_DESTROY_H
diff --git a/libc/src/pthread/pthread_cond_init.cpp b/libc/src/pthread/pthread_cond_init.cpp
new file mode 100644
index 00000000000000..d3bb78925c9cf9
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_init.cpp
@@ -0,0 +1,37 @@
+//===-- Linux implementation of the pthread_cond_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_cond_init.h"
+
+#include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL
+#include "src/__support/common.h"
+#include "src/threads/linux/CndVar.h"
+
+#include <pthread.h> // pthread_cond_t, pthread_condattr_t
+// TODO: https://github.com/llvm/llvm-project/issues/88580
+#include <threads.h> // thrd_succes
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, pthread_cond_init,
+ (pthread_cond_t * cond, const pthread_condattr_t *attr)) {
+ // TODO: properly support pthread_condattr_t.
+ // https://github.com/llvm/llvm-project/issues/88582
+ if (attr)
+ return EINVAL;
+
+ CndVar *C = reinterpret_cast<CndVar *>(cond);
+ int ret = CndVar::init(C);
+ if (ret == thrd_success)
+ return 0;
+
+ // TODO: translate error codes?
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/pthread/pthread_cond_init.h b/libc/src/pthread/pthread_cond_init.h
new file mode 100644
index 00000000000000..2365ae3597175e
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_init.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_cond_init function ----*- 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_COND_INIT_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_INIT_H
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE {
+
+int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_INIT_H
diff --git a/libc/src/pthread/pthread_cond_signal.cpp b/libc/src/pthread/pthread_cond_signal.cpp
new file mode 100644
index 00000000000000..b770d7119015c4
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_signal.cpp
@@ -0,0 +1,35 @@
+//===-- Linux implementation of the pthread_cond_signal 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_cond_signal.h"
+
+#include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL
+#include "src/__support/common.h"
+#include "src/threads/linux/CndVar.h"
+
+#include <pthread.h> // pthread_cond_t
+// TODO: https://github.com/llvm/llvm-project/issues/88580
+#include <threads.h> // thrd_success
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, pthread_cond_signal, (pthread_cond_t * cond)) {
+ if (!cond)
+ return EINVAL;
+
+ CndVar *C = reinterpret_cast<CndVar *>(cond);
+ int ret = C->notify_one();
+
+ if (ret == thrd_success)
+ return 0;
+
+ // TODO: translate error codes.
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/pthread/pthread_cond_signal.h b/libc/src/pthread/pthread_cond_signal.h
new file mode 100644
index 00000000000000..56b3e04a6e2399
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_signal.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_cond_signal function --*- 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_COND_SIGNAL_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_SIGNAL_H
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE {
+
+int pthread_cond_signal(pthread_cond_t *cond);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_SIGNAL_H
diff --git a/libc/src/pthread/pthread_cond_wait.cpp b/libc/src/pthread/pthread_cond_wait.cpp
new file mode 100644
index 00000000000000..dbc4f8ccf3e767
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_wait.cpp
@@ -0,0 +1,37 @@
+//===-- Linux implementation of the pthread_cond_wait 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_cond_wait.h"
+
+#include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL
+#include "src/__support/common.h"
+#include "src/threads/linux/CndVar.h"
+
+#include <pthread.h> // pthread_cond_t, pthread_mutex_t
+// TODO: https://github.com/llvm/llvm-project/issues/88580
+#include <threads.h> // thrd_success
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, pthread_cond_wait,
+ (pthread_cond_t * cond, pthread_mutex_t *mutex)) {
+ if (!cond || !mutex)
+ return EINVAL;
+
+ auto *C = reinterpret_cast<CndVar *>(cond);
+ auto *M = reinterpret_cast<Mutex *>(mutex);
+ int ret = C->wait(M);
+
+ if (ret == thrd_success)
+ return 0;
+
+ // TODO translate error codes
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/pthread/pthread_cond_wait.h b/libc/src/pthread/pthread_cond_wait.h
new file mode 100644
index 00000000000000..809cc49c9f4da6
--- /dev/null
+++ b/libc/src/pthread/pthread_cond_wait.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_cond_wait function ----*- 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_COND_WAIT_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_WAIT_H
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE {
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_WAIT_H
diff --git a/libc/test/integration/src/pthread/CMakeLists.txt b/libc/test/integration/src/pthread/CMakeLists.txt
index a10dc256200d9f..0ddbfd0c796780 100644
--- a/libc/test/integration/src/pthread/CMakeLists.txt
+++ b/libc/test/integration/src/pthread/CMakeLists.txt
@@ -161,3 +161,23 @@ add_integration_test(
libc.src.__support.CPP.array
libc.src.__support.CPP.new
)
+
+add_integration_test(
+ pthread_cond_test
+ SUITE
+ libc-pthread-integration-tests
+ SRCS
+ pthread_cond_test.cpp
+ DEPENDS
+ libc.include.pthread
+ libc.src.pthread.pthread_cond_destroy
+ libc.src.pthread.pthread_cond_init
+ libc.src.pthread.pthread_cond_signal
+ libc.src.pthread.pthread_cond_wait
+ libc.src.pthread.pthread_create
+ libc.src.pthread.pthread_join
+ libc.src.pthread.pthread_mutex_destroy
+ libc.src.pthread.pthread_mutex_init
+ libc.src.pthread.pthread_mutex_lock
+ libc.src.pthread.pthread_mutex_unlock
+)
diff --git a/libc/test/integration/src/pthread/pthread_cond_test.cpp b/libc/test/integration/src/pthread/pthread_cond_test.cpp
new file mode 100644
index 00000000000000..4ab9ffd9b9b64f
--- /dev/null
+++ b/libc/test/integration/src/pthread/pthread_cond_test.cpp
@@ -0,0 +1,68 @@
+// TODO: license block
+
+#include "test/IntegrationTest/test.h"
+
+#include "src/pthread/pthread_cond_destroy.h"
+#include "src/pthread/pthread_cond_init.h"
+#include "src/pthread/pthread_cond_signal.h"
+#include "src/pthread/pthread_cond_wait.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 <pthread.h>
+
+pthread_mutex_t waiter_mtx, main_thread_mtx;
+pthread_cond_t waiter_cnd, main_thread_cnd;
+
+void *waiter_thread_func(void *) {
+ LIBC_NAMESPACE::pthread_mutex_lock(&waiter_mtx);
+
+ LIBC_NAMESPACE::pthread_mutex_lock(&main_thread_mtx);
+ LIBC_NAMESPACE::pthread_cond_signal(&main_thread_cnd);
+ LIBC_NAMESPACE::pthread_mutex_unlock(&main_thread_mtx);
+
+ LIBC_NAMESPACE::pthread_cond_wait(&waiter_cnd, &waiter_mtx);
+ LIBC_NAMESPACE::pthread_mutex_unlock(&waiter_mtx);
+
+ return reinterpret_cast<void *>(0x600D);
+}
+
+void single_waiter_test() {
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&waiter_mtx, nullptr), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&main_thread_mtx, nullptr), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_cond_init(&waiter_cnd, nullptr), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_cond_init(&main_thread_cnd, nullptr), 0);
+
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&main_thread_mtx), 0);
+
+ pthread_t waiter_thread;
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&waiter_thread, nullptr,
+ waiter_thread_func, nullptr),
+ 0);
+
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_cond_wait(&main_thread_cnd, &main_thread_mtx), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&main_thread_mtx), 0);
+
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&waiter_mtx), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_cond_signal(&waiter_cnd), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&waiter_mtx), 0);
+
+ void *retval;
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_join(waiter_thread, &retval), 0);
+ ASSERT_EQ(reinterpret_cast<long>(retval), 0x600D);
+
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_destroy(&waiter_mtx), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_destroy(&main_thread_mtx), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_cond_destroy(&waiter_cnd), 0);
+ ASSERT_EQ(LIBC_NAMESPACE::pthread_cond_destroy(&main_thread_cnd), 0);
+}
+
+TEST_MAIN() {
+ single_waiter_test();
+ return 0;
+}
More information about the libc-commits
mailing list