threads_pthread.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  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
  8. */
  9. #include <openssl/crypto.h>
  10. #include "internal/cryptlib.h"
  11. #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
  12. # ifdef PTHREAD_RWLOCK_INITIALIZER
  13. # define USE_RWLOCK
  14. # endif
  15. CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
  16. {
  17. # ifdef USE_RWLOCK
  18. CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t));
  19. if (lock == NULL)
  20. return NULL;
  21. if (pthread_rwlock_init(lock, NULL) != 0) {
  22. OPENSSL_free(lock);
  23. return NULL;
  24. }
  25. # else
  26. pthread_mutexattr_t attr;
  27. CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_mutex_t));
  28. if (lock == NULL)
  29. return NULL;
  30. pthread_mutexattr_init(&attr);
  31. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  32. if (pthread_mutex_init(lock, &attr) != 0) {
  33. pthread_mutexattr_destroy(&attr);
  34. OPENSSL_free(lock);
  35. return NULL;
  36. }
  37. pthread_mutexattr_destroy(&attr);
  38. # endif
  39. return lock;
  40. }
  41. int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
  42. {
  43. # ifdef USE_RWLOCK
  44. if (pthread_rwlock_rdlock(lock) != 0)
  45. return 0;
  46. # else
  47. if (pthread_mutex_lock(lock) != 0)
  48. return 0;
  49. # endif
  50. return 1;
  51. }
  52. int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
  53. {
  54. # ifdef USE_RWLOCK
  55. if (pthread_rwlock_wrlock(lock) != 0)
  56. return 0;
  57. # else
  58. if (pthread_mutex_lock(lock) != 0)
  59. return 0;
  60. # endif
  61. return 1;
  62. }
  63. int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
  64. {
  65. # ifdef USE_RWLOCK
  66. if (pthread_rwlock_unlock(lock) != 0)
  67. return 0;
  68. # else
  69. if (pthread_mutex_unlock(lock) != 0)
  70. return 0;
  71. # endif
  72. return 1;
  73. }
  74. void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
  75. {
  76. if (lock == NULL)
  77. return;
  78. # ifdef USE_RWLOCK
  79. pthread_rwlock_destroy(lock);
  80. # else
  81. pthread_mutex_destroy(lock);
  82. # endif
  83. OPENSSL_free(lock);
  84. return;
  85. }
  86. int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
  87. {
  88. if (pthread_once(once, init) != 0)
  89. return 0;
  90. return 1;
  91. }
  92. int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
  93. {
  94. if (pthread_key_create(key, cleanup) != 0)
  95. return 0;
  96. return 1;
  97. }
  98. void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
  99. {
  100. return pthread_getspecific(*key);
  101. }
  102. int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
  103. {
  104. if (pthread_setspecific(*key, val) != 0)
  105. return 0;
  106. return 1;
  107. }
  108. int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
  109. {
  110. if (pthread_key_delete(*key) != 0)
  111. return 0;
  112. return 1;
  113. }
  114. CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
  115. {
  116. return pthread_self();
  117. }
  118. int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
  119. {
  120. return pthread_equal(a, b);
  121. }
  122. int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
  123. {
  124. # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
  125. if (__atomic_is_lock_free(sizeof(*val), val)) {
  126. *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
  127. return 1;
  128. }
  129. # endif
  130. if (!CRYPTO_THREAD_write_lock(lock))
  131. return 0;
  132. *val += amount;
  133. *ret = *val;
  134. if (!CRYPTO_THREAD_unlock(lock))
  135. return 0;
  136. return 1;
  137. }
  138. int CRYPTO_atomic_read(int *val, int *ret, CRYPTO_RWLOCK *lock)
  139. {
  140. # if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE)
  141. if (__atomic_is_lock_free(sizeof(*val), val)) {
  142. __atomic_load(val, ret, __ATOMIC_ACQUIRE);
  143. return 1;
  144. }
  145. # endif
  146. if (!CRYPTO_THREAD_write_lock(lock))
  147. return 0;
  148. *ret = *val;
  149. if (!CRYPTO_THREAD_unlock(lock))
  150. return 0;
  151. return 1;
  152. }
  153. int CRYPTO_atomic_write(int *val, int n, CRYPTO_RWLOCK *lock)
  154. {
  155. # if defined(__GNUC__) && defined(__ATOMIC_RELEASE)
  156. if (__atomic_is_lock_free(sizeof(*val), val)) {
  157. __atomic_store(val, &n, __ATOMIC_RELEASE);
  158. return 1;
  159. }
  160. # endif
  161. if (!CRYPTO_THREAD_write_lock(lock))
  162. return 0;
  163. *val = n;
  164. if (!CRYPTO_THREAD_unlock(lock))
  165. return 0;
  166. return 1;
  167. }
  168. # ifdef OPENSSL_SYS_UNIX
  169. static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
  170. static void fork_once_func(void)
  171. {
  172. pthread_atfork(OPENSSL_fork_prepare,
  173. OPENSSL_fork_parent, OPENSSL_fork_child);
  174. }
  175. # endif
  176. int openssl_init_fork_handlers(void)
  177. {
  178. # ifdef OPENSSL_SYS_UNIX
  179. if (pthread_once(&fork_once_control, fork_once_func) == 0)
  180. return 1;
  181. # endif
  182. return 0;
  183. }
  184. #endif