threadpool_test.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright 2022 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 <string.h>
  10. #include <internal/cryptlib.h>
  11. #include <internal/thread_arch.h>
  12. #include <internal/thread.h>
  13. #include <openssl/thread.h>
  14. #include "testutil.h"
  15. static int test_thread_reported_flags(void)
  16. {
  17. uint32_t flags = OSSL_get_thread_support_flags();
  18. #if !defined(OPENSSL_THREADS)
  19. if (!TEST_int_eq(flags, 0))
  20. return 0;
  21. #endif
  22. #if defined(OPENSSL_NO_THREAD_POOL)
  23. if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL, 0))
  24. return 0;
  25. #else
  26. if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL,
  27. OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL))
  28. return 0;
  29. #endif
  30. #if defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
  31. if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN, 0))
  32. return 0;
  33. #else
  34. if (!TEST_int_eq(flags & OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN,
  35. OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN))
  36. return 0;
  37. #endif
  38. return 1;
  39. }
  40. #ifndef OPENSSL_NO_THREAD_POOL
  41. # define TEST_THREAD_NATIVE_FN_SET_VALUE 1
  42. static uint32_t test_thread_native_fn(void *data)
  43. {
  44. uint32_t *ldata = (uint32_t*) data;
  45. *ldata = *ldata + 1;
  46. return *ldata - 1;
  47. }
  48. /* Tests of native threads */
  49. static int test_thread_native(void)
  50. {
  51. uint32_t retval;
  52. uint32_t local;
  53. CRYPTO_THREAD *t;
  54. /* thread spawn, join */
  55. local = 1;
  56. t = ossl_crypto_thread_native_start(test_thread_native_fn, &local, 1);
  57. if (!TEST_ptr(t))
  58. return 0;
  59. /*
  60. * pthread_join results in undefined behaviour if called on a joined
  61. * thread. We do not impose such restrictions, so it's up to us to
  62. * ensure that this does not happen (thread sanitizer will warn us
  63. * if we do).
  64. */
  65. if (!TEST_int_eq(ossl_crypto_thread_native_join(t, &retval), 1))
  66. return 0;
  67. if (!TEST_int_eq(ossl_crypto_thread_native_join(t, &retval), 1))
  68. return 0;
  69. if (!TEST_int_eq(retval, 1) || !TEST_int_eq(local, 2))
  70. return 0;
  71. if (!TEST_int_eq(ossl_crypto_thread_native_clean(t), 1))
  72. return 0;
  73. t = NULL;
  74. if (!TEST_int_eq(ossl_crypto_thread_native_clean(t), 0))
  75. return 0;
  76. return 1;
  77. }
  78. # if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
  79. static int test_thread_internal(void)
  80. {
  81. uint32_t retval[3];
  82. uint32_t local[3] = { 0 };
  83. uint32_t threads_supported;
  84. size_t i;
  85. void *t[3];
  86. OSSL_LIB_CTX *cust_ctx = OSSL_LIB_CTX_new();
  87. threads_supported = OSSL_get_thread_support_flags();
  88. threads_supported &= OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN;
  89. if (threads_supported == 0) {
  90. if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
  91. return 0;
  92. if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
  93. return 0;
  94. if (!TEST_int_eq(OSSL_set_max_threads(NULL, 1), 0))
  95. return 0;
  96. if (!TEST_int_eq(OSSL_set_max_threads(cust_ctx, 1), 0))
  97. return 0;
  98. if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
  99. return 0;
  100. if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
  101. return 0;
  102. t[0] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
  103. if (!TEST_ptr_null(t[0]))
  104. return 0;
  105. return 1;
  106. }
  107. /* fail when not allowed to use threads */
  108. if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
  109. return 0;
  110. t[0] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
  111. if (!TEST_ptr_null(t[0]))
  112. return 0;
  113. /* fail when enabled on a different context */
  114. if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
  115. return 0;
  116. if (!TEST_int_eq(OSSL_set_max_threads(cust_ctx, 1), 1))
  117. return 0;
  118. if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 0))
  119. return 0;
  120. if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 1))
  121. return 0;
  122. t[0] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
  123. if (!TEST_ptr_null(t[0]))
  124. return 0;
  125. if (!TEST_int_eq(OSSL_set_max_threads(cust_ctx, 0), 1))
  126. return 0;
  127. /* sequential startup */
  128. if (!TEST_int_eq(OSSL_set_max_threads(NULL, 1), 1))
  129. return 0;
  130. if (!TEST_uint64_t_eq(OSSL_get_max_threads(NULL), 1))
  131. return 0;
  132. if (!TEST_uint64_t_eq(OSSL_get_max_threads(cust_ctx), 0))
  133. return 0;
  134. for (i = 0; i < OSSL_NELEM(t); ++i) {
  135. local[0] = i + 1;
  136. t[i] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[0]);
  137. if (!TEST_ptr(t[i]))
  138. return 0;
  139. /*
  140. * pthread_join results in undefined behaviour if called on a joined
  141. * thread. We do not impose such restrictions, so it's up to us to
  142. * ensure that this does not happen (thread sanitizer will warn us
  143. * if we do).
  144. */
  145. if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[0]), 1))
  146. return 0;
  147. if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[0]), 1))
  148. return 0;
  149. if (!TEST_int_eq(retval[0], i + 1) || !TEST_int_eq(local[0], i + 2))
  150. return 0;
  151. if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 1))
  152. return 0;
  153. t[i] = NULL;
  154. if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 0))
  155. return 0;
  156. }
  157. /* parallel startup */
  158. if (!TEST_int_eq(OSSL_set_max_threads(NULL, OSSL_NELEM(t)), 1))
  159. return 0;
  160. for (i = 0; i < OSSL_NELEM(t); ++i) {
  161. local[i] = i + 1;
  162. t[i] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[i]);
  163. if (!TEST_ptr(t[i]))
  164. return 0;
  165. }
  166. for (i = 0; i < OSSL_NELEM(t); ++i) {
  167. if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[i]), 1))
  168. return 0;
  169. }
  170. for (i = 0; i < OSSL_NELEM(t); ++i) {
  171. if (!TEST_int_eq(retval[i], i + 1) || !TEST_int_eq(local[i], i + 2))
  172. return 0;
  173. if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 1))
  174. return 0;
  175. }
  176. /* parallel startup, bottleneck */
  177. if (!TEST_int_eq(OSSL_set_max_threads(NULL, OSSL_NELEM(t) - 1), 1))
  178. return 0;
  179. for (i = 0; i < OSSL_NELEM(t); ++i) {
  180. local[i] = i + 1;
  181. t[i] = ossl_crypto_thread_start(NULL, test_thread_native_fn, &local[i]);
  182. if (!TEST_ptr(t[i]))
  183. return 0;
  184. }
  185. for (i = 0; i < OSSL_NELEM(t); ++i) {
  186. if (!TEST_int_eq(ossl_crypto_thread_join(t[i], &retval[i]), 1))
  187. return 0;
  188. }
  189. for (i = 0; i < OSSL_NELEM(t); ++i) {
  190. if (!TEST_int_eq(retval[i], i + 1) || !TEST_int_eq(local[i], i + 2))
  191. return 0;
  192. if (!TEST_int_eq(ossl_crypto_thread_clean(t[i]), 1))
  193. return 0;
  194. }
  195. if (!TEST_int_eq(OSSL_set_max_threads(NULL, 0), 1))
  196. return 0;
  197. OSSL_LIB_CTX_free(cust_ctx);
  198. return 1;
  199. }
  200. # endif
  201. static uint32_t test_thread_native_multiple_joins_fn1(void *data)
  202. {
  203. return 0;
  204. }
  205. static uint32_t test_thread_native_multiple_joins_fn2(void *data)
  206. {
  207. ossl_crypto_thread_native_join((CRYPTO_THREAD *)data, NULL);
  208. return 0;
  209. }
  210. static uint32_t test_thread_native_multiple_joins_fn3(void *data)
  211. {
  212. ossl_crypto_thread_native_join((CRYPTO_THREAD *)data, NULL);
  213. return 0;
  214. }
  215. static int test_thread_native_multiple_joins(void)
  216. {
  217. CRYPTO_THREAD *t, *t1, *t2;
  218. t = ossl_crypto_thread_native_start(test_thread_native_multiple_joins_fn1, NULL, 1);
  219. t1 = ossl_crypto_thread_native_start(test_thread_native_multiple_joins_fn2, t, 1);
  220. t2 = ossl_crypto_thread_native_start(test_thread_native_multiple_joins_fn3, t, 1);
  221. if (!TEST_ptr(t) || !TEST_ptr(t1) || !TEST_ptr(t2))
  222. return 0;
  223. if (!TEST_int_eq(ossl_crypto_thread_native_join(t2, NULL), 1))
  224. return 0;
  225. if (!TEST_int_eq(ossl_crypto_thread_native_join(t1, NULL), 1))
  226. return 0;
  227. if (!TEST_int_eq(ossl_crypto_thread_native_clean(t2), 1))
  228. return 0;
  229. if (!TEST_int_eq(ossl_crypto_thread_native_clean(t1), 1))
  230. return 0;
  231. if (!TEST_int_eq(ossl_crypto_thread_native_clean(t), 1))
  232. return 0;
  233. return 1;
  234. }
  235. #endif
  236. int setup_tests(void)
  237. {
  238. ADD_TEST(test_thread_reported_flags);
  239. #if !defined(OPENSSL_NO_THREAD_POOL)
  240. ADD_TEST(test_thread_native);
  241. ADD_TEST(test_thread_native_multiple_joins);
  242. # if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
  243. ADD_TEST(test_thread_internal);
  244. # endif
  245. #endif
  246. return 1;
  247. }