141fecca9SSchrodinger ZHU Yifan //===-- Tests for pthread_rwlock ------------------------------------------===// 241fecca9SSchrodinger ZHU Yifan // 341fecca9SSchrodinger ZHU Yifan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 441fecca9SSchrodinger ZHU Yifan // See https://llvm.org/LICENSE.txt for license information. 541fecca9SSchrodinger ZHU Yifan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 641fecca9SSchrodinger ZHU Yifan // 741fecca9SSchrodinger ZHU Yifan //===----------------------------------------------------------------------===// 841fecca9SSchrodinger ZHU Yifan 9*03841e7aSSchrodinger ZHU Yifan #include "hdr/errno_macros.h" 10*03841e7aSSchrodinger ZHU Yifan #include "hdr/time_macros.h" 1141fecca9SSchrodinger ZHU Yifan #include "src/__support/CPP/atomic.h" 12c091dd48SSchrodinger ZHU Yifan #include "src/__support/CPP/new.h" 1341fecca9SSchrodinger ZHU Yifan #include "src/__support/OSUtil/syscall.h" 145ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1541fecca9SSchrodinger ZHU Yifan #include "src/__support/threads/linux/raw_mutex.h" 1641fecca9SSchrodinger ZHU Yifan #include "src/__support/threads/linux/rwlock.h" 1741fecca9SSchrodinger ZHU Yifan #include "src/__support/threads/sleep.h" 1841fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_create.h" 1941fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_join.h" 2044df89ccSEric977 #include "src/pthread/pthread_rwlock_clockrdlock.h" 2144df89ccSEric977 #include "src/pthread/pthread_rwlock_clockwrlock.h" 2241fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_destroy.h" 2341fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_init.h" 2441fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_rdlock.h" 2541fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_timedrdlock.h" 2641fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_timedwrlock.h" 2741fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_tryrdlock.h" 2841fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_trywrlock.h" 2941fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_unlock.h" 3041fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlock_wrlock.h" 3141fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlockattr_destroy.h" 3241fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlockattr_init.h" 3341fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlockattr_setkind_np.h" 3441fecca9SSchrodinger ZHU Yifan #include "src/pthread/pthread_rwlockattr_setpshared.h" 3541fecca9SSchrodinger ZHU Yifan #include "src/stdio/printf.h" 3641fecca9SSchrodinger ZHU Yifan #include "src/stdlib/exit.h" 3741fecca9SSchrodinger ZHU Yifan #include "src/stdlib/getenv.h" 3841fecca9SSchrodinger ZHU Yifan #include "src/sys/mman/mmap.h" 3941fecca9SSchrodinger ZHU Yifan #include "src/sys/mman/munmap.h" 4041fecca9SSchrodinger ZHU Yifan #include "src/sys/random/getrandom.h" 4141fecca9SSchrodinger ZHU Yifan #include "src/sys/wait/waitpid.h" 4241fecca9SSchrodinger ZHU Yifan #include "src/time/clock_gettime.h" 4341fecca9SSchrodinger ZHU Yifan #include "src/unistd/fork.h" 4441fecca9SSchrodinger ZHU Yifan #include "test/IntegrationTest/test.h" 4541fecca9SSchrodinger ZHU Yifan #include <pthread.h> 4641fecca9SSchrodinger ZHU Yifan 475ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 485ff3ff33SPetr Hosek namespace rwlock { 4941fecca9SSchrodinger ZHU Yifan class RwLockTester { 5041fecca9SSchrodinger ZHU Yifan public: 5141fecca9SSchrodinger ZHU Yifan static constexpr int full_reader_state() { 5241fecca9SSchrodinger ZHU Yifan return (~0) & (~RwState::PENDING_MASK) & (~RwState::ACTIVE_WRITER_BIT); 5341fecca9SSchrodinger ZHU Yifan } 5441fecca9SSchrodinger ZHU Yifan }; 555ff3ff33SPetr Hosek } // namespace rwlock 565ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 5741fecca9SSchrodinger ZHU Yifan 5841fecca9SSchrodinger ZHU Yifan static void smoke_test() { 5941fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 6041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, nullptr), 0); 6141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(&rwlock), 0); 6241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), 0); 6341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(&rwlock), EBUSY); 6441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 6541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 6641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), 0); 6741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(&rwlock), EDEADLK); 6841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), EDEADLK); 6941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), EBUSY); 7041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(&rwlock), EBUSY); 7141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 7241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 7341fecca9SSchrodinger ZHU Yifan } 7441fecca9SSchrodinger ZHU Yifan 7541fecca9SSchrodinger ZHU Yifan static void deadlock_detection_test() { 7641fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 7741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, nullptr), 0); 7841fecca9SSchrodinger ZHU Yifan // We only detect RAW, WAW deadlocks. 7941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), 0); 8041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), EDEADLK); 8141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 8241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 8341fecca9SSchrodinger ZHU Yifan } 8441fecca9SSchrodinger ZHU Yifan 8541fecca9SSchrodinger ZHU Yifan static void try_lock_test() { 8641fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 8741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, nullptr), 0); 8841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), 0); 8941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(&rwlock), EBUSY); 9041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), EBUSY); 9141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 9241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), 0); 9341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(&rwlock), 0); 9441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), 0); 9541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(&rwlock), EBUSY); 9641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 9741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 9841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 9941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 10041fecca9SSchrodinger ZHU Yifan } 10141fecca9SSchrodinger ZHU Yifan 10241fecca9SSchrodinger ZHU Yifan static void destroy_before_unlock_test() { 10341fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 10441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, nullptr), 0); 10541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), 0); 10641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), EBUSY); 10741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 10841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 10941fecca9SSchrodinger ZHU Yifan } 11041fecca9SSchrodinger ZHU Yifan 11141fecca9SSchrodinger ZHU Yifan static void nullptr_test() { 11241fecca9SSchrodinger ZHU Yifan timespec ts = {}; 11341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(nullptr), EINVAL); 11441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(nullptr), EINVAL); 11541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(nullptr, &ts), EINVAL); 11641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(nullptr, &ts), EINVAL); 11744df89ccSEric977 ASSERT_EQ( 11844df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockrdlock(nullptr, CLOCK_MONOTONIC, &ts), 11944df89ccSEric977 EINVAL); 12044df89ccSEric977 ASSERT_EQ( 12144df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockwrlock(nullptr, CLOCK_MONOTONIC, &ts), 12244df89ccSEric977 EINVAL); 12341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(nullptr), EINVAL); 12441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(nullptr), EINVAL); 12541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(nullptr), EINVAL); 12641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(nullptr), EINVAL); 12741fecca9SSchrodinger ZHU Yifan } 12841fecca9SSchrodinger ZHU Yifan 12941fecca9SSchrodinger ZHU Yifan // If you are a user reading this code, please do not do something like this. 13041fecca9SSchrodinger ZHU Yifan // We manually modify the internal state of the rwlock to test high reader 13141fecca9SSchrodinger ZHU Yifan // counts. 13241fecca9SSchrodinger ZHU Yifan static void high_reader_count_test() { 13341fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 13441fecca9SSchrodinger ZHU Yifan rwlock.__state = LIBC_NAMESPACE::rwlock::RwLockTester::full_reader_state(); 13541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(&rwlock), EAGAIN); 13641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), EAGAIN); 13741fecca9SSchrodinger ZHU Yifan // allocate 4 reader slots. 13841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 13941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 14041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 14141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 14241fecca9SSchrodinger ZHU Yifan 14341fecca9SSchrodinger ZHU Yifan pthread_t threads[20]; 14441fecca9SSchrodinger ZHU Yifan for (auto &i : threads) 14541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_create( 14641fecca9SSchrodinger ZHU Yifan &i, nullptr, 14741fecca9SSchrodinger ZHU Yifan [](void *arg) -> void * { 14841fecca9SSchrodinger ZHU Yifan pthread_rwlock_t *rwlock = 14941fecca9SSchrodinger ZHU Yifan reinterpret_cast<pthread_rwlock_t *>(arg); 15041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(rwlock), 15141fecca9SSchrodinger ZHU Yifan EBUSY); 15241fecca9SSchrodinger ZHU Yifan while (LIBC_NAMESPACE::pthread_rwlock_rdlock(rwlock) == 15341fecca9SSchrodinger ZHU Yifan EAGAIN) 15441fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::sleep_briefly(); 15541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(rwlock), 0); 15641fecca9SSchrodinger ZHU Yifan return nullptr; 15741fecca9SSchrodinger ZHU Yifan }, 15841fecca9SSchrodinger ZHU Yifan &rwlock), 15941fecca9SSchrodinger ZHU Yifan 0); 16041fecca9SSchrodinger ZHU Yifan 16141fecca9SSchrodinger ZHU Yifan for (auto &i : threads) 16241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_join(i, nullptr), 0); 16341fecca9SSchrodinger ZHU Yifan } 16441fecca9SSchrodinger ZHU Yifan 16541fecca9SSchrodinger ZHU Yifan static void unusual_timespec_test() { 16641fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 16741fecca9SSchrodinger ZHU Yifan timespec ts = {0, -1}; 16841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), EINVAL); 16941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts), EINVAL); 17044df89ccSEric977 ASSERT_EQ( 17144df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts), 17244df89ccSEric977 EINVAL); 17344df89ccSEric977 ASSERT_EQ( 17444df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts), 17544df89ccSEric977 EINVAL); 17641fecca9SSchrodinger ZHU Yifan ts.tv_nsec = 1'000'000'000; 17741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), EINVAL); 17844df89ccSEric977 ASSERT_EQ( 17944df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts), 18044df89ccSEric977 EINVAL); 18144df89ccSEric977 ASSERT_EQ( 18244df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts), 18344df89ccSEric977 EINVAL); 18441fecca9SSchrodinger ZHU Yifan ts.tv_nsec += 1; 18541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts), EINVAL); 18644df89ccSEric977 ASSERT_EQ( 18744df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts), 18844df89ccSEric977 EINVAL); 18944df89ccSEric977 ASSERT_EQ( 19044df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts), 19144df89ccSEric977 EINVAL); 19241fecca9SSchrodinger ZHU Yifan ts.tv_nsec = 0; 19341fecca9SSchrodinger ZHU Yifan ts.tv_sec = -1; 19441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), 19541fecca9SSchrodinger ZHU Yifan ETIMEDOUT); 19641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts), 19741fecca9SSchrodinger ZHU Yifan ETIMEDOUT); 19844df89ccSEric977 ASSERT_EQ( 19944df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_MONOTONIC, &ts), 20044df89ccSEric977 ETIMEDOUT); 20144df89ccSEric977 ASSERT_EQ( 20244df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_MONOTONIC, &ts), 20344df89ccSEric977 ETIMEDOUT); 20441fecca9SSchrodinger ZHU Yifan } 20541fecca9SSchrodinger ZHU Yifan 20641fecca9SSchrodinger ZHU Yifan static void timedlock_with_deadlock_test() { 20741fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 20841fecca9SSchrodinger ZHU Yifan timespec ts{}; 20941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(&rwlock), 0); 21041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::clock_gettime(CLOCK_REALTIME, &ts); 21141fecca9SSchrodinger ZHU Yifan ts.tv_nsec += 50'000; 21241fecca9SSchrodinger ZHU Yifan if (ts.tv_nsec >= 1'000'000'000) { 21341fecca9SSchrodinger ZHU Yifan ts.tv_nsec -= 1'000'000'000; 21441fecca9SSchrodinger ZHU Yifan ts.tv_sec += 1; 21541fecca9SSchrodinger ZHU Yifan } 21641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&rwlock, &ts), 21741fecca9SSchrodinger ZHU Yifan ETIMEDOUT); 21841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&rwlock, &ts), 0); 21944df89ccSEric977 ASSERT_EQ( 2205cddc314SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&rwlock, CLOCK_REALTIME, &ts), 22144df89ccSEric977 ETIMEDOUT); 22244df89ccSEric977 ASSERT_EQ( 2235cddc314SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&rwlock, CLOCK_REALTIME, &ts), 22444df89ccSEric977 0); 22541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 22641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 2275cddc314SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 22841fecca9SSchrodinger ZHU Yifan // notice that ts is already expired, but the following should still succeed. 22941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&rwlock), 0); 23041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 23141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_trywrlock(&rwlock), 0); 23241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 23341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_rdlock(&rwlock), 0); 23441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 23541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_wrlock(&rwlock), 0); 23641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_unlock(&rwlock), 0); 23741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 23841fecca9SSchrodinger ZHU Yifan } 23941fecca9SSchrodinger ZHU Yifan 24041fecca9SSchrodinger ZHU Yifan static void attributed_initialization_test() { 24141fecca9SSchrodinger ZHU Yifan pthread_rwlockattr_t attr{}; 24241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); 24341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np( 24441fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_RWLOCK_PREFER_READER_NP), 24541fecca9SSchrodinger ZHU Yifan 0); 24641fecca9SSchrodinger ZHU Yifan { 24741fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 24841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), 0); 24941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 25041fecca9SSchrodinger ZHU Yifan } 25141fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np( 25241fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP), 25341fecca9SSchrodinger ZHU Yifan 0); 25441fecca9SSchrodinger ZHU Yifan { 25541fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 25641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), 0); 25741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 25841fecca9SSchrodinger ZHU Yifan } 25941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np( 26041fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_RWLOCK_PREFER_WRITER_NP), 26141fecca9SSchrodinger ZHU Yifan 0); 26241fecca9SSchrodinger ZHU Yifan { 26341fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 26441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), EINVAL); 26541fecca9SSchrodinger ZHU Yifan } 26641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np( 26741fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_RWLOCK_PREFER_READER_NP), 26841fecca9SSchrodinger ZHU Yifan 0); 26941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( 27041fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_PROCESS_PRIVATE), 27141fecca9SSchrodinger ZHU Yifan 0); 27241fecca9SSchrodinger ZHU Yifan { 27341fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 27441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), 0); 27541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 27641fecca9SSchrodinger ZHU Yifan } 27741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( 27841fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_PROCESS_SHARED), 27941fecca9SSchrodinger ZHU Yifan 0); 28041fecca9SSchrodinger ZHU Yifan { 28141fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 28241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), 0); 28341fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&rwlock), 0); 28441fecca9SSchrodinger ZHU Yifan } 28541fecca9SSchrodinger ZHU Yifan attr.pref = -1; 28641fecca9SSchrodinger ZHU Yifan { 28741fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 28841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), EINVAL); 28941fecca9SSchrodinger ZHU Yifan } 29041fecca9SSchrodinger ZHU Yifan attr.pref = PTHREAD_RWLOCK_PREFER_READER_NP; 29141fecca9SSchrodinger ZHU Yifan attr.pshared = -1; 29241fecca9SSchrodinger ZHU Yifan { 29341fecca9SSchrodinger ZHU Yifan pthread_rwlock_t rwlock{}; 29441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&rwlock, &attr), EINVAL); 29541fecca9SSchrodinger ZHU Yifan } 29641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); 29741fecca9SSchrodinger ZHU Yifan } 29841fecca9SSchrodinger ZHU Yifan 29941fecca9SSchrodinger ZHU Yifan struct SharedData { 30041fecca9SSchrodinger ZHU Yifan pthread_rwlock_t lock; 30141fecca9SSchrodinger ZHU Yifan int data; 30241fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::cpp::Atomic<int> reader_count; 30341fecca9SSchrodinger ZHU Yifan bool writer_flag; 30441fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::cpp::Atomic<int> total_writer_count; 30541fecca9SSchrodinger ZHU Yifan }; 30641fecca9SSchrodinger ZHU Yifan 30741fecca9SSchrodinger ZHU Yifan enum class Operation : int { 30841fecca9SSchrodinger ZHU Yifan READ = 0, 30941fecca9SSchrodinger ZHU Yifan WRITE = 1, 31041fecca9SSchrodinger ZHU Yifan TIMED_READ = 2, 31141fecca9SSchrodinger ZHU Yifan TIMED_WRITE = 3, 31244df89ccSEric977 CLOCK_READ = 4, 31344df89ccSEric977 CLOCK_WRITE = 5, 31444df89ccSEric977 TRY_READ = 6, 31544df89ccSEric977 TRY_WRITE = 7, 31644df89ccSEric977 COUNT = 8 31741fecca9SSchrodinger ZHU Yifan }; 31841fecca9SSchrodinger ZHU Yifan 31941fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::RawMutex *io_mutex; 32041fecca9SSchrodinger ZHU Yifan struct ThreadGuard { 32141fecca9SSchrodinger ZHU Yifan Operation record[64]{}; 32241fecca9SSchrodinger ZHU Yifan size_t cursor = 0; 32341fecca9SSchrodinger ZHU Yifan void push(Operation op) { record[cursor++] = op; } 32441fecca9SSchrodinger ZHU Yifan ~ThreadGuard() { 32541fecca9SSchrodinger ZHU Yifan if (!LIBC_NAMESPACE::getenv("LIBC_PTHREAD_RWLOCK_TEST_VERBOSE")) 32641fecca9SSchrodinger ZHU Yifan return; 32741fecca9SSchrodinger ZHU Yifan pid_t pid = LIBC_NAMESPACE::syscall_impl(SYS_getpid); 32841fecca9SSchrodinger ZHU Yifan pid_t tid = LIBC_NAMESPACE::syscall_impl(SYS_gettid); 32941fecca9SSchrodinger ZHU Yifan io_mutex->lock(LIBC_NAMESPACE::cpp::nullopt, true); 33041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::printf("process %d thread %d: ", pid, tid); 33141fecca9SSchrodinger ZHU Yifan for (size_t i = 0; i < cursor; ++i) 33241fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::printf("%d ", static_cast<int>(record[i])); 33341fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::printf("\n"); 33441fecca9SSchrodinger ZHU Yifan io_mutex->unlock(true); 33541fecca9SSchrodinger ZHU Yifan } 33641fecca9SSchrodinger ZHU Yifan }; 33741fecca9SSchrodinger ZHU Yifan 33841fecca9SSchrodinger ZHU Yifan static void randomized_thread_operation(SharedData *data, ThreadGuard &guard) { 33941fecca9SSchrodinger ZHU Yifan int buffer; 34041fecca9SSchrodinger ZHU Yifan // We cannot reason about thread order anyway, let's go wild and randomize it 34141fecca9SSchrodinger ZHU Yifan // directly using getrandom. 34241fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::getrandom(&buffer, sizeof(buffer), 0); 34341fecca9SSchrodinger ZHU Yifan constexpr int TOTAL = static_cast<int>(Operation::COUNT); 34441fecca9SSchrodinger ZHU Yifan Operation op = static_cast<Operation>(((buffer % TOTAL) + TOTAL) % TOTAL); 34541fecca9SSchrodinger ZHU Yifan guard.push(op); 34641fecca9SSchrodinger ZHU Yifan auto read_ops = [data]() { 34741fecca9SSchrodinger ZHU Yifan ASSERT_FALSE(data->writer_flag); 34841fecca9SSchrodinger ZHU Yifan data->reader_count.fetch_add(1, LIBC_NAMESPACE::cpp::MemoryOrder::RELAXED); 34941fecca9SSchrodinger ZHU Yifan for (int i = 0; i < 10; ++i) 35041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::sleep_briefly(); 35141fecca9SSchrodinger ZHU Yifan data->reader_count.fetch_sub(1, LIBC_NAMESPACE::cpp::MemoryOrder::RELAXED); 35241fecca9SSchrodinger ZHU Yifan }; 35341fecca9SSchrodinger ZHU Yifan auto write_ops = [data]() { 35441fecca9SSchrodinger ZHU Yifan ASSERT_FALSE(data->writer_flag); 35541fecca9SSchrodinger ZHU Yifan data->data += 1; 35641fecca9SSchrodinger ZHU Yifan data->writer_flag = true; 35741fecca9SSchrodinger ZHU Yifan for (int i = 0; i < 10; ++i) 35841fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::sleep_briefly(); 35941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(data->reader_count, 0); 36041fecca9SSchrodinger ZHU Yifan data->writer_flag = false; 36141fecca9SSchrodinger ZHU Yifan data->total_writer_count.fetch_add(1); 36241fecca9SSchrodinger ZHU Yifan }; 36341fecca9SSchrodinger ZHU Yifan auto get_ts = []() { 36441fecca9SSchrodinger ZHU Yifan timespec ts{}; 36541fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::clock_gettime(CLOCK_REALTIME, &ts); 36641fecca9SSchrodinger ZHU Yifan ts.tv_nsec += 5'000; 36741fecca9SSchrodinger ZHU Yifan if (ts.tv_nsec >= 1'000'000'000) { 36841fecca9SSchrodinger ZHU Yifan ts.tv_nsec -= 1'000'000'000; 36941fecca9SSchrodinger ZHU Yifan ts.tv_sec += 1; 37041fecca9SSchrodinger ZHU Yifan } 37141fecca9SSchrodinger ZHU Yifan return ts; 37241fecca9SSchrodinger ZHU Yifan }; 37341fecca9SSchrodinger ZHU Yifan switch (op) { 37441fecca9SSchrodinger ZHU Yifan case Operation::READ: { 37541fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_rdlock(&data->lock); 37641fecca9SSchrodinger ZHU Yifan read_ops(); 37741fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 37841fecca9SSchrodinger ZHU Yifan break; 37941fecca9SSchrodinger ZHU Yifan } 38041fecca9SSchrodinger ZHU Yifan case Operation::WRITE: { 38141fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_wrlock(&data->lock); 38241fecca9SSchrodinger ZHU Yifan write_ops(); 38341fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 38441fecca9SSchrodinger ZHU Yifan break; 38541fecca9SSchrodinger ZHU Yifan } 38641fecca9SSchrodinger ZHU Yifan case Operation::TIMED_READ: { 38741fecca9SSchrodinger ZHU Yifan timespec ts = get_ts(); 38841fecca9SSchrodinger ZHU Yifan if (LIBC_NAMESPACE::pthread_rwlock_timedrdlock(&data->lock, &ts) == 0) { 38941fecca9SSchrodinger ZHU Yifan read_ops(); 39041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 39141fecca9SSchrodinger ZHU Yifan } 39241fecca9SSchrodinger ZHU Yifan break; 39341fecca9SSchrodinger ZHU Yifan } 39441fecca9SSchrodinger ZHU Yifan case Operation::TIMED_WRITE: { 39541fecca9SSchrodinger ZHU Yifan timespec ts = get_ts(); 39641fecca9SSchrodinger ZHU Yifan if (LIBC_NAMESPACE::pthread_rwlock_timedwrlock(&data->lock, &ts) == 0) { 39741fecca9SSchrodinger ZHU Yifan write_ops(); 39841fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 39941fecca9SSchrodinger ZHU Yifan } 40041fecca9SSchrodinger ZHU Yifan break; 40141fecca9SSchrodinger ZHU Yifan } 40244df89ccSEric977 case Operation::CLOCK_READ: { 40344df89ccSEric977 timespec ts = get_ts(); 40444df89ccSEric977 if (LIBC_NAMESPACE::pthread_rwlock_clockrdlock(&data->lock, CLOCK_MONOTONIC, 40544df89ccSEric977 &ts) == 0) { 40644df89ccSEric977 read_ops(); 40744df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 40844df89ccSEric977 } 40944df89ccSEric977 break; 41044df89ccSEric977 } 41144df89ccSEric977 case Operation::CLOCK_WRITE: { 41244df89ccSEric977 timespec ts = get_ts(); 41344df89ccSEric977 if (LIBC_NAMESPACE::pthread_rwlock_clockwrlock(&data->lock, CLOCK_MONOTONIC, 41444df89ccSEric977 &ts) == 0) { 41544df89ccSEric977 write_ops(); 41644df89ccSEric977 LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 41744df89ccSEric977 } 41844df89ccSEric977 break; 41944df89ccSEric977 } 42041fecca9SSchrodinger ZHU Yifan case Operation::TRY_READ: { 42141fecca9SSchrodinger ZHU Yifan if (LIBC_NAMESPACE::pthread_rwlock_tryrdlock(&data->lock) == 0) { 42241fecca9SSchrodinger ZHU Yifan read_ops(); 42341fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 42441fecca9SSchrodinger ZHU Yifan } 42541fecca9SSchrodinger ZHU Yifan break; 42641fecca9SSchrodinger ZHU Yifan } 42741fecca9SSchrodinger ZHU Yifan case Operation::TRY_WRITE: { 42841fecca9SSchrodinger ZHU Yifan if (LIBC_NAMESPACE::pthread_rwlock_trywrlock(&data->lock) == 0) { 42941fecca9SSchrodinger ZHU Yifan write_ops(); 43041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_rwlock_unlock(&data->lock); 43141fecca9SSchrodinger ZHU Yifan } 43241fecca9SSchrodinger ZHU Yifan break; 43341fecca9SSchrodinger ZHU Yifan } 43441fecca9SSchrodinger ZHU Yifan case Operation::COUNT: 43541fecca9SSchrodinger ZHU Yifan __builtin_trap(); 43641fecca9SSchrodinger ZHU Yifan } 43741fecca9SSchrodinger ZHU Yifan } 43841fecca9SSchrodinger ZHU Yifan 43941fecca9SSchrodinger ZHU Yifan static void 44041fecca9SSchrodinger ZHU Yifan randomized_process_operation(SharedData &data, 44141fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::cpp::Atomic<int> &finish_count, 44241fecca9SSchrodinger ZHU Yifan int expected_count) { 44341fecca9SSchrodinger ZHU Yifan pthread_t threads[32]; 44441fecca9SSchrodinger ZHU Yifan for (auto &i : threads) 44541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_create( 44641fecca9SSchrodinger ZHU Yifan &i, nullptr, 44741fecca9SSchrodinger ZHU Yifan [](void *arg) -> void * { 44841fecca9SSchrodinger ZHU Yifan ThreadGuard guard{}; 44941fecca9SSchrodinger ZHU Yifan for (int i = 0; i < 64; ++i) 45041fecca9SSchrodinger ZHU Yifan randomized_thread_operation( 45141fecca9SSchrodinger ZHU Yifan reinterpret_cast<SharedData *>(arg), guard); 45241fecca9SSchrodinger ZHU Yifan return nullptr; 45341fecca9SSchrodinger ZHU Yifan }, 45441fecca9SSchrodinger ZHU Yifan &data), 45541fecca9SSchrodinger ZHU Yifan 0); 45641fecca9SSchrodinger ZHU Yifan 45741fecca9SSchrodinger ZHU Yifan for (auto &i : threads) 45841fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_join(i, nullptr), 0); 45941fecca9SSchrodinger ZHU Yifan 46041fecca9SSchrodinger ZHU Yifan finish_count.fetch_add(1); 46141fecca9SSchrodinger ZHU Yifan while (finish_count.load() != expected_count) 46241fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::sleep_briefly(); 46341fecca9SSchrodinger ZHU Yifan 46441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(data.total_writer_count.load(), data.data); 46541fecca9SSchrodinger ZHU Yifan ASSERT_FALSE(data.writer_flag); 46641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(data.reader_count, 0); 46741fecca9SSchrodinger ZHU Yifan } 46841fecca9SSchrodinger ZHU Yifan 46941fecca9SSchrodinger ZHU Yifan static void single_process_test(int preference) { 47041fecca9SSchrodinger ZHU Yifan SharedData data{}; 47141fecca9SSchrodinger ZHU Yifan data.data = 0; 47241fecca9SSchrodinger ZHU Yifan data.reader_count = 0; 47341fecca9SSchrodinger ZHU Yifan data.writer_flag = false; 47441fecca9SSchrodinger ZHU Yifan data.total_writer_count.store(0); 47541fecca9SSchrodinger ZHU Yifan pthread_rwlockattr_t attr{}; 47641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); 47741fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np(&attr, preference), 47841fecca9SSchrodinger ZHU Yifan 0); 47941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&data.lock, nullptr), 0); 48041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::cpp::Atomic<int> finish_count{0}; 48141fecca9SSchrodinger ZHU Yifan randomized_process_operation(data, finish_count, 1); 48241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&data.lock), 0); 48341fecca9SSchrodinger ZHU Yifan } 48441fecca9SSchrodinger ZHU Yifan 48541fecca9SSchrodinger ZHU Yifan static void multiple_process_test(int preference) { 48641fecca9SSchrodinger ZHU Yifan struct PShared { 48741fecca9SSchrodinger ZHU Yifan SharedData data; 48841fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::cpp::Atomic<int> finish_count; 48941fecca9SSchrodinger ZHU Yifan }; 49041fecca9SSchrodinger ZHU Yifan PShared *shared_data = reinterpret_cast<PShared *>( 49141fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::mmap(nullptr, sizeof(PShared), PROT_READ | PROT_WRITE, 49241fecca9SSchrodinger ZHU Yifan MAP_SHARED | MAP_ANONYMOUS, -1, 0)); 49341fecca9SSchrodinger ZHU Yifan shared_data->data.data = 0; 49441fecca9SSchrodinger ZHU Yifan shared_data->data.reader_count = 0; 49541fecca9SSchrodinger ZHU Yifan shared_data->data.writer_flag = false; 49641fecca9SSchrodinger ZHU Yifan shared_data->data.total_writer_count.store(0); 49741fecca9SSchrodinger ZHU Yifan shared_data->finish_count.store(0); 49841fecca9SSchrodinger ZHU Yifan pthread_rwlockattr_t attr{}; 49941fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); 50041fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np(&attr, preference), 50141fecca9SSchrodinger ZHU Yifan 0); 50241fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( 50341fecca9SSchrodinger ZHU Yifan &attr, PTHREAD_PROCESS_SHARED), 50441fecca9SSchrodinger ZHU Yifan 0); 50541fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_init(&shared_data->data.lock, &attr), 50641fecca9SSchrodinger ZHU Yifan 0); 50741fecca9SSchrodinger ZHU Yifan int pid = LIBC_NAMESPACE::fork(); 50841fecca9SSchrodinger ZHU Yifan randomized_process_operation(shared_data->data, shared_data->finish_count, 2); 50941fecca9SSchrodinger ZHU Yifan if (pid == 0) 51041fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::exit(0); 51141fecca9SSchrodinger ZHU Yifan else { 51241fecca9SSchrodinger ZHU Yifan int status; 51341fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::waitpid(pid, &status, 0); 51441fecca9SSchrodinger ZHU Yifan ASSERT_EQ(status, 0); 51541fecca9SSchrodinger ZHU Yifan } 51641fecca9SSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlock_destroy(&shared_data->data.lock), 0); 51741fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::munmap(shared_data, sizeof(PShared)); 51841fecca9SSchrodinger ZHU Yifan } 51941fecca9SSchrodinger ZHU Yifan 52041fecca9SSchrodinger ZHU Yifan TEST_MAIN() { 52141fecca9SSchrodinger ZHU Yifan io_mutex = new (LIBC_NAMESPACE::mmap( 52241fecca9SSchrodinger ZHU Yifan nullptr, sizeof(LIBC_NAMESPACE::RawMutex), PROT_READ | PROT_WRITE, 52341fecca9SSchrodinger ZHU Yifan MAP_ANONYMOUS | MAP_SHARED, -1, 0)) LIBC_NAMESPACE::RawMutex(); 52441fecca9SSchrodinger ZHU Yifan smoke_test(); 52541fecca9SSchrodinger ZHU Yifan deadlock_detection_test(); 52641fecca9SSchrodinger ZHU Yifan try_lock_test(); 52741fecca9SSchrodinger ZHU Yifan destroy_before_unlock_test(); 52841fecca9SSchrodinger ZHU Yifan nullptr_test(); 52941fecca9SSchrodinger ZHU Yifan high_reader_count_test(); 53041fecca9SSchrodinger ZHU Yifan unusual_timespec_test(); 53141fecca9SSchrodinger ZHU Yifan timedlock_with_deadlock_test(); 53241fecca9SSchrodinger ZHU Yifan attributed_initialization_test(); 53341fecca9SSchrodinger ZHU Yifan single_process_test(PTHREAD_RWLOCK_PREFER_READER_NP); 53441fecca9SSchrodinger ZHU Yifan single_process_test(PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 53541fecca9SSchrodinger ZHU Yifan multiple_process_test(PTHREAD_RWLOCK_PREFER_READER_NP); 53641fecca9SSchrodinger ZHU Yifan multiple_process_test(PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 53741fecca9SSchrodinger ZHU Yifan io_mutex->~RawMutex(); 53841fecca9SSchrodinger ZHU Yifan LIBC_NAMESPACE::munmap(io_mutex, sizeof(LIBC_NAMESPACE::RawMutex)); 53941fecca9SSchrodinger ZHU Yifan return 0; 54041fecca9SSchrodinger ZHU Yifan } 541