VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.7/crypto/threads_iprt.c@ 105963

Last change on this file since 105963 was 105339, checked in by vboxsync, 5 months ago

OpenSSL: Calling convention fix. bugref:10725

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.9 KB
Line 
1/* $Id: threads_iprt.c 105339 2024-07-16 08:25:18Z vboxsync $ */
2/** @file
3 * Crypto threading and atomic functions built upon IPRT.
4 */
5
6/*
7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <openssl/crypto.h>
29#include "internal/cryptlib.h"
30
31#if defined(OPENSSL_THREADS)
32
33# include <iprt/asm.h>
34# include <iprt/assert.h>
35# include <iprt/critsect.h>
36# include <iprt/errcore.h>
37# include <iprt/log.h>
38# include <iprt/process.h>
39
40/* Use read/write sections. */
41/*# define USE_RW_CRITSECT */ /** @todo test the code */
42
43# ifndef USE_RW_CRITSECT
44/*
45 * Of course it's wrong to use a critical section to implement a read/write
46 * lock. But as the OpenSSL interface is too simple (there is only read_lock()/
47 * write_lock() and only unspecified unlock() and the Windows implementatio
48 * (threads_win.c) uses {Enter,Leave}CriticalSection we do that here as well.
49 */
50# endif
51
52CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
53{
54# ifdef USE_RW_CRITSECT
55 PRTCRITSECTRW const pCritSect = (PRTCRITSECTRW)OPENSSL_zalloc(sizeof(*pCritSect));
56# else
57 PRTCRITSECT const pCritSect = (PRTCRITSECT)OPENSSL_zalloc(sizeof(*pCritSect));
58# endif
59 if (pCritSect)
60 {
61# ifdef USE_RW_CRITSECT
62 int const rc = RTCritSectRwInitEx(pCritSect, 0, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
63# else
64 int const rc = RTCritSectInitEx(pCritSect, 0, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
65# endif
66 if (RT_SUCCESS(rc))
67 return (CRYPTO_RWLOCK *)pCritSect;
68 OPENSSL_free(pCritSect);
69 }
70 return NULL;
71}
72
73int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
74{
75# ifdef USE_RW_CRITSECT
76 PRTCRITSECTRW const pCritSect = (PRTCRITSECTRW)lock;
77 int rc;
78
79 /* writers cannot acquire read locks the way CRYPTO_THREAD_unlock works
80 right now. It's also looks incompatible with pthread_rwlock_rdlock,
81 so this should never trigger. */
82 Assert(!RTCritSectRwIsWriteOwner(pCritSect));
83
84 rc = RTCritSectRwEnterShared(pCritSect);
85# else
86 int const rc = RTCritSectEnter((PRTCRITSECT)lock);
87# endif
88 AssertRCReturn(rc, 0);
89 return 1;
90}
91
92int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
93{
94# ifdef USE_RW_CRITSECT
95 int const rc = RTCritSectRwEnterExcl((PRTCRITSECTRW)lock);
96# else
97 int const rc = RTCritSectEnter((PRTCRITSECT)lock);
98# endif
99 AssertRCReturn(rc, 0);
100 return 1;
101}
102
103int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
104{
105# ifdef USE_RW_CRITSECT
106 PRTCRITSECTRW const pCritSect = (PRTCRITSECTRW)lock;
107 if (RTCritSectRwIsWriteOwner(pCritSect))
108 {
109 int const rc1 = RTCritSectRwLeaveExcl(pCritSect);
110 AssertRCReturn(rc1, 0);
111 }
112 else
113 {
114 int const rc2 = RTCritSectRwLeaveShared(pCritSect);
115 AssertRCReturn(rc2, 0);
116 }
117# else
118 int const rc = RTCritSectLeave((PRTCRITSECT)lock);
119 AssertRCReturn(rc, 0);
120# endif
121 return 1;
122}
123
124void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
125{
126 if (lock)
127 {
128# ifdef USE_RW_CRITSECT
129 PRTCRITSECTRW const pCritSect = (PRTCRITSECTRW)lock;
130 int const rc = RTCritSectRwDelete(pCritSect);
131# else
132 PRTCRITSECT const pCritSect = (PRTCRITSECT)lock;
133 int const rc = RTCritSectDelete(pCritSect);
134# endif
135 AssertRC(rc);
136 OPENSSL_free(pCritSect);
137 }
138}
139
140int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
141{
142 int rc = RTTlsAllocEx(key, (PFNRTTLSDTOR)cleanup); /* ASSUMES default calling convention is __cdecl, or close enough to it. */
143 AssertRCReturn(rc, 0);
144 return 1;
145}
146
147void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
148{
149 return RTTlsGet(*key);
150}
151
152int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
153{
154 int rc = RTTlsSet(*key, val);
155 AssertRCReturn(rc, 0);
156 return 1;
157}
158
159int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
160{
161 int rc = RTTlsFree(*key);
162 AssertRCReturn(rc, 0);
163 return 1;
164}
165
166CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
167{
168 return RTThreadSelf();
169}
170
171int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
172{
173 return (a == b);
174}
175
176/** @callback_method_impl{FNRTONCE,
177 * Wrapper that calls the @a init function given CRYPTO_THREAD_run_once().}
178 */
179static DECLCALLBACK(int32_t) cryptoThreadRunOnceWrapper(void *pvUser)
180{
181 void (*pfnInit)(void) = (void (*)(void))pvUser;
182 pfnInit();
183 return VINF_SUCCESS;
184}
185
186int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
187{
188 int rc = RTOnce(once, cryptoThreadRunOnceWrapper, (void *)(uintptr_t)init);
189 AssertRCReturn(rc, 0);
190 return 1;
191}
192
193int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
194{
195 *ret = ASMAtomicAddS32((int32_t volatile*)val, amount) + amount;
196 return 1;
197}
198
199int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
200 CRYPTO_RWLOCK *lock)
201{
202 uint64_t u64RetOld = ASMAtomicUoReadU64(val);
203 uint64_t u64New;
204 do
205 u64New = u64RetOld | op;
206 while (!ASMAtomicCmpXchgExU64(val, u64New, u64RetOld, &u64RetOld));
207 *ret = u64RetOld;
208
209 return 1;
210}
211
212int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
213{
214 *ret = ASMAtomicReadU64((uint64_t volatile *)val);
215 return 1;
216}
217
218#endif /* defined(OPENSSL_THREADS) */
219
220int openssl_init_fork_handlers(void)
221{
222 return 0;
223}
224
225int openssl_get_fork_id(void)
226{
227 return (int)RTProcSelf();
228}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette