86 lines · cpp
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-exception6//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 20static constexpr int THREAD_DATA_INITVAL = 0x1234;21static constexpr int THREAD_DATA_FINIVAL = 0x4321;22static constexpr int THREAD_RUN_VAL = 0x600D;23 24static int child_thread_data = THREAD_DATA_INITVAL;25static int main_thread_data = THREAD_DATA_INITVAL;26 27static pthread_key_t key;28static 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.34static void dtor_failure(void *) { ASSERT_TRUE(false); }35 36static 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 46static void *func_null_val(void *) {47 // null value, we should not call dtor48 ASSERT_EQ(LIBC_NAMESPACE::pthread_setspecific(key, nullptr), 0);49 ASSERT_EQ(LIBC_NAMESPACE::pthread_getspecific(key), nullptr);50 return nullptr;51}52 53static 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 72static 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 81TEST_MAIN() {82 standard_usage_test();83 null_value_test();84 return 0;85}86