]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/threadstest.c
Update the internal chacha test to use the framework
[thirdparty/openssl.git] / test / threadstest.c
CommitLineData
440e5d80
RS
1/*
2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
71a04cfc 3 *
440e5d80
RS
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
71a04cfc
AG
8 */
9
f1f5ee17
AP
10#if defined(_WIN32)
11# include <windows.h>
12#endif
13
71a04cfc
AG
14#include <stdio.h>
15
16#include <openssl/crypto.h>
71a04cfc
AG
17
18#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
19
20typedef unsigned int thread_t;
21
22static int run_thread(thread_t *t, void (*f)(void))
23{
24 f();
25 return 1;
26}
27
28static int wait_for_thread(thread_t thread)
29{
30 return 1;
31}
32
33#elif defined(OPENSSL_SYS_WINDOWS)
34
35typedef HANDLE thread_t;
36
37static DWORD WINAPI thread_run(LPVOID arg)
38{
39 void (*f)(void);
40
41 *(void **) (&f) = arg;
42
43 f();
44 return 0;
45}
46
47static int run_thread(thread_t *t, void (*f)(void))
48{
49 *t = CreateThread(NULL, 0, thread_run, *(void **) &f, 0, NULL);
50 return *t != NULL;
51}
52
53static int wait_for_thread(thread_t thread)
54{
55 return WaitForSingleObject(thread, INFINITE) == 0;
56}
57
58#else
59
60typedef pthread_t thread_t;
61
62static void *thread_run(void *arg)
63{
64 void (*f)(void);
65
66 *(void **) (&f) = arg;
67
68 f();
69 return NULL;
70}
71
72static int run_thread(thread_t *t, void (*f)(void))
73{
74 return pthread_create(t, NULL, thread_run, *(void **) &f) == 0;
75}
76
77static int wait_for_thread(thread_t thread)
78{
79 return pthread_join(thread, NULL) == 0;
80}
81
82#endif
83
84static int test_lock(void)
85{
86 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
87
88 if (!CRYPTO_THREAD_read_lock(lock)) {
89 fprintf(stderr, "CRYPTO_THREAD_read_lock() failed\n");
90 return 0;
91 }
92
93 if (!CRYPTO_THREAD_unlock(lock)) {
94 fprintf(stderr, "CRYPTO_THREAD_unlock() failed\n");
95 return 0;
96 }
97
98 CRYPTO_THREAD_lock_free(lock);
99
100 return 1;
101}
102
103static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
104static unsigned once_run_count = 0;
105
106static void once_do_run(void)
107{
108 once_run_count++;
109}
110
111static void once_run_thread_cb(void)
112{
113 CRYPTO_THREAD_run_once(&once_run, once_do_run);
114}
115
116static int test_once(void)
117{
118 thread_t thread;
119 if (!run_thread(&thread, once_run_thread_cb) ||
120 !wait_for_thread(thread))
121 {
122 fprintf(stderr, "run_thread() failed\n");
123 return 0;
124 }
125
126 if (!CRYPTO_THREAD_run_once(&once_run, once_do_run)) {
127 fprintf(stderr, "CRYPTO_THREAD_run_once() failed\n");
128 return 0;
129 }
130
131 if (once_run_count != 1) {
132 fprintf(stderr, "once run %u times\n", once_run_count);
133 return 0;
134 }
135
136 return 1;
137}
138
139static CRYPTO_THREAD_LOCAL thread_local_key;
140static unsigned destructor_run_count = 0;
141static int thread_local_thread_cb_ok = 0;
142
143static void thread_local_destructor(void *arg)
144{
145 unsigned *count;
146
147 if (arg == NULL)
148 return;
149
150 count = arg;
151
152 (*count)++;
153}
154
155static void thread_local_thread_cb(void)
156{
157 void *ptr;
158
159 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
160 if (ptr != NULL) {
161 fprintf(stderr, "ptr not NULL\n");
162 return;
163 }
164
165 if (!CRYPTO_THREAD_set_local(&thread_local_key, &destructor_run_count)) {
166 fprintf(stderr, "CRYPTO_THREAD_set_local() failed\n");
167 return;
168 }
169
170 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
171 if (ptr != &destructor_run_count) {
172 fprintf(stderr, "invalid ptr\n");
173 return;
174 }
175
176 thread_local_thread_cb_ok = 1;
177}
178
179static int test_thread_local(void)
180{
181 thread_t thread;
182 void *ptr = NULL;
183
184 if (!CRYPTO_THREAD_init_local(&thread_local_key, thread_local_destructor)) {
185 fprintf(stderr, "CRYPTO_THREAD_init_local() failed\n");
186 return 0;
187 }
188
189 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
190 if (ptr != NULL) {
191 fprintf(stderr, "ptr not NULL\n");
192 return 0;
193 }
194
195 if (!run_thread(&thread, thread_local_thread_cb) ||
196 !wait_for_thread(thread))
197 {
198 fprintf(stderr, "run_thread() failed\n");
199 return 0;
200 }
201
202 if (thread_local_thread_cb_ok != 1) {
203 fprintf(stderr, "thread-local thread callback failed\n");
204 return 0;
205 }
206
207#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
208
209 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
210 if (ptr != NULL) {
211 fprintf(stderr, "ptr not NULL\n");
212 return 0;
213 }
214
215# if !defined(OPENSSL_SYS_WINDOWS)
216 if (destructor_run_count != 1) {
217 fprintf(stderr, "thread-local destructor run %u times\n",
218 destructor_run_count);
219 return 0;
220 }
221# endif
222
223#endif
224
225 if (!CRYPTO_THREAD_cleanup_local(&thread_local_key)) {
226 fprintf(stderr, "CRYPTO_THREAD_cleanup_local() failed\n");
227 return 0;
228 }
229
230 return 1;
231}
232
233int main(int argc, char **argv)
234{
235 if (!test_lock())
236 return 1;
237
238 if (!test_once())
239 return 1;
240
241 if (!test_thread_local())
242 return 1;
243
244 printf("PASS\n");
245 return 0;
246}