133675390SSiva Chandra Reddy //===-- Tests for pthread_once --------------------------------------------===//
233675390SSiva Chandra Reddy //
333675390SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
433675390SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
533675390SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
633675390SSiva Chandra Reddy //
733675390SSiva Chandra Reddy //===----------------------------------------------------------------------===//
833675390SSiva Chandra Reddy
933675390SSiva Chandra Reddy #include "src/__support/CPP/atomic.h"
1033675390SSiva Chandra Reddy #include "src/pthread/pthread_create.h"
1133675390SSiva Chandra Reddy #include "src/pthread/pthread_join.h"
1233675390SSiva Chandra Reddy #include "src/pthread/pthread_mutex_destroy.h"
1333675390SSiva Chandra Reddy #include "src/pthread/pthread_mutex_init.h"
1433675390SSiva Chandra Reddy #include "src/pthread/pthread_mutex_lock.h"
1533675390SSiva Chandra Reddy #include "src/pthread/pthread_mutex_unlock.h"
1633675390SSiva Chandra Reddy #include "src/pthread/pthread_once.h"
1733675390SSiva Chandra Reddy
18af1315c2SSiva Chandra Reddy #include "test/IntegrationTest/test.h"
1933675390SSiva Chandra Reddy
2033675390SSiva Chandra Reddy #include <pthread.h>
21d9c135cfSGuillaume Chatelet #include <stdint.h> // uintptr_t
2233675390SSiva Chandra Reddy
2333675390SSiva Chandra Reddy static constexpr unsigned int NUM_THREADS = 5;
24*b6bc9d72SGuillaume Chatelet static LIBC_NAMESPACE::cpp::Atomic<unsigned int> thread_count;
2533675390SSiva Chandra Reddy
2633675390SSiva Chandra Reddy static unsigned int call_count;
pthread_once_func()2733675390SSiva Chandra Reddy static void pthread_once_func() { ++call_count; }
2833675390SSiva Chandra Reddy
func(void *)2933675390SSiva Chandra Reddy static void *func(void *) {
3033675390SSiva Chandra Reddy static pthread_once_t flag = PTHREAD_ONCE_INIT;
31*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_once(&flag, pthread_once_func), 0);
3233675390SSiva Chandra Reddy
3333675390SSiva Chandra Reddy thread_count.fetch_add(1);
3433675390SSiva Chandra Reddy
3533675390SSiva Chandra Reddy return nullptr;
3633675390SSiva Chandra Reddy }
3733675390SSiva Chandra Reddy
call_from_5_threads()3833675390SSiva Chandra Reddy void call_from_5_threads() {
3933675390SSiva Chandra Reddy // Ensure the call count and thread count are 0 to begin with.
4033675390SSiva Chandra Reddy call_count = 0;
4133675390SSiva Chandra Reddy thread_count = 0;
4233675390SSiva Chandra Reddy
4333675390SSiva Chandra Reddy pthread_t threads[NUM_THREADS];
4433675390SSiva Chandra Reddy for (unsigned int i = 0; i < NUM_THREADS; ++i) {
45*b6bc9d72SGuillaume Chatelet ASSERT_EQ(
46*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_create(threads + i, nullptr, func, nullptr), 0);
4733675390SSiva Chandra Reddy }
4833675390SSiva Chandra Reddy
4933675390SSiva Chandra Reddy for (unsigned int i = 0; i < NUM_THREADS; ++i) {
5033675390SSiva Chandra Reddy void *retval;
51*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_join(threads[i], &retval), 0);
5233675390SSiva Chandra Reddy ASSERT_EQ(uintptr_t(retval), uintptr_t(0));
5333675390SSiva Chandra Reddy }
5433675390SSiva Chandra Reddy
5533675390SSiva Chandra Reddy EXPECT_EQ(thread_count.val, 5U);
5633675390SSiva Chandra Reddy EXPECT_EQ(call_count, 1U);
5733675390SSiva Chandra Reddy }
5833675390SSiva Chandra Reddy
5933675390SSiva Chandra Reddy static pthread_mutex_t once_func_blocker;
blocking_once_func()6033675390SSiva Chandra Reddy static void blocking_once_func() {
61*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_mutex_lock(&once_func_blocker);
62*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_mutex_unlock(&once_func_blocker);
6333675390SSiva Chandra Reddy }
6433675390SSiva Chandra Reddy
65*b6bc9d72SGuillaume Chatelet static LIBC_NAMESPACE::cpp::Atomic<unsigned int> start_count;
66*b6bc9d72SGuillaume Chatelet static LIBC_NAMESPACE::cpp::Atomic<unsigned int> done_count;
once_func_caller(void *)6733675390SSiva Chandra Reddy static void *once_func_caller(void *) {
6833675390SSiva Chandra Reddy static pthread_once_t flag;
6933675390SSiva Chandra Reddy start_count.fetch_add(1);
70*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_once(&flag, blocking_once_func);
7133675390SSiva Chandra Reddy done_count.fetch_add(1);
7233675390SSiva Chandra Reddy return nullptr;
7333675390SSiva Chandra Reddy }
7433675390SSiva Chandra Reddy
7533675390SSiva Chandra Reddy // Test the synchronization aspect of the pthread_once function.
7633675390SSiva Chandra Reddy // This is not a fool proof test, but something which might be
7733675390SSiva Chandra Reddy // useful when we add a flakiness detection scheme to UnitTest.
test_synchronization()7833675390SSiva Chandra Reddy void test_synchronization() {
7933675390SSiva Chandra Reddy start_count = 0;
8033675390SSiva Chandra Reddy done_count = 0;
8133675390SSiva Chandra Reddy
82*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&once_func_blocker, nullptr), 0);
8333675390SSiva Chandra Reddy // Lock the blocking mutex so that the once func blocks.
84*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&once_func_blocker), 0);
8533675390SSiva Chandra Reddy
8633675390SSiva Chandra Reddy pthread_t t1, t2;
8733675390SSiva Chandra Reddy ASSERT_EQ(
88*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_create(&t1, nullptr, once_func_caller, nullptr),
89*b6bc9d72SGuillaume Chatelet 0);
9033675390SSiva Chandra Reddy ASSERT_EQ(
91*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_create(&t2, nullptr, once_func_caller, nullptr),
92*b6bc9d72SGuillaume Chatelet 0);
9333675390SSiva Chandra Reddy
9433675390SSiva Chandra Reddy while (start_count.load() != 2)
9533675390SSiva Chandra Reddy ; // Spin until both threads start.
9633675390SSiva Chandra Reddy
9733675390SSiva Chandra Reddy // Since the once func is blocked, the threads should not be done yet.
9833675390SSiva Chandra Reddy EXPECT_EQ(done_count.val, 0U);
9933675390SSiva Chandra Reddy
10033675390SSiva Chandra Reddy // Unlock the blocking mutex so that the once func blocks.
101*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&once_func_blocker), 0);
10233675390SSiva Chandra Reddy
10333675390SSiva Chandra Reddy void *retval;
104*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_join(t1, &retval), uintptr_t(0));
10533675390SSiva Chandra Reddy ASSERT_EQ(uintptr_t(retval), 0);
106*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::pthread_join(t2, &retval), uintptr_t(0));
10733675390SSiva Chandra Reddy ASSERT_EQ(uintptr_t(retval), 0);
10833675390SSiva Chandra Reddy
10933675390SSiva Chandra Reddy ASSERT_EQ(done_count.val, 2U);
11033675390SSiva Chandra Reddy
111*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_mutex_destroy(&once_func_blocker);
11233675390SSiva Chandra Reddy }
11333675390SSiva Chandra Reddy
TEST_MAIN()11433675390SSiva Chandra Reddy TEST_MAIN() {
11533675390SSiva Chandra Reddy call_from_5_threads();
11633675390SSiva Chandra Reddy test_synchronization();
11733675390SSiva Chandra Reddy return 0;
11833675390SSiva Chandra Reddy }
119