2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 #include <openssl/crypto.h>
14 #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
16 typedef unsigned int thread_t;
18 static int run_thread(thread_t *t, void (*f)(void))
24 static int wait_for_thread(thread_t thread)
29 #elif defined(OPENSSL_SYS_WINDOWS)
31 typedef HANDLE thread_t;
33 static DWORD WINAPI thread_run(LPVOID arg)
37 *(void **) (&f) = arg;
43 static int run_thread(thread_t *t, void (*f)(void))
45 *t = CreateThread(NULL, 0, thread_run, *(void **) &f, 0, NULL);
49 static int wait_for_thread(thread_t thread)
51 return WaitForSingleObject(thread, INFINITE) == 0;
56 typedef pthread_t thread_t;
58 static void *thread_run(void *arg)
62 *(void **) (&f) = arg;
68 static int run_thread(thread_t *t, void (*f)(void))
70 return pthread_create(t, NULL, thread_run, *(void **) &f) == 0;
73 static int wait_for_thread(thread_t thread)
75 return pthread_join(thread, NULL) == 0;
80 static int test_lock(void)
82 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
84 if (!CRYPTO_THREAD_read_lock(lock)) {
85 fprintf(stderr, "CRYPTO_THREAD_read_lock() failed\n");
89 if (!CRYPTO_THREAD_unlock(lock)) {
90 fprintf(stderr, "CRYPTO_THREAD_unlock() failed\n");
94 CRYPTO_THREAD_lock_free(lock);
99 static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
100 static unsigned once_run_count = 0;
102 static void once_do_run(void)
107 static void once_run_thread_cb(void)
109 CRYPTO_THREAD_run_once(&once_run, once_do_run);
112 static int test_once(void)
115 if (!run_thread(&thread, once_run_thread_cb) ||
116 !wait_for_thread(thread))
118 fprintf(stderr, "run_thread() failed\n");
122 if (!CRYPTO_THREAD_run_once(&once_run, once_do_run)) {
123 fprintf(stderr, "CRYPTO_THREAD_run_once() failed\n");
127 if (once_run_count != 1) {
128 fprintf(stderr, "once run %u times\n", once_run_count);
135 static CRYPTO_THREAD_LOCAL thread_local_key;
136 static unsigned destructor_run_count = 0;
137 static int thread_local_thread_cb_ok = 0;
139 static void thread_local_destructor(void *arg)
151 static void thread_local_thread_cb(void)
155 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
157 fprintf(stderr, "ptr not NULL\n");
161 if (!CRYPTO_THREAD_set_local(&thread_local_key, &destructor_run_count)) {
162 fprintf(stderr, "CRYPTO_THREAD_set_local() failed\n");
166 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
167 if (ptr != &destructor_run_count) {
168 fprintf(stderr, "invalid ptr\n");
172 thread_local_thread_cb_ok = 1;
175 static int test_thread_local(void)
180 if (!CRYPTO_THREAD_init_local(&thread_local_key, thread_local_destructor)) {
181 fprintf(stderr, "CRYPTO_THREAD_init_local() failed\n");
185 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
187 fprintf(stderr, "ptr not NULL\n");
191 if (!run_thread(&thread, thread_local_thread_cb) ||
192 !wait_for_thread(thread))
194 fprintf(stderr, "run_thread() failed\n");
198 if (thread_local_thread_cb_ok != 1) {
199 fprintf(stderr, "thread-local thread callback failed\n");
203 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
205 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
207 fprintf(stderr, "ptr not NULL\n");
211 # if !defined(OPENSSL_SYS_WINDOWS)
212 if (destructor_run_count != 1) {
213 fprintf(stderr, "thread-local destructor run %u times\n",
214 destructor_run_count);
221 if (!CRYPTO_THREAD_cleanup_local(&thread_local_key)) {
222 fprintf(stderr, "CRYPTO_THREAD_cleanup_local() failed\n");
229 int main(int argc, char **argv)
237 if (!test_thread_local())