threads_pthread.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. /*
  2. * Copyright 2016-2024 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. /* We need to use the OPENSSL_fork_*() deprecated APIs */
  10. #define OPENSSL_SUPPRESS_DEPRECATED
  11. #include <openssl/crypto.h>
  12. #include <crypto/cryptlib.h>
  13. #include "internal/cryptlib.h"
  14. #include "internal/rcu.h"
  15. #include "rcu_internal.h"
  16. #if defined(__clang__) && defined(__has_feature)
  17. # if __has_feature(thread_sanitizer)
  18. # define __SANITIZE_THREAD__
  19. # endif
  20. #endif
  21. #if defined(__SANITIZE_THREAD__)
  22. # include <sanitizer/tsan_interface.h>
  23. # define TSAN_FAKE_UNLOCK(x) __tsan_mutex_pre_unlock((x), 0); \
  24. __tsan_mutex_post_unlock((x), 0)
  25. # define TSAN_FAKE_LOCK(x) __tsan_mutex_pre_lock((x), 0); \
  26. __tsan_mutex_post_lock((x), 0, 0)
  27. #else
  28. # define TSAN_FAKE_UNLOCK(x)
  29. # define TSAN_FAKE_LOCK(x)
  30. #endif
  31. #if defined(__sun)
  32. # include <atomic.h>
  33. #endif
  34. #if defined(__apple_build_version__) && __apple_build_version__ < 6000000
  35. /*
  36. * OS/X 10.7 and 10.8 had a weird version of clang which has __ATOMIC_ACQUIRE and
  37. * __ATOMIC_ACQ_REL but which expects only one parameter for __atomic_is_lock_free()
  38. * rather than two which has signature __atomic_is_lock_free(sizeof(_Atomic(T))).
  39. * All of this makes impossible to use __atomic_is_lock_free here.
  40. *
  41. * See: https://github.com/llvm/llvm-project/commit/a4c2602b714e6c6edb98164550a5ae829b2de760
  42. */
  43. # define BROKEN_CLANG_ATOMICS
  44. #endif
  45. #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
  46. # if defined(OPENSSL_SYS_UNIX)
  47. # include <sys/types.h>
  48. # include <unistd.h>
  49. # endif
  50. # include <assert.h>
  51. # ifdef PTHREAD_RWLOCK_INITIALIZER
  52. # define USE_RWLOCK
  53. # endif
  54. /*
  55. * For all GNU/clang atomic builtins, we also need fallbacks, to cover all
  56. * other compilers.
  57. * Unfortunately, we can't do that with some "generic type", because there's no
  58. * guarantee that the chosen generic type is large enough to cover all cases.
  59. * Therefore, we implement fallbacks for each applicable type, with composed
  60. * names that include the type they handle.
  61. *
  62. * (an anecdote: we previously tried to use |void *| as the generic type, with
  63. * the thought that the pointer itself is the largest type. However, this is
  64. * not true on 32-bit pointer platforms, as a |uint64_t| is twice as large)
  65. *
  66. * All applicable ATOMIC_ macros take the intended type as first parameter, so
  67. * they can map to the correct fallback function. In the GNU/clang case, that
  68. * parameter is simply ignored.
  69. */
  70. /*
  71. * Internal types used with the ATOMIC_ macros, to make it possible to compose
  72. * fallback function names.
  73. */
  74. typedef void *pvoid;
  75. typedef struct rcu_cb_item *prcu_cb_item;
  76. # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS) \
  77. && !defined(USE_ATOMIC_FALLBACKS)
  78. # if defined(__APPLE__) && defined(__clang__) && defined(__aarch64__)
  79. /*
  80. * For pointers, Apple M1 virtualized cpu seems to have some problem using the
  81. * ldapr instruction (see https://github.com/openssl/openssl/pull/23974)
  82. * When using the native apple clang compiler, this instruction is emitted for
  83. * atomic loads, which is bad. So, if
  84. * 1) We are building on a target that defines __APPLE__ AND
  85. * 2) We are building on a target using clang (__clang__) AND
  86. * 3) We are building for an M1 processor (__aarch64__)
  87. * Then we should not use __atomic_load_n and instead implement our own
  88. * function to issue the ldar instruction instead, which produces the proper
  89. * sequencing guarantees
  90. */
  91. static inline void *apple_atomic_load_n_pvoid(void **p,
  92. ossl_unused int memorder)
  93. {
  94. void *ret;
  95. __asm volatile("ldar %0, [%1]" : "=r" (ret): "r" (p):);
  96. return ret;
  97. }
  98. /* For uint64_t, we should be fine, though */
  99. # define apple_atomic_load_n_uint64_t(p, o) __atomic_load_n(p, o)
  100. # define ATOMIC_LOAD_N(t, p, o) apple_atomic_load_n_##t(p, o)
  101. # else
  102. # define ATOMIC_LOAD_N(t, p, o) __atomic_load_n(p, o)
  103. # endif
  104. # define ATOMIC_STORE_N(t, p, v, o) __atomic_store_n(p, v, o)
  105. # define ATOMIC_STORE(t, p, v, o) __atomic_store(p, v, o)
  106. # define ATOMIC_EXCHANGE_N(t, p, v, o) __atomic_exchange_n(p, v, o)
  107. # define ATOMIC_ADD_FETCH(p, v, o) __atomic_add_fetch(p, v, o)
  108. # define ATOMIC_FETCH_ADD(p, v, o) __atomic_fetch_add(p, v, o)
  109. # define ATOMIC_SUB_FETCH(p, v, o) __atomic_sub_fetch(p, v, o)
  110. # define ATOMIC_AND_FETCH(p, m, o) __atomic_and_fetch(p, m, o)
  111. # define ATOMIC_OR_FETCH(p, m, o) __atomic_or_fetch(p, m, o)
  112. # else
  113. static pthread_mutex_t atomic_sim_lock = PTHREAD_MUTEX_INITIALIZER;
  114. # define IMPL_fallback_atomic_load_n(t) \
  115. static inline t fallback_atomic_load_n_##t(t *p) \
  116. { \
  117. t ret; \
  118. \
  119. pthread_mutex_lock(&atomic_sim_lock); \
  120. ret = *p; \
  121. pthread_mutex_unlock(&atomic_sim_lock); \
  122. return ret; \
  123. }
  124. IMPL_fallback_atomic_load_n(uint64_t)
  125. IMPL_fallback_atomic_load_n(pvoid)
  126. # define ATOMIC_LOAD_N(t, p, o) fallback_atomic_load_n_##t(p)
  127. # define IMPL_fallback_atomic_store_n(t) \
  128. static inline t fallback_atomic_store_n_##t(t *p, t v) \
  129. { \
  130. t ret; \
  131. \
  132. pthread_mutex_lock(&atomic_sim_lock); \
  133. ret = *p; \
  134. *p = v; \
  135. pthread_mutex_unlock(&atomic_sim_lock); \
  136. return ret; \
  137. }
  138. IMPL_fallback_atomic_store_n(uint64_t)
  139. # define ATOMIC_STORE_N(t, p, v, o) fallback_atomic_store_n_##t(p, v)
  140. # define IMPL_fallback_atomic_store(t) \
  141. static inline void fallback_atomic_store_##t(t *p, t *v) \
  142. { \
  143. pthread_mutex_lock(&atomic_sim_lock); \
  144. *p = *v; \
  145. pthread_mutex_unlock(&atomic_sim_lock); \
  146. }
  147. IMPL_fallback_atomic_store(uint64_t)
  148. IMPL_fallback_atomic_store(pvoid)
  149. # define ATOMIC_STORE(t, p, v, o) fallback_atomic_store_##t(p, v)
  150. # define IMPL_fallback_atomic_exchange_n(t) \
  151. static inline t fallback_atomic_exchange_n_##t(t *p, t v) \
  152. { \
  153. t ret; \
  154. \
  155. pthread_mutex_lock(&atomic_sim_lock); \
  156. ret = *p; \
  157. *p = v; \
  158. pthread_mutex_unlock(&atomic_sim_lock); \
  159. return ret; \
  160. }
  161. IMPL_fallback_atomic_exchange_n(uint64_t)
  162. IMPL_fallback_atomic_exchange_n(prcu_cb_item)
  163. # define ATOMIC_EXCHANGE_N(t, p, v, o) fallback_atomic_exchange_n_##t(p, v)
  164. /*
  165. * The fallbacks that follow don't need any per type implementation, as
  166. * they are designed for uint64_t only. If there comes a time when multiple
  167. * types need to be covered, it's relatively easy to refactor them the same
  168. * way as the fallbacks above.
  169. */
  170. static inline uint64_t fallback_atomic_add_fetch(uint64_t *p, uint64_t v)
  171. {
  172. uint64_t ret;
  173. pthread_mutex_lock(&atomic_sim_lock);
  174. *p += v;
  175. ret = *p;
  176. pthread_mutex_unlock(&atomic_sim_lock);
  177. return ret;
  178. }
  179. # define ATOMIC_ADD_FETCH(p, v, o) fallback_atomic_add_fetch(p, v)
  180. static inline uint64_t fallback_atomic_fetch_add(uint64_t *p, uint64_t v)
  181. {
  182. uint64_t ret;
  183. pthread_mutex_lock(&atomic_sim_lock);
  184. ret = *p;
  185. *p += v;
  186. pthread_mutex_unlock(&atomic_sim_lock);
  187. return ret;
  188. }
  189. # define ATOMIC_FETCH_ADD(p, v, o) fallback_atomic_fetch_add(p, v)
  190. static inline uint64_t fallback_atomic_sub_fetch(uint64_t *p, uint64_t v)
  191. {
  192. uint64_t ret;
  193. pthread_mutex_lock(&atomic_sim_lock);
  194. *p -= v;
  195. ret = *p;
  196. pthread_mutex_unlock(&atomic_sim_lock);
  197. return ret;
  198. }
  199. # define ATOMIC_SUB_FETCH(p, v, o) fallback_atomic_sub_fetch(p, v)
  200. static inline uint64_t fallback_atomic_and_fetch(uint64_t *p, uint64_t m)
  201. {
  202. uint64_t ret;
  203. pthread_mutex_lock(&atomic_sim_lock);
  204. *p &= m;
  205. ret = *p;
  206. pthread_mutex_unlock(&atomic_sim_lock);
  207. return ret;
  208. }
  209. # define ATOMIC_AND_FETCH(p, v, o) fallback_atomic_and_fetch(p, v)
  210. static inline uint64_t fallback_atomic_or_fetch(uint64_t *p, uint64_t m)
  211. {
  212. uint64_t ret;
  213. pthread_mutex_lock(&atomic_sim_lock);
  214. *p |= m;
  215. ret = *p;
  216. pthread_mutex_unlock(&atomic_sim_lock);
  217. return ret;
  218. }
  219. # define ATOMIC_OR_FETCH(p, v, o) fallback_atomic_or_fetch(p, v)
  220. # endif
  221. /*
  222. * users is broken up into 2 parts
  223. * bits 0-15 current readers
  224. * bit 32-63 - ID
  225. */
  226. # define READER_SHIFT 0
  227. # define ID_SHIFT 32
  228. # define READER_SIZE 16
  229. # define ID_SIZE 32
  230. # define READER_MASK (((uint64_t)1 << READER_SIZE) - 1)
  231. # define ID_MASK (((uint64_t)1 << ID_SIZE) - 1)
  232. # define READER_COUNT(x) (((uint64_t)(x) >> READER_SHIFT) & READER_MASK)
  233. # define ID_VAL(x) (((uint64_t)(x) >> ID_SHIFT) & ID_MASK)
  234. # define VAL_READER ((uint64_t)1 << READER_SHIFT)
  235. # define VAL_ID(x) ((uint64_t)x << ID_SHIFT)
  236. /*
  237. * This is the core of an rcu lock. It tracks the readers and writers for the
  238. * current quiescence point for a given lock. Users is the 64 bit value that
  239. * stores the READERS/ID as defined above
  240. *
  241. */
  242. struct rcu_qp {
  243. uint64_t users;
  244. };
  245. struct thread_qp {
  246. struct rcu_qp *qp;
  247. unsigned int depth;
  248. CRYPTO_RCU_LOCK *lock;
  249. };
  250. # define MAX_QPS 10
  251. /*
  252. * This is the per thread tracking data
  253. * that is assigned to each thread participating
  254. * in an rcu qp
  255. *
  256. * qp points to the qp that it last acquired
  257. *
  258. */
  259. struct rcu_thr_data {
  260. struct thread_qp thread_qps[MAX_QPS];
  261. };
  262. /*
  263. * This is the internal version of a CRYPTO_RCU_LOCK
  264. * it is cast from CRYPTO_RCU_LOCK
  265. */
  266. struct rcu_lock_st {
  267. /* Callbacks to call for next ossl_synchronize_rcu */
  268. struct rcu_cb_item *cb_items;
  269. /* The context we are being created against */
  270. OSSL_LIB_CTX *ctx;
  271. /* rcu generation counter for in-order retirement */
  272. uint32_t id_ctr;
  273. /* Array of quiescent points for synchronization */
  274. struct rcu_qp *qp_group;
  275. /* Number of elements in qp_group array */
  276. size_t group_count;
  277. /* Index of the current qp in the qp_group array */
  278. uint64_t reader_idx;
  279. /* value of the next id_ctr value to be retired */
  280. uint32_t next_to_retire;
  281. /* index of the next free rcu_qp in the qp_group */
  282. uint64_t current_alloc_idx;
  283. /* number of qp's in qp_group array currently being retired */
  284. uint32_t writers_alloced;
  285. /* lock protecting write side operations */
  286. pthread_mutex_t write_lock;
  287. /* lock protecting updates to writers_alloced/current_alloc_idx */
  288. pthread_mutex_t alloc_lock;
  289. /* signal to wake threads waiting on alloc_lock */
  290. pthread_cond_t alloc_signal;
  291. /* lock to enforce in-order retirement */
  292. pthread_mutex_t prior_lock;
  293. /* signal to wake threads waiting on prior_lock */
  294. pthread_cond_t prior_signal;
  295. };
  296. /* Read side acquisition of the current qp */
  297. static struct rcu_qp *get_hold_current_qp(struct rcu_lock_st *lock)
  298. {
  299. uint64_t qp_idx;
  300. /* get the current qp index */
  301. for (;;) {
  302. /*
  303. * Notes on use of __ATOMIC_ACQUIRE
  304. * We need to ensure the following:
  305. * 1) That subsequent operations aren't optimized by hoisting them above
  306. * this operation. Specifically, we don't want the below re-load of
  307. * qp_idx to get optimized away
  308. * 2) We want to ensure that any updating of reader_idx on the write side
  309. * of the lock is flushed from a local cpu cache so that we see any
  310. * updates prior to the load. This is a non-issue on cache coherent
  311. * systems like x86, but is relevant on other arches
  312. * Note: This applies to the reload below as well
  313. */
  314. qp_idx = ATOMIC_LOAD_N(uint64_t, &lock->reader_idx, __ATOMIC_ACQUIRE);
  315. /*
  316. * Notes of use of __ATOMIC_RELEASE
  317. * This counter is only read by the write side of the lock, and so we
  318. * specify __ATOMIC_RELEASE here to ensure that the write side of the
  319. * lock see this during the spin loop read of users, as it waits for the
  320. * reader count to approach zero
  321. */
  322. ATOMIC_ADD_FETCH(&lock->qp_group[qp_idx].users, VAL_READER,
  323. __ATOMIC_RELEASE);
  324. /* if the idx hasn't changed, we're good, else try again */
  325. if (qp_idx == ATOMIC_LOAD_N(uint64_t, &lock->reader_idx, __ATOMIC_ACQUIRE))
  326. break;
  327. /*
  328. * Notes on use of __ATOMIC_RELEASE
  329. * As with the add above, we want to ensure that this decrement is
  330. * seen by the write side of the lock as soon as it happens to prevent
  331. * undue spinning waiting for write side completion
  332. */
  333. ATOMIC_SUB_FETCH(&lock->qp_group[qp_idx].users, VAL_READER,
  334. __ATOMIC_RELEASE);
  335. }
  336. return &lock->qp_group[qp_idx];
  337. }
  338. static void ossl_rcu_free_local_data(void *arg)
  339. {
  340. OSSL_LIB_CTX *ctx = arg;
  341. CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(ctx);
  342. struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey);
  343. OPENSSL_free(data);
  344. }
  345. void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock)
  346. {
  347. struct rcu_thr_data *data;
  348. int i, available_qp = -1;
  349. CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx);
  350. /*
  351. * we're going to access current_qp here so ask the
  352. * processor to fetch it
  353. */
  354. data = CRYPTO_THREAD_get_local(lkey);
  355. if (data == NULL) {
  356. data = OPENSSL_zalloc(sizeof(*data));
  357. OPENSSL_assert(data != NULL);
  358. CRYPTO_THREAD_set_local(lkey, data);
  359. ossl_init_thread_start(NULL, lock->ctx, ossl_rcu_free_local_data);
  360. }
  361. for (i = 0; i < MAX_QPS; i++) {
  362. if (data->thread_qps[i].qp == NULL && available_qp == -1)
  363. available_qp = i;
  364. /* If we have a hold on this lock already, we're good */
  365. if (data->thread_qps[i].lock == lock) {
  366. data->thread_qps[i].depth++;
  367. return;
  368. }
  369. }
  370. /*
  371. * if we get here, then we don't have a hold on this lock yet
  372. */
  373. assert(available_qp != -1);
  374. data->thread_qps[available_qp].qp = get_hold_current_qp(lock);
  375. data->thread_qps[available_qp].depth = 1;
  376. data->thread_qps[available_qp].lock = lock;
  377. }
  378. void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock)
  379. {
  380. int i;
  381. CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx);
  382. struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey);
  383. uint64_t ret;
  384. assert(data != NULL);
  385. for (i = 0; i < MAX_QPS; i++) {
  386. if (data->thread_qps[i].lock == lock) {
  387. /*
  388. * As with read side acquisition, we use __ATOMIC_RELEASE here
  389. * to ensure that the decrement is published immediately
  390. * to any write side waiters
  391. */
  392. data->thread_qps[i].depth--;
  393. if (data->thread_qps[i].depth == 0) {
  394. ret = ATOMIC_SUB_FETCH(&data->thread_qps[i].qp->users, VAL_READER,
  395. __ATOMIC_RELEASE);
  396. OPENSSL_assert(ret != UINT64_MAX);
  397. data->thread_qps[i].qp = NULL;
  398. data->thread_qps[i].lock = NULL;
  399. }
  400. return;
  401. }
  402. }
  403. /*
  404. * If we get here, we're trying to unlock a lock that we never acquired -
  405. * that's fatal.
  406. */
  407. assert(0);
  408. }
  409. /*
  410. * Write side allocation routine to get the current qp
  411. * and replace it with a new one
  412. */
  413. static struct rcu_qp *update_qp(CRYPTO_RCU_LOCK *lock)
  414. {
  415. uint64_t new_id;
  416. uint64_t current_idx;
  417. pthread_mutex_lock(&lock->alloc_lock);
  418. /*
  419. * we need at least one qp to be available with one
  420. * left over, so that readers can start working on
  421. * one that isn't yet being waited on
  422. */
  423. while (lock->group_count - lock->writers_alloced < 2)
  424. /* we have to wait for one to be free */
  425. pthread_cond_wait(&lock->alloc_signal, &lock->alloc_lock);
  426. current_idx = lock->current_alloc_idx;
  427. /* Allocate the qp */
  428. lock->writers_alloced++;
  429. /* increment the allocation index */
  430. lock->current_alloc_idx =
  431. (lock->current_alloc_idx + 1) % lock->group_count;
  432. /* get and insert a new id */
  433. new_id = lock->id_ctr;
  434. lock->id_ctr++;
  435. new_id = VAL_ID(new_id);
  436. /*
  437. * Even though we are under a write side lock here
  438. * We need to use atomic instructions to ensure that the results
  439. * of this update are published to the read side prior to updating the
  440. * reader idx below
  441. */
  442. ATOMIC_AND_FETCH(&lock->qp_group[current_idx].users, ID_MASK,
  443. __ATOMIC_RELEASE);
  444. ATOMIC_OR_FETCH(&lock->qp_group[current_idx].users, new_id,
  445. __ATOMIC_RELEASE);
  446. /*
  447. * Update the reader index to be the prior qp.
  448. * Note the use of __ATOMIC_RELEASE here is based on the corresponding use
  449. * of __ATOMIC_ACQUIRE in get_hold_current_qp, as we want any publication
  450. * of this value to be seen on the read side immediately after it happens
  451. */
  452. ATOMIC_STORE_N(uint64_t, &lock->reader_idx, lock->current_alloc_idx,
  453. __ATOMIC_RELEASE);
  454. /* wake up any waiters */
  455. pthread_cond_signal(&lock->alloc_signal);
  456. pthread_mutex_unlock(&lock->alloc_lock);
  457. return &lock->qp_group[current_idx];
  458. }
  459. static void retire_qp(CRYPTO_RCU_LOCK *lock, struct rcu_qp *qp)
  460. {
  461. pthread_mutex_lock(&lock->alloc_lock);
  462. lock->writers_alloced--;
  463. pthread_cond_signal(&lock->alloc_signal);
  464. pthread_mutex_unlock(&lock->alloc_lock);
  465. }
  466. static struct rcu_qp *allocate_new_qp_group(CRYPTO_RCU_LOCK *lock,
  467. int count)
  468. {
  469. struct rcu_qp *new =
  470. OPENSSL_zalloc(sizeof(*new) * count);
  471. lock->group_count = count;
  472. return new;
  473. }
  474. void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock)
  475. {
  476. pthread_mutex_lock(&lock->write_lock);
  477. TSAN_FAKE_UNLOCK(&lock->write_lock);
  478. }
  479. void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock)
  480. {
  481. TSAN_FAKE_LOCK(&lock->write_lock);
  482. pthread_mutex_unlock(&lock->write_lock);
  483. }
  484. void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock)
  485. {
  486. struct rcu_qp *qp;
  487. uint64_t count;
  488. struct rcu_cb_item *cb_items, *tmpcb;
  489. pthread_mutex_lock(&lock->write_lock);
  490. cb_items = lock->cb_items;
  491. lock->cb_items = NULL;
  492. pthread_mutex_unlock(&lock->write_lock);
  493. qp = update_qp(lock);
  494. /*
  495. * wait for the reader count to reach zero
  496. * Note the use of __ATOMIC_ACQUIRE here to ensure that any
  497. * prior __ATOMIC_RELEASE write operation in get_hold_current_qp
  498. * is visible prior to our read
  499. */
  500. do {
  501. count = ATOMIC_LOAD_N(uint64_t, &qp->users, __ATOMIC_ACQUIRE);
  502. } while (READER_COUNT(count) != 0);
  503. /* retire in order */
  504. pthread_mutex_lock(&lock->prior_lock);
  505. while (lock->next_to_retire != ID_VAL(count))
  506. pthread_cond_wait(&lock->prior_signal, &lock->prior_lock);
  507. lock->next_to_retire++;
  508. pthread_cond_broadcast(&lock->prior_signal);
  509. pthread_mutex_unlock(&lock->prior_lock);
  510. retire_qp(lock, qp);
  511. /* handle any callbacks that we have */
  512. while (cb_items != NULL) {
  513. tmpcb = cb_items;
  514. cb_items = cb_items->next;
  515. tmpcb->fn(tmpcb->data);
  516. OPENSSL_free(tmpcb);
  517. }
  518. }
  519. int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data)
  520. {
  521. struct rcu_cb_item *new =
  522. OPENSSL_zalloc(sizeof(*new));
  523. if (new == NULL)
  524. return 0;
  525. new->data = data;
  526. new->fn = cb;
  527. /*
  528. * Use __ATOMIC_ACQ_REL here to indicate that any prior writes to this
  529. * list are visible to us prior to reading, and publish the new value
  530. * immediately
  531. */
  532. new->next = ATOMIC_EXCHANGE_N(prcu_cb_item, &lock->cb_items, new,
  533. __ATOMIC_ACQ_REL);
  534. return 1;
  535. }
  536. void *ossl_rcu_uptr_deref(void **p)
  537. {
  538. return ATOMIC_LOAD_N(pvoid, p, __ATOMIC_ACQUIRE);
  539. }
  540. void ossl_rcu_assign_uptr(void **p, void **v)
  541. {
  542. ATOMIC_STORE(pvoid, p, v, __ATOMIC_RELEASE);
  543. }
  544. CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx)
  545. {
  546. struct rcu_lock_st *new;
  547. if (num_writers < 1)
  548. num_writers = 1;
  549. ctx = ossl_lib_ctx_get_concrete(ctx);
  550. if (ctx == NULL)
  551. return 0;
  552. new = OPENSSL_zalloc(sizeof(*new));
  553. if (new == NULL)
  554. return NULL;
  555. new->ctx = ctx;
  556. pthread_mutex_init(&new->write_lock, NULL);
  557. pthread_mutex_init(&new->prior_lock, NULL);
  558. pthread_mutex_init(&new->alloc_lock, NULL);
  559. pthread_cond_init(&new->prior_signal, NULL);
  560. pthread_cond_init(&new->alloc_signal, NULL);
  561. new->qp_group = allocate_new_qp_group(new, num_writers + 1);
  562. if (new->qp_group == NULL) {
  563. OPENSSL_free(new);
  564. new = NULL;
  565. }
  566. return new;
  567. }
  568. void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock)
  569. {
  570. struct rcu_lock_st *rlock = (struct rcu_lock_st *)lock;
  571. if (lock == NULL)
  572. return;
  573. /* make sure we're synchronized */
  574. ossl_synchronize_rcu(rlock);
  575. OPENSSL_free(rlock->qp_group);
  576. /* There should only be a single qp left now */
  577. OPENSSL_free(rlock);
  578. }
  579. CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
  580. {
  581. # ifdef USE_RWLOCK
  582. CRYPTO_RWLOCK *lock;
  583. if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL)
  584. /* Don't set error, to avoid recursion blowup. */
  585. return NULL;
  586. if (pthread_rwlock_init(lock, NULL) != 0) {
  587. OPENSSL_free(lock);
  588. return NULL;
  589. }
  590. # else
  591. pthread_mutexattr_t attr;
  592. CRYPTO_RWLOCK *lock;
  593. if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL)
  594. /* Don't set error, to avoid recursion blowup. */
  595. return NULL;
  596. /*
  597. * We don't use recursive mutexes, but try to catch errors if we do.
  598. */
  599. pthread_mutexattr_init(&attr);
  600. # if !defined (__TANDEM) && !defined (_SPT_MODEL_)
  601. # if !defined(NDEBUG) && !defined(OPENSSL_NO_MUTEX_ERRORCHECK)
  602. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
  603. # endif
  604. # else
  605. /* The SPT Thread Library does not define MUTEX attributes. */
  606. # endif
  607. if (pthread_mutex_init(lock, &attr) != 0) {
  608. pthread_mutexattr_destroy(&attr);
  609. OPENSSL_free(lock);
  610. return NULL;
  611. }
  612. pthread_mutexattr_destroy(&attr);
  613. # endif
  614. return lock;
  615. }
  616. __owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
  617. {
  618. # ifdef USE_RWLOCK
  619. if (pthread_rwlock_rdlock(lock) != 0)
  620. return 0;
  621. # else
  622. if (pthread_mutex_lock(lock) != 0) {
  623. assert(errno != EDEADLK && errno != EBUSY);
  624. return 0;
  625. }
  626. # endif
  627. return 1;
  628. }
  629. __owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
  630. {
  631. # ifdef USE_RWLOCK
  632. if (pthread_rwlock_wrlock(lock) != 0)
  633. return 0;
  634. # else
  635. if (pthread_mutex_lock(lock) != 0) {
  636. assert(errno != EDEADLK && errno != EBUSY);
  637. return 0;
  638. }
  639. # endif
  640. return 1;
  641. }
  642. int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
  643. {
  644. # ifdef USE_RWLOCK
  645. if (pthread_rwlock_unlock(lock) != 0)
  646. return 0;
  647. # else
  648. if (pthread_mutex_unlock(lock) != 0) {
  649. assert(errno != EPERM);
  650. return 0;
  651. }
  652. # endif
  653. return 1;
  654. }
  655. void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
  656. {
  657. if (lock == NULL)
  658. return;
  659. # ifdef USE_RWLOCK
  660. pthread_rwlock_destroy(lock);
  661. # else
  662. pthread_mutex_destroy(lock);
  663. # endif
  664. OPENSSL_free(lock);
  665. return;
  666. }
  667. int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
  668. {
  669. if (pthread_once(once, init) != 0)
  670. return 0;
  671. return 1;
  672. }
  673. int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
  674. {
  675. if (pthread_key_create(key, cleanup) != 0)
  676. return 0;
  677. return 1;
  678. }
  679. void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
  680. {
  681. return pthread_getspecific(*key);
  682. }
  683. int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
  684. {
  685. if (pthread_setspecific(*key, val) != 0)
  686. return 0;
  687. return 1;
  688. }
  689. int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
  690. {
  691. if (pthread_key_delete(*key) != 0)
  692. return 0;
  693. return 1;
  694. }
  695. CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
  696. {
  697. return pthread_self();
  698. }
  699. int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
  700. {
  701. return pthread_equal(a, b);
  702. }
  703. int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
  704. {
  705. # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS)
  706. if (__atomic_is_lock_free(sizeof(*val), val)) {
  707. *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
  708. return 1;
  709. }
  710. # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
  711. /* This will work for all future Solaris versions. */
  712. if (ret != NULL) {
  713. *ret = atomic_add_int_nv((volatile unsigned int *)val, amount);
  714. return 1;
  715. }
  716. # endif
  717. if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
  718. return 0;
  719. *val += amount;
  720. *ret = *val;
  721. if (!CRYPTO_THREAD_unlock(lock))
  722. return 0;
  723. return 1;
  724. }
  725. int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
  726. CRYPTO_RWLOCK *lock)
  727. {
  728. # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS)
  729. if (__atomic_is_lock_free(sizeof(*val), val)) {
  730. *ret = __atomic_or_fetch(val, op, __ATOMIC_ACQ_REL);
  731. return 1;
  732. }
  733. # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
  734. /* This will work for all future Solaris versions. */
  735. if (ret != NULL) {
  736. *ret = atomic_or_64_nv(val, op);
  737. return 1;
  738. }
  739. # endif
  740. if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
  741. return 0;
  742. *val |= op;
  743. *ret = *val;
  744. if (!CRYPTO_THREAD_unlock(lock))
  745. return 0;
  746. return 1;
  747. }
  748. int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
  749. {
  750. # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
  751. if (__atomic_is_lock_free(sizeof(*val), val)) {
  752. __atomic_load(val, ret, __ATOMIC_ACQUIRE);
  753. return 1;
  754. }
  755. # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
  756. /* This will work for all future Solaris versions. */
  757. if (ret != NULL) {
  758. *ret = atomic_or_64_nv(val, 0);
  759. return 1;
  760. }
  761. # endif
  762. if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
  763. return 0;
  764. *ret = *val;
  765. if (!CRYPTO_THREAD_unlock(lock))
  766. return 0;
  767. return 1;
  768. }
  769. int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock)
  770. {
  771. # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
  772. if (__atomic_is_lock_free(sizeof(*dst), dst)) {
  773. __atomic_store(dst, &val, __ATOMIC_RELEASE);
  774. return 1;
  775. }
  776. # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
  777. /* This will work for all future Solaris versions. */
  778. if (ret != NULL) {
  779. atomic_swap_64(dst, val);
  780. return 1;
  781. }
  782. # endif
  783. if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
  784. return 0;
  785. *dst = val;
  786. if (!CRYPTO_THREAD_unlock(lock))
  787. return 0;
  788. return 1;
  789. }
  790. int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock)
  791. {
  792. # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
  793. if (__atomic_is_lock_free(sizeof(*val), val)) {
  794. __atomic_load(val, ret, __ATOMIC_ACQUIRE);
  795. return 1;
  796. }
  797. # elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
  798. /* This will work for all future Solaris versions. */
  799. if (ret != NULL) {
  800. *ret = (int *)atomic_or_uint_nv((unsigned int *)val, 0);
  801. return 1;
  802. }
  803. # endif
  804. if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
  805. return 0;
  806. *ret = *val;
  807. if (!CRYPTO_THREAD_unlock(lock))
  808. return 0;
  809. return 1;
  810. }
  811. # ifndef FIPS_MODULE
  812. int openssl_init_fork_handlers(void)
  813. {
  814. return 1;
  815. }
  816. # endif /* FIPS_MODULE */
  817. int openssl_get_fork_id(void)
  818. {
  819. return getpid();
  820. }
  821. #endif