556 changes: 556 additions & 0 deletions libc/src/__support/threads/linux/rwlock.h

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions libc/src/pthread/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,106 @@ add_entrypoint_object(
libc.include.errno
)

add_entrypoint_object(
pthread_rwlock_init
SRCS
pthread_rwlock_init.cpp
HDRS
pthread_rwlock_init.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
libc.src.__support.CPP.new
)

add_entrypoint_object(
pthread_rwlock_tryrdlock
SRCS
pthread_rwlock_tryrdlock.cpp
HDRS
pthread_rwlock_tryrdlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_trywrlock
SRCS
pthread_rwlock_trywrlock.cpp
HDRS
pthread_rwlock_trywrlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_timedrdlock
SRCS
pthread_rwlock_timedrdlock.cpp
HDRS
pthread_rwlock_timedrdlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_timedwrlock
SRCS
pthread_rwlock_timedwrlock.cpp
HDRS
pthread_rwlock_timedwrlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_rdlock
SRCS
pthread_rwlock_rdlock.cpp
HDRS
pthread_rwlock_rdlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_wrlock
SRCS
pthread_rwlock_wrlock.cpp
HDRS
pthread_rwlock_wrlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_unlock
SRCS
pthread_rwlock_unlock.cpp
HDRS
pthread_rwlock_unlock.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_rwlock_destroy
SRCS
pthread_rwlock_destroy.cpp
HDRS
pthread_rwlock_destroy.h
DEPENDS
libc.include.pthread
libc.src.__support.threads.linux.rwlock
)

add_entrypoint_object(
pthread_once
SRCS
Expand Down
33 changes: 33 additions & 0 deletions libc/src/pthread/pthread_rwlock_destroy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Implementation for Rwlock's destroy 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_destroy.h"

#include "src/__support/common.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, pthread_rwlock_destroy, (pthread_rwlock_t * rwlock)) {
if (!rwlock)
return EINVAL;
auto *rw = reinterpret_cast<RwLock *>(rwlock);
RwLock::LockResult res = rw->check_for_destroy();

// this is currently no-op, but we still call the destructor as a symmetry
// to its constructor call;
if (res == RwLock::LockResult::Success)
rw->~RwLock();

return static_cast<int>(res);
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_rwlock_destroy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for Rwlock's 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_RWLOCK_DESTROY_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_DESTROY_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_DESTROY_H
67 changes: 67 additions & 0 deletions libc/src/pthread/pthread_rwlock_init.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===-- Linux implementation of the pthread_rwlock_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 "src/pthread/pthread_rwlock_init.h"

#include "src/__support/CPP/new.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

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_init,
(pthread_rwlock_t * rwlock,
const pthread_rwlockattr_t *__restrict attr)) {
pthread_rwlockattr_t rwlockattr{
/*pshared=*/PTHREAD_PROCESS_PRIVATE,
/*pref*/ PTHREAD_RWLOCK_PREFER_READER_NP,
};
// POSIX does not specify this check, so we add an assertion to catch it.
LIBC_ASSERT(rwlock && "rwlock is null");
if (attr)
rwlockattr = *attr;

// PTHREAD_RWLOCK_PREFER_WRITER_NP is not supported.
rwlock::Role preference;
switch (rwlockattr.pref) {
case PTHREAD_RWLOCK_PREFER_READER_NP:
preference = rwlock::Role::Reader;
break;
case PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP:
preference = rwlock::Role::Writer;
break;
default:
return EINVAL;
}
bool is_pshared;
switch (rwlockattr.pshared) {
case PTHREAD_PROCESS_PRIVATE:
is_pshared = false;
break;
case PTHREAD_PROCESS_SHARED:
is_pshared = true;
break;
default:
return EINVAL;
}

new (rwlock) RwLock(preference, is_pshared);
return 0;
}

} // namespace LIBC_NAMESPACE
21 changes: 21 additions & 0 deletions libc/src/pthread/pthread_rwlock_init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for pthread_rwlock_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_RWLOCK_INIT_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_INIT_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_init(pthread_rwlock_t *rwlock,
const pthread_rwlockattr_t *__restrict attr);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_INIT_H
32 changes: 32 additions & 0 deletions libc/src/pthread/pthread_rwlock_rdlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- Implementation of the Rwlock's rdlock 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_rdlock.h"

#include "src/__support/common.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

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_rdlock, (pthread_rwlock_t * rwlock)) {
if (!rwlock)
return EINVAL;
RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
return static_cast<int>(rw->read_lock());
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_rwlock_rdlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for Rwlock's rdlock 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_RDLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_RDLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_RDLOCK_H
49 changes: 49 additions & 0 deletions libc/src/pthread/pthread_rwlock_timedrdlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===-- Implementation of the Rwlock's timedrdlock 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_timedrdlock.h"

#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/threads/linux/rwlock.h"
#include "src/__support/time/linux/abs_timeout.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

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_timedrdlock,
(pthread_rwlock_t * rwlock,
const struct timespec *abstime)) {
if (!rwlock)
return EINVAL;
RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
LIBC_ASSERT(abstime && "timedrdlock called with a null timeout");
auto timeout =
internal::AbsTimeout::from_timespec(*abstime, /*is_realtime=*/true);
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;
// default: unreachable, all two cases are covered.
}
}

} // namespace LIBC_NAMESPACE
21 changes: 21 additions & 0 deletions libc/src/pthread/pthread_rwlock_timedrdlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for Rwlock's timedrdlock 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_TIMEDRDLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TIMEDRDLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict rwlock,
const struct timespec *__restrict abs_timeout);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TIMEDRDLOCK_H
43 changes: 43 additions & 0 deletions libc/src/pthread/pthread_rwlock_timedwrlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- Implementation for Rwlock's timedwrlock 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_timedwrlock.h"

#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/threads/linux/rwlock.h"
#include "src/__support/time/linux/abs_timeout.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, pthread_rwlock_timedwrlock,
(pthread_rwlock_t *__restrict rwlock,
const struct timespec *__restrict abstime)) {
if (!rwlock)
return EINVAL;
RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
LIBC_ASSERT(abstime && "timedwrlock called with a null timeout");
auto timeout =
internal::AbsTimeout::from_timespec(*abstime, /*is_realtime=*/true);
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;
// default: unreachable, all two cases are covered.
}
}

} // namespace LIBC_NAMESPACE
21 changes: 21 additions & 0 deletions libc/src/pthread/pthread_rwlock_timedwrlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for Rwlock's timedwrlock 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_TIMEDWRLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TIMEDWRLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict rwlock,
const struct timespec *__restrict abs_timeout);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TIMEDWRLOCK_H
32 changes: 32 additions & 0 deletions libc/src/pthread/pthread_rwlock_tryrdlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- Implementation of the Rwlock's tryrdlock 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_tryrdlock.h"

#include "src/__support/common.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

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_tryrdlock, (pthread_rwlock_t * rwlock)) {
if (!rwlock)
return EINVAL;
RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
return static_cast<int>(rw->try_read_lock());
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_rwlock_tryrdlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for Rwlock's tryrdlock 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_TRYRDLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TRYRDLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TRYRDLOCK_H
32 changes: 32 additions & 0 deletions libc/src/pthread/pthread_rwlock_trywrlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- Implementation for Rwlock's trywrlock 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_trywrlock.h"

#include "src/__support/common.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

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_trywrlock, (pthread_rwlock_t * rwlock)) {
if (!rwlock)
return EINVAL;
RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
return static_cast<int>(rw->try_write_lock());
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_rwlock_trywrlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for Rwlock's trywrlock 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_TRYWRLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TRYWRLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_TRYWRLOCK_H
26 changes: 26 additions & 0 deletions libc/src/pthread/pthread_rwlock_unlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Implementation for Rwlock's unlock 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_unlock.h"

#include "src/__support/common.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, pthread_rwlock_unlock, (pthread_rwlock_t * rwlock)) {
if (!rwlock)
return EINVAL;
auto *rw = reinterpret_cast<RwLock *>(rwlock);
return static_cast<int>(rw->unlock());
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_rwlock_unlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for Rwlock's unlock 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_UNLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_UNLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_UNLOCK_H
32 changes: 32 additions & 0 deletions libc/src/pthread/pthread_rwlock_wrlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- Implementation for Rwlock's wrlock 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_wrlock.h"

#include "src/__support/common.h"
#include "src/__support/threads/linux/rwlock.h"

#include <errno.h>
#include <pthread.h>

namespace LIBC_NAMESPACE {

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_wrlock, (pthread_rwlock_t * rwlock)) {
if (!rwlock)
return EINVAL;
RwLock *rw = reinterpret_cast<RwLock *>(rwlock);
return static_cast<int>(rw->write_lock());
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_rwlock_wrlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for Rwlock's wrlock 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_WRLOCK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_WRLOCK_H

#include <pthread.h>

namespace LIBC_NAMESPACE {

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCK_WRLOCK_H
39 changes: 39 additions & 0 deletions libc/test/integration/src/pthread/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,45 @@ add_integration_test(
libc.src.pthread.pthread_join
)

add_integration_test(
pthread_rwlock_test
SUITE
libc-pthread-integration-tests
SRCS
pthread_rwlock_test.cpp
DEPENDS
libc.include.pthread
libc.include.time
libc.include.errno
libc.src.pthread.pthread_rwlock_destroy
libc.src.pthread.pthread_rwlock_init
libc.src.pthread.pthread_rwlock_rdlock
libc.src.pthread.pthread_rwlock_tryrdlock
libc.src.pthread.pthread_rwlock_timedrdlock
libc.src.pthread.pthread_rwlock_wrlock
libc.src.pthread.pthread_rwlock_trywrlock
libc.src.pthread.pthread_rwlock_timedwrlock
libc.src.pthread.pthread_rwlock_unlock
libc.src.pthread.pthread_create
libc.src.pthread.pthread_join
libc.src.pthread.pthread_rwlockattr_init
libc.src.pthread.pthread_rwlockattr_destroy
libc.src.pthread.pthread_rwlockattr_setpshared
libc.src.pthread.pthread_rwlockattr_setkind_np
libc.src.__support.threads.linux.raw_mutex
libc.src.stdio.printf
libc.src.stdlib.getenv
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
libc.src.time.clock_gettime
libc.src.sys.random.getrandom
libc.src.unistd.fork
libc.src.sys.wait.waitpid
libc.src.stdlib.exit
libc.src.__support.CPP.atomic
libc.src.__support.threads.sleep
)

add_integration_test(
pthread_test
SUITE
Expand Down
478 changes: 478 additions & 0 deletions libc/test/integration/src/pthread/pthread_rwlock_test.cpp

Large diffs are not rendered by default.