[libc-commits] [libc] 44df89c - [libc] add pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock … (#100543)
via libc-commits
libc-commits at lists.llvm.org
Sun Jul 28 11:58:13 PDT 2024
Author: Eric977
Date: 2024-07-28T11:58:09-07:00
New Revision: 44df89cc30fc462dcb821929c6d5459688ffe545
URL: https://github.com/llvm/llvm-project/commit/44df89cc30fc462dcb821929c6d5459688ffe545
DIFF: https://github.com/llvm/llvm-project/commit/44df89cc30fc462dcb821929c6d5459688ffe545.diff
LOG: [libc] add pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock … (#100543)
Added:
libc/src/pthread/pthread_rwlock_clockrdlock.cpp
libc/src/pthread/pthread_rwlock_clockrdlock.h
libc/src/pthread/pthread_rwlock_clockwrlock.cpp
libc/src/pthread/pthread_rwlock_clockwrlock.h
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/docs/dev/undefined_behavior.rst
libc/newhdrgen/yaml/pthread.yaml
libc/spec/posix.td
libc/src/pthread/CMakeLists.txt
libc/test/integration/src/pthread/CMakeLists.txt
libc/test/integration/src/pthread/pthread_rwlock_test.cpp
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 77da994d8dfdf..4e7b23225f54e 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -692,6 +692,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_mutexattr_setrobust
libc.src.pthread.pthread_mutexattr_settype
libc.src.pthread.pthread_once
+ libc.src.pthread.pthread_rwlock_clockrdlock
+ libc.src.pthread.pthread_rwlock_clockwrlock
libc.src.pthread.pthread_rwlock_destroy
libc.src.pthread.pthread_rwlock_init
libc.src.pthread.pthread_rwlock_rdlock
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 3ec166fc0096c..04b8b3bc4ce39 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -703,6 +703,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_mutexattr_setrobust
libc.src.pthread.pthread_mutexattr_settype
libc.src.pthread.pthread_once
+ libc.src.pthread.pthread_rwlock_clockrdlock
+ libc.src.pthread.pthread_rwlock_clockwrlock
libc.src.pthread.pthread_rwlock_destroy
libc.src.pthread.pthread_rwlock_init
libc.src.pthread.pthread_rwlock_rdlock
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index fe3bd7a757e8f..fa656d946eceb 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -790,6 +790,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_mutexattr_setrobust
libc.src.pthread.pthread_mutexattr_settype
libc.src.pthread.pthread_once
+ libc.src.pthread.pthread_rwlock_clockrdlock
+ libc.src.pthread.pthread_rwlock_clockwrlock
libc.src.pthread.pthread_rwlock_destroy
libc.src.pthread.pthread_rwlock_init
libc.src.pthread.pthread_rwlock_rdlock
diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst
index 3faae3134ce2a..9f50545d745d6 100644
--- a/libc/docs/dev/undefined_behavior.rst
+++ b/libc/docs/dev/undefined_behavior.rst
@@ -93,3 +93,8 @@ direction in this case.
Non-const Constant Return Values
--------------------------------
Some libc functions, like ``dlerror()``, return ``char *`` instead of ``const char *`` and then tell the caller they promise not to to modify this value. Any modification of this value is undefined behavior.
+
+Unrecognized ``clockid_t`` values for ``pthread_rwlock_clock*`` APIs
+----------------------------------------------------------------------
+POSIX.1-2024 only demands support for ``CLOCK_REALTIME`` and ``CLOCK_MONOTONIC``. Currently,
+as in LLVM libc, if other clock ids are used, they will be treated as monotonic clocks.
diff --git a/libc/newhdrgen/yaml/pthread.yaml b/libc/newhdrgen/yaml/pthread.yaml
index 292d91751e406..d492dfcbd51eb 100644
--- a/libc/newhdrgen/yaml/pthread.yaml
+++ b/libc/newhdrgen/yaml/pthread.yaml
@@ -370,6 +370,20 @@ functions:
arguments:
- type: pthread_rwlock_t *__restrict
- type: const struct timespec *__restrict
+ - name: pthread_rwlock_clockrdlock
+ standards: POSIX
+ return_type: int
+ arguments:
+ - type: pthread_rwlock_t *__restrict
+ - type: clockid_t
+ - type: const struct timespec *__restrict
+ - name: pthread_rwlock_clockwrlock
+ standards: POSIX
+ return_type: int
+ arguments:
+ - type: pthread_rwlock_t *__restrict
+ - type: clockid_t
+ - type: const struct timespec *__restrict
- name: pthread_rwlock_rdlock
standards: POSIX
return_type: int
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 1878b1ee2ae41..1b7e18e999600 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -1325,6 +1325,16 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<IntType>,
[ArgSpec<RestrictedPThreadRWLockTPtr>, ArgSpec<ConstRestrictStructTimeSpecPtr>]
>,
+ FunctionSpec<
+ "pthread_rwlock_clockrdlock",
+ RetValSpec<IntType>,
+ [ArgSpec<RestrictedPThreadRWLockTPtr>, ArgSpec<ClockIdT>, ArgSpec<ConstRestrictStructTimeSpecPtr>]
+ >,
+ FunctionSpec<
+ "pthread_rwlock_clockwrlock",
+ RetValSpec<IntType>,
+ [ArgSpec<RestrictedPThreadRWLockTPtr>, ArgSpec<ClockIdT>, ArgSpec<ConstRestrictStructTimeSpecPtr>]
+ >,
FunctionSpec<
"pthread_rwlock_rdlock",
RetValSpec<IntType>,
diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt
index dc748b22e0378..70d10e6c4e3f8 100644
--- a/libc/src/pthread/CMakeLists.txt
+++ b/libc/src/pthread/CMakeLists.txt
@@ -556,6 +556,28 @@ add_entrypoint_object(
libc.src.__support.threads.linux.rwlock
)
+add_entrypoint_object(
+ pthread_rwlock_clockrdlock
+ SRCS
+ pthread_rwlock_clockrdlock.cpp
+ HDRS
+ pthread_rwlock_clockrdlock.h
+ DEPENDS
+ libc.include.pthread
+ libc.src.__support.threads.linux.rwlock
+)
+
+add_entrypoint_object(
+ pthread_rwlock_clockwrlock
+ SRCS
+ pthread_rwlock_clockwrlock.cpp
+ HDRS
+ pthread_rwlock_clockwrlock.h
+ DEPENDS
+ libc.include.pthread
+ libc.src.__support.threads.linux.rwlock
+)
+
add_entrypoint_object(
pthread_rwlock_timedrdlock
SRCS
diff --git a/libc/src/pthread/pthread_rwlock_clockrdlock.cpp b/libc/src/pthread/pthread_rwlock_clockrdlock.cpp
new file mode 100644
index 0000000000000..1e44e6d7694f6
--- /dev/null
+++ b/libc/src/pthread/pthread_rwlock_clockrdlock.cpp
@@ -0,0 +1,50 @@
+//===-- Implementation of the Rwlock's clockrdlock 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/pthread/pthread_rwlock_clockrdlock.h"
+
+#include "hdr/errno_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/linux/rwlock.h"
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+static_assert(
+ sizeof(RwLock) == sizeof(pthread_rwlock_t) &&
+ alignof(RwLock) == alignof(pthread_rwlock_t),
+ "The public pthread_rwlock_t type must be of the same size and alignment "
+ "as the internal rwlock type.");
+
+LLVM_LIBC_FUNCTION(int, pthread_rwlock_clockrdlock,
+ (pthread_rwlock_t * rwlock, clockid_t clockid,
+ const timespec *abstime)) {
+ if (!rwlock)
+ return EINVAL;
+ if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_REALTIME)
+ return EINVAL;
+ bool is_realtime = (clockid == CLOCK_REALTIME);
+ RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
+ LIBC_ASSERT(abstime && "clockrdlock called with a null timeout");
+ auto timeout = internal::AbsTimeout::from_timespec(
+ *abstime, /*is_realtime=*/is_realtime);
+ if (LIBC_LIKELY(timeout.has_value()))
+ return static_cast<int>(rw->read_lock(timeout.value()));
+
+ switch (timeout.error()) {
+ case internal::AbsTimeout::Error::Invalid:
+ return EINVAL;
+ case internal::AbsTimeout::Error::BeforeEpoch:
+ return ETIMEDOUT;
+ }
+ __builtin_unreachable();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pthread/pthread_rwlock_clockrdlock.h b/libc/src/pthread/pthread_rwlock_clockrdlock.h
new file mode 100644
index 0000000000000..8fbd3b089a111
--- /dev/null
+++ b/libc/src/pthread/pthread_rwlock_clockrdlock.h
@@ -0,0 +1,23 @@
+//===-- Implementation header for Rwlock's clockrdlock 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_RWLOCK_CLOCKRDLOCK_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_CLOCKRDLOCK_H
+
+#include "src/__support/macros/config.h"
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pthread_rwlock_clockrdlock(pthread_rwlock_t *__restrict rwlock,
+ clockid_t clockid,
+ const timespec *__restrict abstime);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_CLOCKRDLOCK_H
diff --git a/libc/src/pthread/pthread_rwlock_clockwrlock.cpp b/libc/src/pthread/pthread_rwlock_clockwrlock.cpp
new file mode 100644
index 0000000000000..8f58c7f24bb10
--- /dev/null
+++ b/libc/src/pthread/pthread_rwlock_clockwrlock.cpp
@@ -0,0 +1,51 @@
+//===-- Implementation of the Rwlock's clockwrlock 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/pthread/pthread_rwlock_clockwrlock.h"
+
+#include "hdr/errno_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/threads/linux/rwlock.h"
+#include "src/__support/time/linux/abs_timeout.h"
+
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+static_assert(
+ sizeof(RwLock) == sizeof(pthread_rwlock_t) &&
+ alignof(RwLock) == alignof(pthread_rwlock_t),
+ "The public pthread_rwlock_t type must be of the same size and alignment "
+ "as the internal rwlock type.");
+
+LLVM_LIBC_FUNCTION(int, pthread_rwlock_clockwrlock,
+ (pthread_rwlock_t * rwlock, clockid_t clockid,
+ const timespec *abstime)) {
+ if (!rwlock)
+ return EINVAL;
+ if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_REALTIME)
+ return EINVAL;
+ bool is_realtime = (clockid == CLOCK_REALTIME);
+ RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
+ LIBC_ASSERT(abstime && "clockwrlock called with a null timeout");
+ auto timeout = internal::AbsTimeout::from_timespec(
+ *abstime, /*is_realtime=*/is_realtime);
+ if (LIBC_LIKELY(timeout.has_value()))
+ return static_cast<int>(rw->write_lock(timeout.value()));
+
+ switch (timeout.error()) {
+ case internal::AbsTimeout::Error::Invalid:
+ return EINVAL;
+ case internal::AbsTimeout::Error::BeforeEpoch:
+ return ETIMEDOUT;
+ }
+ __builtin_unreachable();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pthread/pthread_rwlock_clockwrlock.h b/libc/src/pthread/pthread_rwlock_clockwrlock.h
new file mode 100644
index 0000000000000..cb3fa3909fd2b
--- /dev/null
+++ b/libc/src/pthread/pthread_rwlock_clockwrlock.h
@@ -0,0 +1,23 @@
+//===-- Implementation header for Rwlock's clockwrlock 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_RWLOCK_CLOCKWRLOCK_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_CLOCKWRLOCK_H
+
+#include "src/__support/macros/config.h"
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pthread_rwlock_clockwrlock(pthread_rwlock_t *__restrict rwlock,
+ clockid_t clockid,
+ const timespec *__restrict abstime);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_CLOCKWRLOCK_H
diff --git a/libc/test/integration/src/pthread/CMakeLists.txt b/libc/test/integration/src/pthread/CMakeLists.txt
index fa5fd3ad55d5f..eb26822597c2f 100644
--- a/libc/test/integration/src/pthread/CMakeLists.txt
+++ b/libc/test/integration/src/pthread/CMakeLists.txt
@@ -32,9 +32,11 @@ add_integration_test(
libc.src.pthread.pthread_rwlock_rdlock
libc.src.pthread.pthread_rwlock_tryrdlock
libc.src.pthread.pthread_rwlock_timedrdlock
+ libc.src.pthread.pthread_rwlock_clockrdlock
libc.src.pthread.pthread_rwlock_wrlock
libc.src.pthread.pthread_rwlock_trywrlock
libc.src.pthread.pthread_rwlock_timedwrlock
+ libc.src.pthread.pthread_rwlock_clockwrlock
libc.src.pthread.pthread_rwlock_unlock
libc.src.pthread.pthread_create
libc.src.pthread.pthread_join
diff --git a/libc/test/integration/src/pthread/pthread_rwlock_test.cpp b/libc/test/integration/src/pthread/pthread_rwlock_test.cpp
index 455003b6af811..8896f45d2c90a 100644
--- a/libc/test/integration/src/pthread/pthread_rwlock_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_rwlock_test.cpp
@@ -15,6 +15,8 @@
#include "src/__support/threads/sleep.h"
#include "src/pthread/pthread_create.h"
#include "src/pthread/pthread_join.h"
+#include "src/pthread/pthread_rwlock_clockrdlock.h"
+#include "src/pthread/pthread_rwlock_clockwrlock.h"
#include "src/pthread/pthread_rwlock_destroy.h"
#include "src/pthread/pthread_rwlock_init.h"
#include "src/pthread/pthread_rwlock_rdlock.h"
@@ -112,6 +114,12 @@ static void nullptr_test() {
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(nullptr), EINVAL);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(nullptr, &ts), EINVAL);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(nullptr, &ts), EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockrdlock(nullptr, CLOCK_MONOTONIC, &ts),
+ EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockwrlock(nullptr, CLOCK_MONOTONIC, &ts),
+ EINVAL);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(nullptr), EINVAL);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(nullptr), EINVAL);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(nullptr), EINVAL);
@@ -159,16 +167,40 @@ static void unusual_timespec_test() {
timespec ts = {0, -1};
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), EINVAL);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts), EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ EINVAL);
ts.tv_nsec = 1'000'000'000;
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ EINVAL);
ts.tv_nsec += 1;
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts), EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ EINVAL);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ EINVAL);
ts.tv_nsec = 0;
ts.tv_sec = -1;
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts),
ETIMEDOUT);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts),
ETIMEDOUT);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ ETIMEDOUT);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ ETIMEDOUT);
}
static void timedlock_with_deadlock_test() {
@@ -184,6 +216,12 @@ static void timedlock_with_deadlock_test() {
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts),
ETIMEDOUT);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), 0);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ ETIMEDOUT);
+ ASSERT_EQ(
+ LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts),
+ 0);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0);
ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0);
// notice that ts is already expired, but the following should still succeed.
@@ -270,9 +308,11 @@ enum class Operation : int {
WRITE = 1,
TIMED_READ = 2,
TIMED_WRITE = 3,
- TRY_READ = 4,
- TRY_WRITE = 5,
- COUNT = 6
+ CLOCK_READ = 4,
+ CLOCK_WRITE = 5,
+ TRY_READ = 6,
+ TRY_WRITE = 7,
+ COUNT = 8
};
LIBC_NAMESPACE::RawMutex *io_mutex;
@@ -358,6 +398,24 @@ static void randomized_thread_operation(SharedData *data, ThreadGuard &guard) {
}
break;
}
+ case Operation::CLOCK_READ: {
+ timespec ts = get_ts();
+ if (LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&data->lock, CLOCK_MONOTONIC,
+ &ts) == 0) {
+ read_ops();
+ LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock);
+ }
+ break;
+ }
+ case Operation::CLOCK_WRITE: {
+ timespec ts = get_ts();
+ if (LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&data->lock, CLOCK_MONOTONIC,
+ &ts) == 0) {
+ write_ops();
+ LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock);
+ }
+ break;
+ }
case Operation::TRY_READ: {
if (LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&data->lock) == 0) {
read_ops();
More information about the libc-commits
mailing list