]>
Commit | Line | Data |
---|---|---|
440e5d80 | 1 | /* |
ee25dd45 | 2 | * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. |
71a04cfc | 3 | * |
909f1a2e | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
440e5d80 RS |
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 | |
71a04cfc AG |
8 | */ |
9 | ||
f1f5ee17 AP |
10 | #if defined(_WIN32) |
11 | # include <windows.h> | |
12 | #endif | |
13 | ||
71a04cfc | 14 | #include <openssl/crypto.h> |
ee25dd45 | 15 | #include "testutil.h" |
71a04cfc AG |
16 | |
17 | #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) | |
18 | ||
19 | typedef unsigned int thread_t; | |
20 | ||
21 | static int run_thread(thread_t *t, void (*f)(void)) | |
22 | { | |
23 | f(); | |
24 | return 1; | |
25 | } | |
26 | ||
27 | static int wait_for_thread(thread_t thread) | |
28 | { | |
29 | return 1; | |
30 | } | |
31 | ||
32 | #elif defined(OPENSSL_SYS_WINDOWS) | |
33 | ||
34 | typedef HANDLE thread_t; | |
35 | ||
36 | static DWORD WINAPI thread_run(LPVOID arg) | |
37 | { | |
38 | void (*f)(void); | |
39 | ||
40 | *(void **) (&f) = arg; | |
41 | ||
42 | f(); | |
43 | return 0; | |
44 | } | |
45 | ||
46 | static 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 | ||
52 | static int wait_for_thread(thread_t thread) | |
53 | { | |
54 | return WaitForSingleObject(thread, INFINITE) == 0; | |
55 | } | |
56 | ||
57 | #else | |
58 | ||
59 | typedef pthread_t thread_t; | |
60 | ||
61 | static void *thread_run(void *arg) | |
62 | { | |
63 | void (*f)(void); | |
64 | ||
65 | *(void **) (&f) = arg; | |
66 | ||
67 | f(); | |
68 | return NULL; | |
69 | } | |
70 | ||
71 | static int run_thread(thread_t *t, void (*f)(void)) | |
72 | { | |
73 | return pthread_create(t, NULL, thread_run, *(void **) &f) == 0; | |
74 | } | |
75 | ||
76 | static int wait_for_thread(thread_t thread) | |
77 | { | |
78 | return pthread_join(thread, NULL) == 0; | |
79 | } | |
80 | ||
81 | #endif | |
82 | ||
83 | static int test_lock(void) | |
84 | { | |
85 | CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); | |
86 | ||
ee25dd45 P |
87 | if (!TEST_true(CRYPTO_THREAD_read_lock(lock)) |
88 | || !TEST_true(CRYPTO_THREAD_unlock(lock))) | |
71a04cfc | 89 | return 0; |
71a04cfc AG |
90 | |
91 | CRYPTO_THREAD_lock_free(lock); | |
92 | ||
93 | return 1; | |
94 | } | |
95 | ||
96 | static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT; | |
97 | static unsigned once_run_count = 0; | |
98 | ||
99 | static void once_do_run(void) | |
100 | { | |
101 | once_run_count++; | |
102 | } | |
103 | ||
104 | static void once_run_thread_cb(void) | |
105 | { | |
106 | CRYPTO_THREAD_run_once(&once_run, once_do_run); | |
107 | } | |
108 | ||
109 | static int test_once(void) | |
110 | { | |
111 | thread_t thread; | |
71a04cfc | 112 | |
ee25dd45 P |
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)) | |
71a04cfc | 117 | return 0; |
71a04cfc AG |
118 | return 1; |
119 | } | |
120 | ||
121 | static CRYPTO_THREAD_LOCAL thread_local_key; | |
122 | static unsigned destructor_run_count = 0; | |
123 | static int thread_local_thread_cb_ok = 0; | |
124 | ||
125 | static 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 | ||
137 | static void thread_local_thread_cb(void) | |
138 | { | |
139 | void *ptr; | |
140 | ||
141 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 P |
142 | if (!TEST_ptr_null(ptr) |
143 | || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key, | |
144 | &destructor_run_count))) | |
71a04cfc | 145 | return; |
71a04cfc AG |
146 | |
147 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 | 148 | if (!TEST_ptr_eq(ptr, &destructor_run_count)) |
71a04cfc | 149 | return; |
71a04cfc AG |
150 | |
151 | thread_local_thread_cb_ok = 1; | |
152 | } | |
153 | ||
154 | static int test_thread_local(void) | |
155 | { | |
156 | thread_t thread; | |
157 | void *ptr = NULL; | |
158 | ||
ee25dd45 P |
159 | if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key, |
160 | thread_local_destructor))) | |
71a04cfc | 161 | return 0; |
71a04cfc AG |
162 | |
163 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 P |
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)) | |
71a04cfc | 168 | return 0; |
71a04cfc AG |
169 | |
170 | #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) | |
171 | ||
172 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 | 173 | if (!TEST_ptr_null(ptr)) |
71a04cfc | 174 | return 0; |
71a04cfc AG |
175 | |
176 | # if !defined(OPENSSL_SYS_WINDOWS) | |
ee25dd45 | 177 | if (!TEST_int_eq(destructor_run_count, 1)) |
71a04cfc | 178 | return 0; |
71a04cfc | 179 | # endif |
71a04cfc AG |
180 | #endif |
181 | ||
ee25dd45 | 182 | if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key))) |
71a04cfc | 183 | return 0; |
71a04cfc AG |
184 | return 1; |
185 | } | |
186 | ||
ad887416 | 187 | int setup_tests(void) |
71a04cfc | 188 | { |
ee25dd45 P |
189 | ADD_TEST(test_lock); |
190 | ADD_TEST(test_once); | |
191 | ADD_TEST(test_thread_local); | |
ad887416 | 192 | return 1; |
71a04cfc | 193 | } |