xref: /llvm-project/libc/test/integration/src/pthread/pthread_tss_test.cpp (revision b6bc9d72f65a5086f310f321e969d96e9a559e75)
14a738ee8SSiva Chandra Reddy //===-- Tests for TSS API like pthread_setspecific etc. -------------------===//
24a738ee8SSiva Chandra Reddy //
34a738ee8SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44a738ee8SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
54a738ee8SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64a738ee8SSiva Chandra Reddy //
74a738ee8SSiva Chandra Reddy //===----------------------------------------------------------------------===//
84a738ee8SSiva Chandra Reddy 
94a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_create.h"
104a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_exit.h"
114a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_getspecific.h"
124a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_join.h"
134a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_key_create.h"
144a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_key_delete.h"
154a738ee8SSiva Chandra Reddy #include "src/pthread/pthread_setspecific.h"
16af1315c2SSiva Chandra Reddy #include "test/IntegrationTest/test.h"
174a738ee8SSiva Chandra Reddy 
184a738ee8SSiva Chandra Reddy #include <pthread.h>
194a738ee8SSiva Chandra Reddy 
204a738ee8SSiva Chandra Reddy static constexpr int THREAD_DATA_INITVAL = 0x1234;
214a738ee8SSiva Chandra Reddy static constexpr int THREAD_DATA_FINIVAL = 0x4321;
224a738ee8SSiva Chandra Reddy static constexpr int THREAD_RUN_VAL = 0x600D;
234a738ee8SSiva Chandra Reddy 
246f1a9ed0SNoah Goldstein static int child_thread_data = THREAD_DATA_INITVAL;
256f1a9ed0SNoah Goldstein static int main_thread_data = THREAD_DATA_INITVAL;
264a738ee8SSiva Chandra Reddy 
276f1a9ed0SNoah Goldstein static pthread_key_t key;
dtor(void * data)286f1a9ed0SNoah Goldstein static void dtor(void *data) {
294a738ee8SSiva Chandra Reddy   auto *v = reinterpret_cast<int *>(data);
304a738ee8SSiva Chandra Reddy   *v = THREAD_DATA_FINIVAL;
314a738ee8SSiva Chandra Reddy }
324a738ee8SSiva Chandra Reddy 
336f1a9ed0SNoah Goldstein // Used to test that we don't call the destructor when the mapped value in NULL.
dtor_failure(void *)346f1a9ed0SNoah Goldstein static void dtor_failure(void *) { ASSERT_TRUE(false); }
356f1a9ed0SNoah Goldstein 
func(void * obj)366f1a9ed0SNoah Goldstein static void *func(void *obj) {
37*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, &child_thread_data), 0);
38*b6bc9d72SGuillaume Chatelet   int *d = reinterpret_cast<int *>(LIBC_NAMESPACE::pthread_getspecific(key));
394a738ee8SSiva Chandra Reddy   ASSERT_TRUE(d != nullptr);
404a738ee8SSiva Chandra Reddy   ASSERT_EQ(&child_thread_data, d);
414a738ee8SSiva Chandra Reddy   ASSERT_EQ(*d, THREAD_DATA_INITVAL);
424a738ee8SSiva Chandra Reddy   *reinterpret_cast<int *>(obj) = THREAD_RUN_VAL;
434a738ee8SSiva Chandra Reddy   return nullptr;
444a738ee8SSiva Chandra Reddy }
454a738ee8SSiva Chandra Reddy 
func_null_val(void *)466f1a9ed0SNoah Goldstein static void *func_null_val(void *) {
476f1a9ed0SNoah Goldstein   // null value, we should not call dtor
48*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, nullptr), 0);
49*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_getspecific(key), nullptr);
506f1a9ed0SNoah Goldstein   return nullptr;
516f1a9ed0SNoah Goldstein }
526f1a9ed0SNoah Goldstein 
standard_usage_test()536f1a9ed0SNoah Goldstein static void standard_usage_test() {
54*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_key_create(&key, &dtor), 0);
55*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, &main_thread_data), 0);
56*b6bc9d72SGuillaume Chatelet   int *d = reinterpret_cast<int *>(LIBC_NAMESPACE::pthread_getspecific(key));
574a738ee8SSiva Chandra Reddy   ASSERT_TRUE(d != nullptr);
584a738ee8SSiva Chandra Reddy   ASSERT_EQ(&main_thread_data, d);
594a738ee8SSiva Chandra Reddy   ASSERT_EQ(*d, THREAD_DATA_INITVAL);
604a738ee8SSiva Chandra Reddy 
614a738ee8SSiva Chandra Reddy   pthread_t th;
624a738ee8SSiva Chandra Reddy   int arg = 0xBAD;
63*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&th, nullptr, &func, &arg), 0);
644a738ee8SSiva Chandra Reddy   void *retval = &child_thread_data; // Init to some non-nullptr val.
65*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, &retval), 0);
664a738ee8SSiva Chandra Reddy   ASSERT_EQ(retval, nullptr);
674a738ee8SSiva Chandra Reddy   ASSERT_EQ(arg, THREAD_RUN_VAL);
684a738ee8SSiva Chandra Reddy   ASSERT_EQ(child_thread_data, THREAD_DATA_FINIVAL);
69*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_key_delete(key), 0);
706f1a9ed0SNoah Goldstein }
716f1a9ed0SNoah Goldstein 
null_value_test()726f1a9ed0SNoah Goldstein static void null_value_test() {
736f1a9ed0SNoah Goldstein   pthread_t th;
74*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_key_create(&key, &dtor_failure), 0);
75*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(
76*b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::pthread_create(&th, nullptr, &func_null_val, nullptr), 0);
77*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, nullptr), 0);
78*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_key_delete(key), 0);
796f1a9ed0SNoah Goldstein }
806f1a9ed0SNoah Goldstein 
TEST_MAIN()816f1a9ed0SNoah Goldstein TEST_MAIN() {
826f1a9ed0SNoah Goldstein   standard_usage_test();
836f1a9ed0SNoah Goldstein   null_value_test();
844a738ee8SSiva Chandra Reddy   return 0;
854a738ee8SSiva Chandra Reddy }
86