doc: update FIPS provider version information
[openssl.git] / test / threadpool_test.c
1 /*
2  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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
8  */
9
10 #include <string.h>
11 #include <internal/cryptlib.h>
12 #include <internal/thread_arch.h>
13 #include <internal/thread.h>
14 #include <openssl/thread.h>
15 #include "testutil.h"
16
17 static int test_thread_reported_flags(void)
18 {
19     uint32_t flags = OSSL_get_thread_support_flags();
20
21 #if !defined(OPENSSL_THREADS)
22     if (!TEST_int_eq(flags, 0))
23         return 0;
24 #endif
25
26 #if defined(OPENSSL_NO_THREAD_POOL)
27     if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL, 0))
28         return 0;
29 #else
30     if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL,
31                      OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL))
32         return 0;
33 #endif
34
35 #if defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
36     if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN, 0))
37         return 0;
38 #else
39     if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN,
40                      OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN))
41         return 0;
42 #endif
43
44     return 1;
45 }
46
47 #ifndef OPENSSL_NO_THREAD_POOL
48
49 # define TEST_THREAD_NATIVE_FN_SET_VALUE 1
50 static uint32_t test_thread_native_fn(void *data)
51 {
52     uint32_t *ldata = (uint32_t*) data;
53     *ldata = *ldata + 1;
54     return *ldata - 1;
55 }
56 /* Tests of native threads */
57
58 static int test_thread_native(void)
59 {
60     uint32_t retval;
61     uint32_t local;
62     CRYPTO_THREAD *t;
63
64     /* thread spawn, join */
65
66     local = 1;
67     t = ossl_crypto_thread_native_start(test_thread_native_fn, &local, 1);
68     if (!TEST_ptr(t))
69         return 0;
70
71     /*
72      * pthread_join results in undefined behaviour if called on a joined
73      * thread. We do not impose such restrictions, so it's up to us to
74      * ensure that this does not happen (thread sanitizer will warn us
75      * if we do).
76      */
77     if (!TEST_int_eq(ossl_crypto_thread_native_join(t, &retval), 1))
78         return 0;
79     if (!TEST_int_eq(ossl_crypto_thread_native_join(t, &retval), 1))
80         return 0;
81
82     if (!TEST_int_eq(retval, 1) || !TEST_int_eq(local, 2))
83         return 0;
84
85     if (!TEST_int_eq(ossl_crypto_thread_native_clean(t), 1))
86         return 0;
87     t = NULL;
88
89     if (!TEST_int_eq(ossl_crypto_thread_native_clean(t), 0))
90         return 0;
91
92     return 1;
93 }
94
95 # if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
96 static int test_thread_internal(void)
97 {
98     uint32_t retval[3];
99     uint32_t local[3] = { 0 };
100     uint32_t threads_supported;
101     size_t i;
102     void *t[3];
103     OSSL_LIB_CTX *cust_ctx = OSSL_LIB_CTX_new();
104
105     threads_supported = OSSL_get_thread_support_flags();
106     threads_supported &= OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN;
107
108     if (threads_supported == 0) {
109         if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
110             return 0;
111         if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
112             return 0;
113
114         if (!TEST_int_eq(OSSL_set_max_threads(NULL, 1), 0))
115             return 0;
116         if (!TEST_int_eq(OSSL_set_max_threads(cust_ctx, 1), 0))
117             return 0;
118
119         if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
120             return 0;
121         if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
122             return 0;
123
124         t[0] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
125         if (!TEST_ptr_null(t[0]))
126             return 0;
127
128         return 1;
129     }
130
131     /* fail when not allowed to use threads */
132
133     if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
134         return 0;
135     t[0] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
136     if (!TEST_ptr_null(t[0]))
137         return 0;
138
139     /* fail when enabled on a different context */
140     if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
141         return 0;
142     if (!TEST_int_eq(OSSL_set_max_threads(cust_ctx, 1), 1))
143         return 0;
144     if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
145         return 0;
146     if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 1))
147         return 0;
148     t[0] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
149     if (!TEST_ptr_null(t[0]))
150         return 0;
151     if (!TEST_int_eq(OSSL_set_max_threads(cust_ctx, 0), 1))
152         return 0;
153
154     /* sequential startup */
155
156     if (!TEST_int_eq(OSSL_set_max_threads(NULL, 1), 1))
157         return 0;
158     if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 1))
159         return 0;
160     if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
161         return 0;
162
163     for (i = 0; i < OSSL_NELEM(t); ++i) {
164         local[0] = i + 1;
165
166         t[i] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
167         if (!TEST_ptr(t[i]))
168             return 0;
169
170         /*
171          * pthread_join results in undefined behaviour if called on a joined
172          * thread. We do not impose such restrictions, so it's up to us to
173          * ensure that this does not happen (thread sanitizer will warn us
174          * if we do).
175          */
176         if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[0]), 1))
177             return 0;
178         if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[0]), 1))
179             return 0;
180
181         if (!TEST_int_eq(retval[0], i + 1) || !TEST_int_eq(local[0], i + 2))
182             return 0;
183
184         if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 1))
185             return 0;
186         t[i] = NULL;
187
188         if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 0))
189             return 0;
190     }
191
192     /* parallel startup */
193
194     if (!TEST_int_eq(OSSL_set_max_threads(NULL, OSSL_NELEM(t)), 1))
195         return 0;
196
197     for (i = 0; i < OSSL_NELEM(t); ++i) {
198         local[i] = i + 1;
199         t[i] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[i]);
200         if (!TEST_ptr(t[i]))
201             return 0;
202     }
203     for (i = 0; i < OSSL_NELEM(t); ++i) {
204         if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[i]), 1))
205             return 0;
206     }
207     for (i = 0; i < OSSL_NELEM(t); ++i) {
208         if (!TEST_int_eq(retval[i], i + 1) || !TEST_int_eq(local[i], i + 2))
209             return 0;
210         if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 1))
211             return 0;
212     }
213
214     /* parallel startup, bottleneck */
215
216     if (!TEST_int_eq(OSSL_set_max_threads(NULL, OSSL_NELEM(t) - 1), 1))
217         return 0;
218
219     for (i = 0; i < OSSL_NELEM(t); ++i) {
220         local[i] = i + 1;
221         t[i] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[i]);
222         if (!TEST_ptr(t[i]))
223             return 0;
224     }
225     for (i = 0; i < OSSL_NELEM(t); ++i) {
226         if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[i]), 1))
227             return 0;
228     }
229     for (i = 0; i < OSSL_NELEM(t); ++i) {
230         if (!TEST_int_eq(retval[i], i + 1) || !TEST_int_eq(local[i], i + 2))
231             return 0;
232         if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 1))
233             return 0;
234     }
235
236     if (!TEST_int_eq(OSSL_set_max_threads(NULL, 0), 1))
237         return 0;
238
239     OSSL_LIB_CTX_free(cust_ctx);
240     return 1;
241 }
242 # endif
243
244 static uint32_t test_thread_native_multiple_joins_fn1(void *data)
245 {
246     return 0;
247 }
248
249 static uint32_t test_thread_native_multiple_joins_fn2(void *data)
250 {
251     ossl_crypto_thread_native_join((CRYPTO_THREAD *)data, NULL);
252     return 0;
253 }
254
255 static uint32_t test_thread_native_multiple_joins_fn3(void *data)
256 {
257     ossl_crypto_thread_native_join((CRYPTO_THREAD *)data, NULL);
258     return 0;
259 }
260
261 static int test_thread_native_multiple_joins(void)
262 {
263     CRYPTO_THREAD *t, *t1, *t2;
264
265     t = ossl_crypto_thread_native_start(test_thread_native_multiple_joins_fn1, NULL, 1);
266     t1 = ossl_crypto_thread_native_start(test_thread_native_multiple_joins_fn2, t, 1);
267     t2 = ossl_crypto_thread_native_start(test_thread_native_multiple_joins_fn3, t, 1);
268
269     if (!TEST_ptr(t) || !TEST_ptr(t1) || !TEST_ptr(t2))
270         return 0;
271
272     if (!TEST_int_eq(ossl_crypto_thread_native_join(t2, NULL), 1))
273         return 0;
274     if (!TEST_int_eq(ossl_crypto_thread_native_join(t1, NULL), 1))
275         return 0;
276
277     if (!TEST_int_eq(ossl_crypto_thread_native_clean(t2), 1))
278         return 0;
279
280     if (!TEST_int_eq(ossl_crypto_thread_native_clean(t1), 1))
281         return 0;
282
283     if (!TEST_int_eq(ossl_crypto_thread_native_clean(t), 1))
284         return 0;
285
286     return 1;
287 }
288
289 #endif
290
291 int setup_tests(void)
292 {
293     ADD_TEST(test_thread_reported_flags);
294 #if !defined(OPENSSL_NO_THREAD_POOL)
295     ADD_TEST(test_thread_native);
296     ADD_TEST(test_thread_native_multiple_joins);
297 # if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
298     ADD_TEST(test_thread_internal);
299 # endif
300 #endif
301
302     return 1;
303 }