118 lines · cpp
1//===-- Tests for pthread_barrier_t ---------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/pthread/pthread_barrier_destroy.h"10#include "src/pthread/pthread_barrier_init.h"11#include "src/pthread/pthread_barrier_wait.h"12 13#include "src/__support/CPP/atomic.h"14#include "src/pthread/pthread_create.h"15#include "src/pthread/pthread_join.h"16#include "src/pthread/pthread_mutex_destroy.h"17#include "src/pthread/pthread_mutex_init.h"18#include "src/pthread/pthread_mutex_lock.h"19#include "src/pthread/pthread_mutex_unlock.h"20#include "src/string/memset.h"21 22#include "test/IntegrationTest/test.h"23 24#include <pthread.h>25 26pthread_barrier_t barrier;27LIBC_NAMESPACE::cpp::Atomic<int> counter;28 29void *increment_counter_and_wait(void *args) {30 counter.fetch_add(1);31 return reinterpret_cast<void *>(32 LIBC_NAMESPACE::pthread_barrier_wait(&barrier));33}34 35void single_use_barrier_test(int num_threads) {36 counter.set(0);37 // create n - 1 ADDITIONAL threads since the current thread will also wait at38 // the barrier39 pthread_t threads[num_threads - 1];40 LIBC_NAMESPACE::memset(&barrier, 0, sizeof(pthread_barrier_t));41 ASSERT_EQ(42 LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, num_threads), 0);43 44 for (int i = 0; i < num_threads - 1; ++i)45 LIBC_NAMESPACE::pthread_create(&threads[i], nullptr,46 increment_counter_and_wait, nullptr);47 48 uintptr_t return_val_sum =49 reinterpret_cast<uintptr_t>(increment_counter_and_wait(nullptr));50 ASSERT_EQ(counter.load(), num_threads);51 52 // verify only one thread got the PTHREAD_BARRIER_SERIAL_THREAD return value53 for (int i = 0; i < num_threads - 1; ++i) {54 void *ret;55 LIBC_NAMESPACE::pthread_join(threads[i], &ret);56 if (reinterpret_cast<uintptr_t>(ret) ==57 static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)) {58 return_val_sum += reinterpret_cast<uintptr_t>(ret);59 } else {60 ASSERT_EQ(ret, 0);61 }62 }63 ASSERT_EQ(return_val_sum,64 static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD));65 66 LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);67}68 69void reused_barrier_test() {70 counter.set(0);71 const int NUM_THREADS = 30;72 const int REPEAT = 20;73 pthread_t threads[NUM_THREADS - 1]; // subtract 1 for main thread74 LIBC_NAMESPACE::memset(&barrier, 0, sizeof(pthread_barrier_t));75 ASSERT_EQ(76 LIBC_NAMESPACE::pthread_barrier_init(&barrier, nullptr, NUM_THREADS), 0);77 78 for (int i = 0; i < REPEAT; ++i) {79 for (int j = 0; j < NUM_THREADS - 1; ++j)80 LIBC_NAMESPACE::pthread_create(&threads[j], nullptr,81 increment_counter_and_wait, nullptr);82 83 uintptr_t return_val_sum =84 reinterpret_cast<uintptr_t>(increment_counter_and_wait(nullptr));85 ASSERT_EQ(counter.load(), NUM_THREADS * (i + 1));86 87 // verify only one thread got the PTHREAD_BARRIER_SERIAL_THREAD return value88 for (int i = 0; i < NUM_THREADS - 1; ++i) {89 void *ret;90 LIBC_NAMESPACE::pthread_join(threads[i], &ret);91 if (reinterpret_cast<uintptr_t>(ret) ==92 static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD)) {93 return_val_sum += reinterpret_cast<uintptr_t>(ret);94 } else {95 ASSERT_EQ(ret, 0);96 }97 }98 ASSERT_EQ(return_val_sum,99 static_cast<uintptr_t>(PTHREAD_BARRIER_SERIAL_THREAD));100 }101 102 LIBC_NAMESPACE::pthread_barrier_destroy(&barrier);103}104 105void *barrier_wait(void *in) {106 return reinterpret_cast<void *>(107 LIBC_NAMESPACE::pthread_barrier_wait(&barrier));108}109 110TEST_MAIN() {111 // don't create any additional threads; only use main thread112 single_use_barrier_test(1);113 114 single_use_barrier_test(30);115 reused_barrier_test();116 return 0;117}118