您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

253 行
6.7 KiB

  1. /* Copyright (c) 2015, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include "internal.h"
  15. #include <openssl/crypto.h>
  16. #include <stdio.h>
  17. #if !defined(OPENSSL_NO_THREADS)
  18. #if defined(OPENSSL_WINDOWS)
  19. OPENSSL_MSVC_PRAGMA(warning(push, 3))
  20. #include <windows.h>
  21. OPENSSL_MSVC_PRAGMA(warning(pop))
  22. typedef HANDLE thread_t;
  23. static DWORD WINAPI thread_run(LPVOID arg) {
  24. void (*thread_func)(void);
  25. /* VC really doesn't like casting between data and function pointers. */
  26. OPENSSL_memcpy(&thread_func, &arg, sizeof(thread_func));
  27. thread_func();
  28. return 0;
  29. }
  30. static int run_thread(thread_t *out_thread, void (*thread_func)(void)) {
  31. void *arg;
  32. /* VC really doesn't like casting between data and function pointers. */
  33. OPENSSL_memcpy(&arg, &thread_func, sizeof(arg));
  34. *out_thread = CreateThread(NULL /* security attributes */,
  35. 0 /* default stack size */, thread_run, arg,
  36. 0 /* run immediately */, NULL /* ignore id */);
  37. return *out_thread != NULL;
  38. }
  39. static int wait_for_thread(thread_t thread) {
  40. return WaitForSingleObject(thread, INFINITE) == 0;
  41. }
  42. #else
  43. #include <pthread.h>
  44. #include <string.h>
  45. #include <time.h>
  46. typedef pthread_t thread_t;
  47. static void *thread_run(void *arg) {
  48. void (*thread_func)(void) = arg;
  49. thread_func();
  50. return NULL;
  51. }
  52. static int run_thread(thread_t *out_thread, void (*thread_func)(void)) {
  53. return pthread_create(out_thread, NULL /* default attributes */, thread_run,
  54. thread_func) == 0;
  55. }
  56. static int wait_for_thread(thread_t thread) {
  57. return pthread_join(thread, NULL) == 0;
  58. }
  59. #endif /* OPENSSL_WINDOWS */
  60. static unsigned g_once_init_called = 0;
  61. static void once_init(void) {
  62. g_once_init_called++;
  63. /* Sleep briefly so one |call_once_thread| instance will call |CRYPTO_once|
  64. * while the other is running this function. */
  65. #if defined(OPENSSL_WINDOWS)
  66. Sleep(1 /* milliseconds */);
  67. #else
  68. struct timespec req;
  69. OPENSSL_memset(&req, 0, sizeof(req));
  70. req.tv_nsec = 1000000;
  71. nanosleep(&req, NULL);
  72. #endif
  73. }
  74. static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT;
  75. static void call_once_thread(void) {
  76. CRYPTO_once(&g_test_once, once_init);
  77. }
  78. static CRYPTO_once_t once_init_value = CRYPTO_ONCE_INIT;
  79. static CRYPTO_once_t once_bss;
  80. static struct CRYPTO_STATIC_MUTEX mutex_init_value = CRYPTO_STATIC_MUTEX_INIT;
  81. static struct CRYPTO_STATIC_MUTEX mutex_bss;
  82. static CRYPTO_EX_DATA_CLASS ex_data_class_value = CRYPTO_EX_DATA_CLASS_INIT;
  83. static CRYPTO_EX_DATA_CLASS ex_data_class_bss;
  84. static int test_once(void) {
  85. if (g_once_init_called != 0) {
  86. fprintf(stderr, "g_once_init_called was non-zero at start.\n");
  87. return 0;
  88. }
  89. thread_t thread1, thread2;
  90. if (!run_thread(&thread1, call_once_thread) ||
  91. !run_thread(&thread2, call_once_thread) ||
  92. !wait_for_thread(thread1) ||
  93. !wait_for_thread(thread2)) {
  94. fprintf(stderr, "thread failed.\n");
  95. return 0;
  96. }
  97. CRYPTO_once(&g_test_once, once_init);
  98. if (g_once_init_called != 1) {
  99. fprintf(stderr, "Expected init function to be called once, but found %u.\n",
  100. g_once_init_called);
  101. return 0;
  102. }
  103. if (FIPS_mode()) {
  104. /* Our FIPS tooling currently requires that |CRYPTO_ONCE_INIT|,
  105. * |CRYPTO_STATIC_MUTEX_INIT| and |CRYPTO_EX_DATA_CLASS| are all zeros and
  106. * so can be placed in the BSS section. */
  107. if (OPENSSL_memcmp((void *)&once_init_value, (void *)&once_bss,
  108. sizeof(CRYPTO_once_t)) != 0) {
  109. fprintf(stderr, "CRYPTO_ONCE_INIT did not expand to all zeros.\n");
  110. return 0;
  111. }
  112. if (OPENSSL_memcmp((void *)&mutex_init_value, (void *)&mutex_bss,
  113. sizeof(struct CRYPTO_STATIC_MUTEX)) != 0) {
  114. fprintf(stderr, "CRYPTO_STATIC_MUTEX did not expand to all zeros.\n");
  115. return 0;
  116. }
  117. if (OPENSSL_memcmp((void *)&ex_data_class_value, (void *)&ex_data_class_bss,
  118. sizeof(CRYPTO_EX_DATA_CLASS))) {
  119. fprintf(stderr,
  120. "CRYPTO_EX_DATA_CLASS_INIT did not expand to all zeros.\n");
  121. return 0;
  122. }
  123. }
  124. return 1;
  125. }
  126. static int g_test_thread_ok = 0;
  127. static unsigned g_destructor_called_count = 0;
  128. static void thread_local_destructor(void *arg) {
  129. if (arg == NULL) {
  130. return;
  131. }
  132. unsigned *count = arg;
  133. (*count)++;
  134. }
  135. static void thread_local_test_thread(void) {
  136. void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST);
  137. if (ptr != NULL) {
  138. return;
  139. }
  140. if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_TEST,
  141. &g_destructor_called_count,
  142. thread_local_destructor)) {
  143. return;
  144. }
  145. if (CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST) !=
  146. &g_destructor_called_count) {
  147. return;
  148. }
  149. g_test_thread_ok = 1;
  150. }
  151. static void thread_local_test2_thread(void) {}
  152. static int test_thread_local(void) {
  153. void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST);
  154. if (ptr != NULL) {
  155. fprintf(stderr, "Thread-local data was non-NULL at start.\n");
  156. }
  157. thread_t thread;
  158. if (!run_thread(&thread, thread_local_test_thread) ||
  159. !wait_for_thread(thread)) {
  160. fprintf(stderr, "thread failed.\n");
  161. return 0;
  162. }
  163. if (!g_test_thread_ok) {
  164. fprintf(stderr, "Thread-local data didn't work in thread.\n");
  165. return 0;
  166. }
  167. if (g_destructor_called_count != 1) {
  168. fprintf(stderr,
  169. "Destructor should have been called once, but actually called %u "
  170. "times.\n",
  171. g_destructor_called_count);
  172. return 0;
  173. }
  174. /* thread_local_test2_thread doesn't do anything, but it tests that the
  175. * thread destructor function works even if thread-local storage wasn't used
  176. * for a thread. */
  177. if (!run_thread(&thread, thread_local_test2_thread) ||
  178. !wait_for_thread(thread)) {
  179. fprintf(stderr, "thread failed.\n");
  180. return 0;
  181. }
  182. return 1;
  183. }
  184. int main(int argc, char **argv) {
  185. if (!test_once() ||
  186. !test_thread_local()) {
  187. return 1;
  188. }
  189. printf("PASS\n");
  190. return 0;
  191. }
  192. #else /* OPENSSL_NO_THREADS */
  193. int main(int argc, char **argv) {
  194. printf("PASS\n");
  195. return 0;
  196. }
  197. #endif