/src/openssl/crypto/thread/internal.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2019-2023 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 <openssl/configuration.h> |
11 | | #include <openssl/e_os2.h> |
12 | | #include <openssl/types.h> |
13 | | #include <openssl/crypto.h> |
14 | | #include <internal/thread.h> |
15 | | #include <internal/thread_arch.h> |
16 | | |
17 | | #if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL) |
18 | | |
19 | | static ossl_inline uint64_t _ossl_get_avail_threads(OSSL_LIB_CTX_THREADS *tdata) |
20 | 0 | { |
21 | | /* assumes that tdata->lock is taken */ |
22 | 0 | return tdata->max_threads - tdata->active_threads; |
23 | 0 | } |
24 | | |
25 | | uint64_t ossl_get_avail_threads(OSSL_LIB_CTX *ctx) |
26 | 0 | { |
27 | 0 | uint64_t retval = 0; |
28 | 0 | OSSL_LIB_CTX_THREADS *tdata = OSSL_LIB_CTX_GET_THREADS(ctx); |
29 | |
|
30 | 0 | if (tdata == NULL) |
31 | 0 | return retval; |
32 | | |
33 | 0 | ossl_crypto_mutex_lock(tdata->lock); |
34 | 0 | retval = _ossl_get_avail_threads(tdata); |
35 | 0 | ossl_crypto_mutex_unlock(tdata->lock); |
36 | |
|
37 | 0 | return retval; |
38 | 0 | } |
39 | | |
40 | | void *ossl_crypto_thread_start(OSSL_LIB_CTX *ctx, CRYPTO_THREAD_ROUTINE start, |
41 | | void *data) |
42 | 0 | { |
43 | 0 | CRYPTO_THREAD *thread; |
44 | 0 | OSSL_LIB_CTX_THREADS *tdata = OSSL_LIB_CTX_GET_THREADS(ctx); |
45 | |
|
46 | 0 | if (tdata == NULL) |
47 | 0 | return NULL; |
48 | | |
49 | 0 | ossl_crypto_mutex_lock(tdata->lock); |
50 | 0 | if (tdata == NULL || tdata->max_threads == 0) { |
51 | 0 | ossl_crypto_mutex_unlock(tdata->lock); |
52 | 0 | return NULL; |
53 | 0 | } |
54 | | |
55 | 0 | while (_ossl_get_avail_threads(tdata) == 0) |
56 | 0 | ossl_crypto_condvar_wait(tdata->cond_finished, tdata->lock); |
57 | 0 | tdata->active_threads++; |
58 | 0 | ossl_crypto_mutex_unlock(tdata->lock); |
59 | |
|
60 | 0 | thread = ossl_crypto_thread_native_start(start, data, 1); |
61 | 0 | if (thread == NULL) { |
62 | 0 | ossl_crypto_mutex_lock(tdata->lock); |
63 | 0 | tdata->active_threads--; |
64 | 0 | ossl_crypto_mutex_unlock(tdata->lock); |
65 | 0 | goto fail; |
66 | 0 | } |
67 | 0 | thread->ctx = ctx; |
68 | |
|
69 | 0 | fail: |
70 | 0 | return (void *) thread; |
71 | 0 | } |
72 | | |
73 | | int ossl_crypto_thread_join(void *vhandle, CRYPTO_THREAD_RETVAL *retval) |
74 | 0 | { |
75 | 0 | CRYPTO_THREAD *handle = vhandle; |
76 | 0 | OSSL_LIB_CTX_THREADS *tdata; |
77 | |
|
78 | 0 | if (vhandle == NULL) |
79 | 0 | return 0; |
80 | | |
81 | 0 | tdata = OSSL_LIB_CTX_GET_THREADS(handle->ctx); |
82 | 0 | if (tdata == NULL) |
83 | 0 | return 0; |
84 | | |
85 | 0 | if (ossl_crypto_thread_native_join(handle, retval) == 0) |
86 | 0 | return 0; |
87 | | |
88 | 0 | ossl_crypto_mutex_lock(tdata->lock); |
89 | 0 | tdata->active_threads--; |
90 | 0 | ossl_crypto_condvar_signal(tdata->cond_finished); |
91 | 0 | ossl_crypto_mutex_unlock(tdata->lock); |
92 | 0 | return 1; |
93 | 0 | } |
94 | | |
95 | | int ossl_crypto_thread_clean(void *vhandle) |
96 | 0 | { |
97 | 0 | CRYPTO_THREAD *handle = vhandle; |
98 | |
|
99 | 0 | return ossl_crypto_thread_native_clean(handle); |
100 | 0 | } |
101 | | |
102 | | #else |
103 | | |
104 | | ossl_inline uint64_t ossl_get_avail_threads(OSSL_LIB_CTX *ctx) |
105 | | { |
106 | | return 0; |
107 | | } |
108 | | |
109 | | void *ossl_crypto_thread_start(OSSL_LIB_CTX *ctx, CRYPTO_THREAD_ROUTINE start, |
110 | | void *data) |
111 | | { |
112 | | return NULL; |
113 | | } |
114 | | |
115 | | int ossl_crypto_thread_join(void *vhandle, CRYPTO_THREAD_RETVAL *retval) |
116 | | { |
117 | | return 0; |
118 | | } |
119 | | |
120 | | int ossl_crypto_thread_clean(void *vhandle) |
121 | | { |
122 | | return 0; |
123 | | } |
124 | | |
125 | | #endif |
126 | | |
127 | | void *ossl_threads_ctx_new(OSSL_LIB_CTX *ctx) |
128 | 2 | { |
129 | 2 | struct openssl_threads_st *t = OPENSSL_zalloc(sizeof(*t)); |
130 | | |
131 | 2 | if (t == NULL) |
132 | 0 | return NULL; |
133 | | |
134 | 2 | t->lock = ossl_crypto_mutex_new(); |
135 | 2 | t->cond_finished = ossl_crypto_condvar_new(); |
136 | | |
137 | 2 | if (t->lock == NULL || t->cond_finished == NULL) |
138 | 0 | goto fail; |
139 | | |
140 | 2 | return t; |
141 | | |
142 | 0 | fail: |
143 | 0 | ossl_threads_ctx_free((void *)t); |
144 | 0 | return NULL; |
145 | 2 | } |
146 | | |
147 | | void ossl_threads_ctx_free(void *vdata) |
148 | 2 | { |
149 | 2 | OSSL_LIB_CTX_THREADS *t = (OSSL_LIB_CTX_THREADS *) vdata; |
150 | | |
151 | 2 | if (t == NULL) |
152 | 0 | return; |
153 | | |
154 | 2 | ossl_crypto_mutex_free(&t->lock); |
155 | 2 | ossl_crypto_condvar_free(&t->cond_finished); |
156 | 2 | OPENSSL_free(t); |
157 | 2 | } |