threads_pthread.c 4.6 KB

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