diff options
Diffstat (limited to 'libc/test/integration')
-rw-r--r-- | libc/test/integration/src/pthread/CMakeLists.txt | 17 | ||||
-rw-r--r-- | libc/test/integration/src/pthread/pthread_barrier_test.cpp | 117 | ||||
-rw-r--r-- | libc/test/integration/src/stdlib/gpu/malloc_stress.cpp | 28 |
3 files changed, 162 insertions, 0 deletions
diff --git a/libc/test/integration/src/pthread/CMakeLists.txt b/libc/test/integration/src/pthread/CMakeLists.txt index 0bdd99c..251b009 100644 --- a/libc/test/integration/src/pthread/CMakeLists.txt +++ b/libc/test/integration/src/pthread/CMakeLists.txt @@ -19,6 +19,23 @@ add_integration_test( ) add_integration_test( + pthread_barrier_test + SUITE + libc-pthread-integration-tests + SRCS + pthread_barrier_test.cpp + DEPENDS + libc.include.pthread + libc.src.errno.errno + libc.src.pthread.pthread_barrier_destroy + libc.src.pthread.pthread_barrier_wait + libc.src.pthread.pthread_barrier_init + libc.src.pthread.pthread_create + libc.src.pthread.pthread_join + libc.src.stdio.printf +) + +add_integration_test( pthread_rwlock_test SUITE libc-pthread-integration-tests diff --git a/libc/test/integration/src/pthread/pthread_barrier_test.cpp b/libc/test/integration/src/pthread/pthread_barrier_test.cpp new file mode 100644 index 0000000..c8e1104 --- /dev/null +++ b/libc/test/integration/src/pthread/pthread_barrier_test.cpp @@ -0,0 +1,117 @@ +//===-- Tests for pthread_barrier_t ---------------------------------------===// +// +// 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_barrier_destroy.h" +#include "src/pthread/pthread_barrier_init.h" +#include "src/pthread/pthread_barrier_wait.h" + +#include "src/__support/CPP/atomic.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 "src/string/memset.h" + +#include "test/IntegrationTest/test.h" + +#include <pthread.h> + +pthread_barrier_t barrier; +LIBC_NAMESPACE::cpp::Atomic<int> counter; + +void *increment_counter_and_wait(void *args) { + counter.fetch_add(1); + return reinterpret_cast<void *>( + LIBC_NAMESPACE::pthread_barrier_wait(&barrier)); +} + +void single_use_barrier_test(int num_threads) { + counter.set(0); + // create n - 1 ADDITIONAL threads since the current thread will also wait at + // the barrier + pthread_t threads[num_threads - 1]; + LIBC_NAMESPACE::memset(&barrier, 0, sizeof(pthread_barrier_t)); + ASSERT_EQ( + LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, num_threads), 0); + + for (int i = 0; i < num_threads - 1; ++i) + LIBC_NAMESPACE::pthread_create(&threads[i], nullptr, + increment_counter_and_wait, nullptr); + + uintptr_t return_val_sum = + reinterpret_cast<uintptr_t>(increment_counter_and_wait(nullptr)); + ASSERT_EQ(counter.load(), num_threads); + + // verify only one thread got the PTHREAD_BARRIER_SERIAL_THREAD return value + for (int i = 0; i < num_threads - 1; ++i) { + void *ret; + LIBC_NAMESPACE::pthread_join(threads[i], &ret); + if (reinterpret_cast<uintptr_t>(ret) == + static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)) { + return_val_sum += reinterpret_cast<uintptr_t>(ret); + } else { + ASSERT_EQ(ret, 0); + } + } + ASSERT_EQ(return_val_sum, + static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)); + + LIBC_NAMESPACE::pthread_barrier_destroy(&barrier); +} + +void reused_barrier_test() { + counter.set(0); + const int NUM_THREADS = 30; + const int REPEAT = 20; + pthread_t threads[NUM_THREADS - 1]; // subtract 1 for main thread + LIBC_NAMESPACE::memset(&barrier, 0, sizeof(pthread_barrier_t)); + ASSERT_EQ( + LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS), 0); + + for (int i = 0; i < REPEAT; ++i) { + for (int j = 0; j < NUM_THREADS - 1; ++j) + LIBC_NAMESPACE::pthread_create(&threads[j], nullptr, + increment_counter_and_wait, nullptr); + + uintptr_t return_val_sum = + reinterpret_cast<uintptr_t>(increment_counter_and_wait(nullptr)); + ASSERT_EQ(counter.load(), NUM_THREADS * (i + 1)); + + // verify only one thread got the PTHREAD_BARRIER_SERIAL_THREAD return value + for (int i = 0; i < NUM_THREADS - 1; ++i) { + void *ret; + LIBC_NAMESPACE::pthread_join(threads[i], &ret); + if (reinterpret_cast<uintptr_t>(ret) == + static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)) { + return_val_sum += reinterpret_cast<uintptr_t>(ret); + } else { + ASSERT_EQ(ret, 0); + } + } + ASSERT_EQ(return_val_sum, + static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)); + } + + LIBC_NAMESPACE::pthread_barrier_destroy(&barrier); +} + +void *barrier_wait(void *in) { + return reinterpret_cast<void *>( + LIBC_NAMESPACE::pthread_barrier_wait(&barrier)); +} + +TEST_MAIN() { + // don't create any additional threads; only use main thread + single_use_barrier_test(1); + + single_use_barrier_test(30); + reused_barrier_test(); + return 0; +} diff --git a/libc/test/integration/src/stdlib/gpu/malloc_stress.cpp b/libc/test/integration/src/stdlib/gpu/malloc_stress.cpp index 77479f8..4c540a8 100644 --- a/libc/test/integration/src/stdlib/gpu/malloc_stress.cpp +++ b/libc/test/integration/src/stdlib/gpu/malloc_stress.cpp @@ -14,6 +14,20 @@ using namespace LIBC_NAMESPACE; +static inline uint32_t entropy() { + return (static_cast<uint32_t>(gpu::processor_clock()) ^ + (gpu::get_thread_id_x() * 0x632be59b) ^ + (gpu::get_block_id_x() * 0x85157af5)) * + 0x9e3779bb; +} + +static inline uint32_t xorshift32(uint32_t &state) { + state ^= state << 13; + state ^= state >> 17; + state ^= state << 5; + return state * 0x9e3779bb; +} + static inline void use(uint8_t *ptr, uint32_t size) { EXPECT_NE(ptr, nullptr); for (int i = 0; i < size; ++i) @@ -34,5 +48,19 @@ TEST_MAIN(int, char **, char **) { for (int i = 0; i < 256; ++i) free(ptrs[i]); + + uint32_t state = entropy(); + for (int i = 0; i < 1024; ++i) { + if (xorshift32(state) % 2) { + uint64_t size = xorshift32(state) % 256 + 16; + uint64_t *ptr = reinterpret_cast<uint64_t *>(malloc(size)); + *ptr = gpu::get_thread_id(); + + EXPECT_EQ(*ptr, gpu::get_thread_id()); + ASSERT_TRUE(ptr); + ASSERT_TRUE(__builtin_is_aligned(ptr, 16)); + free(ptr); + } + } return 0; } |