1219820Sjeff/* 2219820Sjeff * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. 3219820Sjeff * 4219820Sjeff * Licensed under the OpenSSL license (the "License"). You may not use 5219820Sjeff * this file except in compliance with the License. You can obtain a copy 6219820Sjeff * in the file LICENSE in the source distribution or at 7219820Sjeff * https://www.openssl.org/source/license.html 8219820Sjeff */ 9219820Sjeff 10219820Sjeff#if defined(_WIN32) 11219820Sjeff# include <windows.h> 12219820Sjeff#endif 13219820Sjeff 14219820Sjeff#include <openssl/crypto.h> 15219820Sjeff#include "testutil.h" 16219820Sjeff 17219820Sjeff#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) 18219820Sjeff 19219820Sjefftypedef unsigned int thread_t; 20219820Sjeff 21219820Sjeffstatic int run_thread(thread_t *t, void (*f)(void)) 22219820Sjeff{ 23219820Sjeff f(); 24219820Sjeff return 1; 25219820Sjeff} 26219820Sjeff 27219820Sjeffstatic int wait_for_thread(thread_t thread) 28219820Sjeff{ 29219820Sjeff return 1; 30219820Sjeff} 31219820Sjeff 32255932Salfred#elif defined(OPENSSL_SYS_WINDOWS) 33219820Sjeff 34255932Salfredtypedef HANDLE thread_t; 35219820Sjeff 36219820Sjeffstatic DWORD WINAPI thread_run(LPVOID arg) 37{ 38 void (*f)(void); 39 40 *(void **) (&f) = arg; 41 42 f(); 43 return 0; 44} 45 46static int run_thread(thread_t *t, void (*f)(void)) 47{ 48 *t = CreateThread(NULL, 0, thread_run, *(void **) &f, 0, NULL); 49 return *t != NULL; 50} 51 52static int wait_for_thread(thread_t thread) 53{ 54 return WaitForSingleObject(thread, INFINITE) == 0; 55} 56 57#else 58 59typedef pthread_t thread_t; 60 61static void *thread_run(void *arg) 62{ 63 void (*f)(void); 64 65 *(void **) (&f) = arg; 66 67 f(); 68 return NULL; 69} 70 71static int run_thread(thread_t *t, void (*f)(void)) 72{ 73 return pthread_create(t, NULL, thread_run, *(void **) &f) == 0; 74} 75 76static int wait_for_thread(thread_t thread) 77{ 78 return pthread_join(thread, NULL) == 0; 79} 80 81#endif 82 83static int test_lock(void) 84{ 85 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); 86 87 if (!TEST_true(CRYPTO_THREAD_read_lock(lock)) 88 || !TEST_true(CRYPTO_THREAD_unlock(lock))) 89 return 0; 90 91 CRYPTO_THREAD_lock_free(lock); 92 93 return 1; 94} 95 96static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT; 97static unsigned once_run_count = 0; 98 99static void once_do_run(void) 100{ 101 once_run_count++; 102} 103 104static void once_run_thread_cb(void) 105{ 106 CRYPTO_THREAD_run_once(&once_run, once_do_run); 107} 108 109static int test_once(void) 110{ 111 thread_t thread; 112 113 if (!TEST_true(run_thread(&thread, once_run_thread_cb)) 114 || !TEST_true(wait_for_thread(thread)) 115 || !CRYPTO_THREAD_run_once(&once_run, once_do_run) 116 || !TEST_int_eq(once_run_count, 1)) 117 return 0; 118 return 1; 119} 120 121static CRYPTO_THREAD_LOCAL thread_local_key; 122static unsigned destructor_run_count = 0; 123static int thread_local_thread_cb_ok = 0; 124 125static void thread_local_destructor(void *arg) 126{ 127 unsigned *count; 128 129 if (arg == NULL) 130 return; 131 132 count = arg; 133 134 (*count)++; 135} 136 137static void thread_local_thread_cb(void) 138{ 139 void *ptr; 140 141 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 142 if (!TEST_ptr_null(ptr) 143 || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key, 144 &destructor_run_count))) 145 return; 146 147 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 148 if (!TEST_ptr_eq(ptr, &destructor_run_count)) 149 return; 150 151 thread_local_thread_cb_ok = 1; 152} 153 154static int test_thread_local(void) 155{ 156 thread_t thread; 157 void *ptr = NULL; 158 159 if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key, 160 thread_local_destructor))) 161 return 0; 162 163 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 164 if (!TEST_ptr_null(ptr) 165 || !TEST_true(run_thread(&thread, thread_local_thread_cb)) 166 || !TEST_true(wait_for_thread(thread)) 167 || !TEST_int_eq(thread_local_thread_cb_ok, 1)) 168 return 0; 169 170#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 171 172 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 173 if (!TEST_ptr_null(ptr)) 174 return 0; 175 176# if !defined(OPENSSL_SYS_WINDOWS) 177 if (!TEST_int_eq(destructor_run_count, 1)) 178 return 0; 179# endif 180#endif 181 182 if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key))) 183 return 0; 184 return 1; 185} 186 187int setup_tests(void) 188{ 189 ADD_TEST(test_lock); 190 ADD_TEST(test_once); 191 ADD_TEST(test_thread_local); 192 return 1; 193} 194