1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <assert.h> 6#include <zircon/syscalls.h> 7#include <unittest/unittest.h> 8#include <pthread.h> 9#include <stdatomic.h> 10#include <stdio.h> 11#include <unistd.h> 12 13static pthread_key_t tsd_key; 14static pthread_key_t tsd_key_dtor; 15static atomic_int dtor_count = ATOMIC_VAR_INIT(0); 16 17void dtor(void* unused) { 18 atomic_fetch_add(&dtor_count, 1); 19} 20 21static void test_tls(int thread_no) { 22 int value1 = thread_no; 23 int value2 = thread_no + 10; 24 EXPECT_EQ(pthread_setspecific(tsd_key, &value1), 0, 25 "Error while setting tls value"); 26 EXPECT_EQ(pthread_setspecific(tsd_key_dtor, &value2), 0, 27 "Error while setting tls value"); 28 zx_nanosleep(zx_deadline_after(ZX_MSEC(100))); 29 int* v = pthread_getspecific(tsd_key); 30 EXPECT_EQ(*v, value1, "wrong TLS value for key"); 31 v = pthread_getspecific(tsd_key_dtor); 32 EXPECT_EQ(*v, value2, "wrong TLS value for key_dtor"); 33 unittest_printf("tls_test completed for thread: %d\n", thread_no); 34} 35 36static void* do_work(void* arg) { 37 unittest_printf("do_work for thread: %d\n", *(int*)arg); 38 test_tls(*(int*)arg); 39 return NULL; 40} 41 42bool tls_test(void) { 43 BEGIN_TEST; 44 ASSERT_EQ(pthread_key_create(&tsd_key, NULL), 0, "Error during key creation"); 45 ASSERT_EQ(pthread_key_create(&tsd_key_dtor, dtor), 0, "Error during key creation"); 46 47 int expected_dtor_count = 0; 48 49 // Run this 20 times for sanity check 50 for (int i = 1; i <= 20; i++) { 51 int main_thread = 1, thread_1 = i * 2, thread_2 = i * 2 + 1; 52 53 pthread_t thread2, thread3; 54 55 unittest_printf("creating thread: %d\n", thread_1); 56 pthread_create(&thread2, NULL, do_work, &thread_1); 57 58 unittest_printf("creating thread: %d\n", thread_2); 59 pthread_create(&thread3, NULL, do_work, &thread_2); 60 61 test_tls(main_thread); 62 63 unittest_printf("joining thread: %d\n", thread_1); 64 pthread_join(thread2, NULL); 65 66 unittest_printf("joining thread: %d\n", thread_2); 67 pthread_join(thread3, NULL); 68 69 expected_dtor_count += 2; 70 ASSERT_EQ(atomic_load(&dtor_count), expected_dtor_count, "dtors not run"); 71 } 72 END_TEST; 73} 74 75BEGIN_TEST_CASE(tls_tests) 76RUN_TEST(tls_test) 77END_TEST_CASE(tls_tests) 78 79#ifndef BUILD_COMBINED_TESTS 80int main(int argc, char** argv) { 81 return unittest_run_all_tests(argc, argv) ? 0 : -1; 82} 83#endif 84