1 //===-- Tests for TSS API like pthread_setspecific etc. -------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "src/pthread/pthread_create.h"
10 #include "src/pthread/pthread_exit.h"
11 #include "src/pthread/pthread_getspecific.h"
12 #include "src/pthread/pthread_join.h"
13 #include "src/pthread/pthread_key_create.h"
14 #include "src/pthread/pthread_key_delete.h"
15 #include "src/pthread/pthread_setspecific.h"
16 #include "test/IntegrationTest/test.h"
17
18 #include <pthread.h>
19
20 static constexpr int THREAD_DATA_INITVAL = 0x1234;
21 static constexpr int THREAD_DATA_FINIVAL = 0x4321;
22 static constexpr int THREAD_RUN_VAL = 0x600D;
23
24 static int child_thread_data = THREAD_DATA_INITVAL;
25 static int main_thread_data = THREAD_DATA_INITVAL;
26
27 static pthread_key_t key;
dtor(void * data)28 static void dtor(void *data) {
29 auto *v = reinterpret_cast<int *>(data);
30 *v = THREAD_DATA_FINIVAL;
31 }
32
33 // Used to test that we don't call the destructor when the mapped value in NULL.
dtor_failure(void *)34 static void dtor_failure(void *) { ASSERT_TRUE(false); }
35
func(void * obj)36 static void *func(void *obj) {
37 ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, &child_thread_data), 0);
38 int *d = reinterpret_cast<int *>(LIBC_NAMESPACE::pthread_getspecific(key));
39 ASSERT_TRUE(d != nullptr);
40 ASSERT_EQ(&child_thread_data, d);
41 ASSERT_EQ(*d, THREAD_DATA_INITVAL);
42 *reinterpret_cast<int *>(obj) = THREAD_RUN_VAL;
43 return nullptr;
44 }
45
func_null_val(void *)46 static void *func_null_val(void *) {
47 // null value, we should not call dtor
48 ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, nullptr), 0);
49 ASSERT_EQ(LIBC_NAMESPACE::pthread_getspecific(key), nullptr);
50 return nullptr;
51 }
52
standard_usage_test()53 static void standard_usage_test() {
54 ASSERT_EQ(LIBC_NAMESPACE::pthread_key_create(&key, &dtor), 0);
55 ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, &main_thread_data), 0);
56 int *d = reinterpret_cast<int *>(LIBC_NAMESPACE::pthread_getspecific(key));
57 ASSERT_TRUE(d != nullptr);
58 ASSERT_EQ(&main_thread_data, d);
59 ASSERT_EQ(*d, THREAD_DATA_INITVAL);
60
61 pthread_t th;
62 int arg = 0xBAD;
63 ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&th, nullptr, &func, &arg), 0);
64 void *retval = &child_thread_data; // Init to some non-nullptr val.
65 ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, &retval), 0);
66 ASSERT_EQ(retval, nullptr);
67 ASSERT_EQ(arg, THREAD_RUN_VAL);
68 ASSERT_EQ(child_thread_data, THREAD_DATA_FINIVAL);
69 ASSERT_EQ(LIBC_NAMESPACE::pthread_key_delete(key), 0);
70 }
71
null_value_test()72 static void null_value_test() {
73 pthread_t th;
74 ASSERT_EQ(LIBC_NAMESPACE::pthread_key_create(&key, &dtor_failure), 0);
75 ASSERT_EQ(
76 LIBC_NAMESPACE::pthread_create(&th, nullptr, &func_null_val, nullptr), 0);
77 ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, nullptr), 0);
78 ASSERT_EQ(LIBC_NAMESPACE::pthread_key_delete(key), 0);
79 }
80
TEST_MAIN()81 TEST_MAIN() {
82 standard_usage_test();
83 null_value_test();
84 return 0;
85 }
86