2
0

thread_win.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * Copyright 2019-2023 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 <internal/thread_arch.h>
  10. #if defined(OPENSSL_THREADS_WINNT)
  11. # include <process.h>
  12. # include <windows.h>
  13. static unsigned __stdcall thread_start_thunk(LPVOID vthread)
  14. {
  15. CRYPTO_THREAD *thread;
  16. CRYPTO_THREAD_RETVAL ret;
  17. thread = (CRYPTO_THREAD *)vthread;
  18. thread->thread_id = GetCurrentThreadId();
  19. ret = thread->routine(thread->data);
  20. ossl_crypto_mutex_lock(thread->statelock);
  21. CRYPTO_THREAD_SET_STATE(thread, CRYPTO_THREAD_FINISHED);
  22. thread->retval = ret;
  23. ossl_crypto_condvar_signal(thread->condvar);
  24. ossl_crypto_mutex_unlock(thread->statelock);
  25. return 0;
  26. }
  27. int ossl_crypto_thread_native_spawn(CRYPTO_THREAD *thread)
  28. {
  29. HANDLE *handle;
  30. handle = OPENSSL_zalloc(sizeof(*handle));
  31. if (handle == NULL)
  32. goto fail;
  33. *handle = (HANDLE)_beginthreadex(NULL, 0, &thread_start_thunk, thread, 0, NULL);
  34. if (*handle == NULL)
  35. goto fail;
  36. thread->handle = handle;
  37. return 1;
  38. fail:
  39. thread->handle = NULL;
  40. OPENSSL_free(handle);
  41. return 0;
  42. }
  43. int ossl_crypto_thread_native_perform_join(CRYPTO_THREAD *thread, CRYPTO_THREAD_RETVAL *retval)
  44. {
  45. DWORD thread_retval;
  46. HANDLE *handle;
  47. if (thread == NULL || thread->handle == NULL)
  48. return 0;
  49. handle = (HANDLE *) thread->handle;
  50. if (WaitForSingleObject(*handle, INFINITE) != WAIT_OBJECT_0)
  51. return 0;
  52. if (GetExitCodeThread(*handle, &thread_retval) == 0)
  53. return 0;
  54. /*
  55. * GetExitCodeThread call followed by this check is to make sure that
  56. * the thread exited properly. In particular, thread_retval may be
  57. * non-zero when exited via explicit ExitThread/TerminateThread or
  58. * if the thread is still active (returns STILL_ACTIVE (259)).
  59. */
  60. if (thread_retval != 0)
  61. return 0;
  62. if (CloseHandle(*handle) == 0)
  63. return 0;
  64. return 1;
  65. }
  66. int ossl_crypto_thread_native_exit(void)
  67. {
  68. _endthreadex(0);
  69. return 1;
  70. }
  71. int ossl_crypto_thread_native_is_self(CRYPTO_THREAD *thread)
  72. {
  73. return thread->thread_id == GetCurrentThreadId();
  74. }
  75. CRYPTO_MUTEX *ossl_crypto_mutex_new(void)
  76. {
  77. CRITICAL_SECTION *mutex;
  78. if ((mutex = OPENSSL_zalloc(sizeof(*mutex))) == NULL)
  79. return NULL;
  80. InitializeCriticalSection(mutex);
  81. return (CRYPTO_MUTEX *)mutex;
  82. }
  83. void ossl_crypto_mutex_lock(CRYPTO_MUTEX *mutex)
  84. {
  85. CRITICAL_SECTION *mutex_p;
  86. mutex_p = (CRITICAL_SECTION *)mutex;
  87. EnterCriticalSection(mutex_p);
  88. }
  89. int ossl_crypto_mutex_try_lock(CRYPTO_MUTEX *mutex)
  90. {
  91. CRITICAL_SECTION *mutex_p;
  92. mutex_p = (CRITICAL_SECTION *)mutex;
  93. if (TryEnterCriticalSection(mutex_p))
  94. return 1;
  95. return 0;
  96. }
  97. void ossl_crypto_mutex_unlock(CRYPTO_MUTEX *mutex)
  98. {
  99. CRITICAL_SECTION *mutex_p;
  100. mutex_p = (CRITICAL_SECTION *)mutex;
  101. LeaveCriticalSection(mutex_p);
  102. }
  103. void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex)
  104. {
  105. CRITICAL_SECTION **mutex_p;
  106. mutex_p = (CRITICAL_SECTION **)mutex;
  107. if (*mutex_p != NULL)
  108. DeleteCriticalSection(*mutex_p);
  109. OPENSSL_free(*mutex_p);
  110. *mutex = NULL;
  111. }
  112. static int determine_timeout(OSSL_TIME deadline, DWORD *w_timeout_p)
  113. {
  114. OSSL_TIME now, delta;
  115. uint64_t ms;
  116. if (ossl_time_is_infinite(deadline)) {
  117. *w_timeout_p = INFINITE;
  118. return 1;
  119. }
  120. now = ossl_time_now();
  121. delta = ossl_time_subtract(deadline, now);
  122. if (ossl_time_is_zero(delta))
  123. return 0;
  124. ms = ossl_time2ms(delta);
  125. /*
  126. * Amount of time we want to wait is too long for the 32-bit argument to
  127. * the Win32 API, so just wait as long as possible.
  128. */
  129. if (ms > (uint64_t)(INFINITE - 1))
  130. *w_timeout_p = INFINITE - 1;
  131. else
  132. *w_timeout_p = (DWORD)ms;
  133. return 1;
  134. }
  135. # if defined(OPENSSL_THREADS_WINNT_LEGACY)
  136. # include <assert.h>
  137. /*
  138. * Win32, before Vista, did not have an OS-provided condition variable
  139. * construct. This leads to the need to construct our own condition variable
  140. * construct in order to support Windows XP.
  141. *
  142. * It is difficult to construct a condition variable construct using the
  143. * OS-provided primitives in a way that is both correct (avoiding race
  144. * conditions where broadcasts get lost) and fair.
  145. *
  146. * CORRECTNESS:
  147. * A blocked thread is a thread which is calling wait(), between the
  148. * precise instants at which the external mutex passed to wait() is
  149. * unlocked and the instant at which it is relocked.
  150. *
  151. * a)
  152. * - If broadcast() is called, ALL blocked threads MUST be unblocked.
  153. * - If signal() is called, at least one blocked thread MUST be unblocked.
  154. *
  155. * (i.e.: a signal or broadcast must never get 'lost')
  156. *
  157. * b)
  158. * - If broadcast() or signal() is called, this must not cause a thread
  159. * which is not blocked to return immediately from a subsequent
  160. * call to wait().
  161. *
  162. * FAIRNESS:
  163. * If broadcast() is called at time T1, all blocked threads must be unblocked
  164. * before any thread which subsequently calls wait() at time T2 > T1 is
  165. * unblocked.
  166. *
  167. * An example of an implementation which lacks fairness is as follows:
  168. *
  169. * t1 enters wait()
  170. * t2 enters wait()
  171. *
  172. * tZ calls broadcast()
  173. *
  174. * t1 exits wait()
  175. * t1 enters wait()
  176. *
  177. * tZ calls broadcast()
  178. *
  179. * t1 exits wait()
  180. *
  181. * IMPLEMENTATION:
  182. *
  183. * The most suitable primitives available to us in Windows XP are semaphores,
  184. * auto-reset events and manual-reset events. A solution based on semaphores
  185. * is chosen.
  186. *
  187. * PROBLEM. Designing a solution based on semaphores is non-trivial because,
  188. * while it is easy to track the number of waiters in an interlocked data
  189. * structure and then add that number to the semaphore, this does not
  190. * guarantee fairness or correctness. Consider the following situation:
  191. *
  192. * - t1 enters wait(), adding 1 to the wait counter & blocks on the semaphore
  193. * - t2 enters wait(), adding 1 to the wait counter & blocks on the semaphore
  194. * - tZ calls broadcast(), finds the wait counter is 2, adds 2 to the semaphore
  195. *
  196. * - t1 exits wait()
  197. * - t1 immediately reenters wait() and blocks on the semaphore
  198. * - The semaphore is still positive due to also having been signalled
  199. * for t2, therefore it is decremented
  200. * - t1 exits wait() immediately; t2 is never woken
  201. *
  202. * GENERATION COUNTERS. One naive solution to this is to use a generation
  203. * counter. Each broadcast() invocation increments a generation counter. If
  204. * the generation counter has not changed during a semaphore wait operation
  205. * inside wait(), this indicates that no broadcast() call has been made in
  206. * the meantime; therefore, the successful semaphore decrement must have
  207. * 'stolen' a wakeup from another thread which was waiting to wakeup from the
  208. * prior broadcast() call but which had not yet had a chance to do so. The
  209. * semaphore can then be reincremented and the wait() operation repeated.
  210. *
  211. * However, this suffers from the obvious problem that without OS guarantees
  212. * as to how semaphore readiness events are distributed amongst threads,
  213. * there is no particular guarantee that the semaphore readiness event will
  214. * not be immediately redistributed back to the same thread t1.
  215. *
  216. * SOLUTION. A solution is chosen as follows. In its initial state, a
  217. * condition variable can accept waiters, who wait for the semaphore
  218. * normally. However, once broadcast() is called, the condition
  219. * variable becomes 'closed'. Any existing blocked threads are unblocked,
  220. * but any new calls to wait() will instead enter a blocking pre-wait stage.
  221. * Pre-wait threads are not considered to be waiting (and the external
  222. * mutex remains held). A call to wait() in pre-wait cannot progress
  223. * to waiting until all threads due to be unblocked by the prior broadcast()
  224. * call have returned and had a chance to execute.
  225. *
  226. * This pre-wait does not affect a thread if it does not call wait()
  227. * again until after all threads have had a chance to execute.
  228. *
  229. * RESOURCE USAGE. Aside from an allocation for the condition variable
  230. * structure, this solution uses two Win32 semaphores.
  231. *
  232. * FUTURE OPTIMISATIONS:
  233. *
  234. * An optimised multi-generation implementation is possible at the cost of
  235. * higher Win32 resource usage. Multiple 'buckets' could be defined, with
  236. * usage rotating between buckets internally as buckets become closed.
  237. * This would avoid the need for the prewait in more cases, depending
  238. * on intensity of usage.
  239. *
  240. */
  241. typedef struct legacy_condvar_st {
  242. CRYPTO_MUTEX *int_m; /* internal mutex */
  243. HANDLE sema; /* main wait semaphore */
  244. HANDLE prewait_sema; /* prewait semaphore */
  245. /*
  246. * All of the following fields are protected by int_m.
  247. *
  248. * num_wake only ever increases by virtue of a corresponding decrease in
  249. * num_wait. num_wait can decrease for other reasons (for example due to a
  250. * wait operation timing out).
  251. */
  252. size_t num_wait; /* Num. threads currently blocked */
  253. size_t num_wake; /* Num. threads due to wake up */
  254. size_t num_prewait; /* Num. threads in prewait */
  255. size_t gen; /* Prewait generation */
  256. int closed; /* Is closed? */
  257. } LEGACY_CONDVAR;
  258. CRYPTO_CONDVAR *ossl_crypto_condvar_new(void)
  259. {
  260. LEGACY_CONDVAR *cv;
  261. if ((cv = OPENSSL_malloc(sizeof(LEGACY_CONDVAR))) == NULL)
  262. return NULL;
  263. if ((cv->int_m = ossl_crypto_mutex_new()) == NULL) {
  264. OPENSSL_free(cv);
  265. return NULL;
  266. }
  267. if ((cv->sema = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL)) == NULL) {
  268. ossl_crypto_mutex_free(&cv->int_m);
  269. OPENSSL_free(cv);
  270. return NULL;
  271. }
  272. if ((cv->prewait_sema = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL)) == NULL) {
  273. CloseHandle(cv->sema);
  274. ossl_crypto_mutex_free(&cv->int_m);
  275. OPENSSL_free(cv);
  276. return NULL;
  277. }
  278. cv->num_wait = 0;
  279. cv->num_wake = 0;
  280. cv->num_prewait = 0;
  281. cv->closed = 0;
  282. return (CRYPTO_CONDVAR *)cv;
  283. }
  284. void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv_p)
  285. {
  286. if (*cv_p != NULL) {
  287. LEGACY_CONDVAR *cv = *(LEGACY_CONDVAR **)cv_p;
  288. CloseHandle(cv->sema);
  289. CloseHandle(cv->prewait_sema);
  290. ossl_crypto_mutex_free(&cv->int_m);
  291. OPENSSL_free(cv);
  292. }
  293. *cv_p = NULL;
  294. }
  295. static uint32_t obj_wait(HANDLE h, OSSL_TIME deadline)
  296. {
  297. DWORD timeout;
  298. if (!determine_timeout(deadline, &timeout))
  299. timeout = 1;
  300. return WaitForSingleObject(h, timeout);
  301. }
  302. void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv_, CRYPTO_MUTEX *ext_m,
  303. OSSL_TIME deadline)
  304. {
  305. LEGACY_CONDVAR *cv = (LEGACY_CONDVAR *)cv_;
  306. int closed, set_prewait = 0, have_orig_gen = 0;
  307. uint32_t rc;
  308. size_t orig_gen;
  309. /* Admission control - prewait until we can enter our actual wait phase. */
  310. do {
  311. ossl_crypto_mutex_lock(cv->int_m);
  312. closed = cv->closed;
  313. /*
  314. * Once prewait is over the prewait semaphore is signalled and
  315. * num_prewait is set to 0. Use a generation counter to track if we need
  316. * to remove a value we added to num_prewait when exiting (e.g. due to
  317. * timeout or failure of WaitForSingleObject).
  318. */
  319. if (!have_orig_gen) {
  320. orig_gen = cv->gen;
  321. have_orig_gen = 1;
  322. } else if (cv->gen != orig_gen) {
  323. set_prewait = 0;
  324. orig_gen = cv->gen;
  325. }
  326. if (!closed) {
  327. /* We can now be admitted. */
  328. ++cv->num_wait;
  329. if (set_prewait) {
  330. --cv->num_prewait;
  331. set_prewait = 0;
  332. }
  333. } else if (!set_prewait) {
  334. ++cv->num_prewait;
  335. set_prewait = 1;
  336. }
  337. ossl_crypto_mutex_unlock(cv->int_m);
  338. if (closed)
  339. if (obj_wait(cv->prewait_sema, deadline) != WAIT_OBJECT_0) {
  340. /*
  341. * If we got WAIT_OBJECT_0 we are safe - num_prewait has been
  342. * set to 0 and the semaphore has been consumed. On the other
  343. * hand if we timed out, there may be a residual posting that
  344. * was made just after we timed out. However in the worst case
  345. * this will just cause an internal spurious wakeup here in the
  346. * future, so we do not care too much about this. We treat
  347. * failure and timeout cases as the same, and simply exit in
  348. * this case.
  349. */
  350. ossl_crypto_mutex_lock(cv->int_m);
  351. if (set_prewait && cv->gen == orig_gen)
  352. --cv->num_prewait;
  353. ossl_crypto_mutex_unlock(cv->int_m);
  354. return;
  355. }
  356. } while (closed);
  357. /*
  358. * Unlock external mutex. Do not do this until we have been admitted, as we
  359. * must guarantee we wake if broadcast is called at any time after ext_m is
  360. * unlocked.
  361. */
  362. ossl_crypto_mutex_unlock(ext_m);
  363. for (;;) {
  364. /* Wait. */
  365. rc = obj_wait(cv->sema, deadline);
  366. /* Reacquire internal mutex and probe state. */
  367. ossl_crypto_mutex_lock(cv->int_m);
  368. if (cv->num_wake > 0) {
  369. /*
  370. * A wake token is available, so we can wake up. Consume the token
  371. * and get out of here. We don't care what WaitForSingleObject
  372. * returned here (e.g. if it timed out coincidentally). In the
  373. * latter case a signal might be left in the semaphore which causes
  374. * a future WaitForSingleObject call to return immediately, but in
  375. * this case we will just loop again.
  376. */
  377. --cv->num_wake;
  378. if (cv->num_wake == 0 && cv->closed) {
  379. /*
  380. * We consumed the last wake token, so we can now open the
  381. * condition variable for new admissions.
  382. */
  383. cv->closed = 0;
  384. if (cv->num_prewait > 0) {
  385. ReleaseSemaphore(cv->prewait_sema, (LONG)cv->num_prewait, NULL);
  386. cv->num_prewait = 0;
  387. ++cv->gen;
  388. }
  389. }
  390. } else if (rc == WAIT_OBJECT_0) {
  391. /*
  392. * We got a wakeup from the semaphore but we did not have any wake
  393. * tokens. This ideally does not happen, but might if during a
  394. * previous wait() call the semaphore is posted just after
  395. * WaitForSingleObject returns due to a timeout (such that the
  396. * num_wake > 0 case is taken above). Just spin again. (It is worth
  397. * noting that repeated WaitForSingleObject calls is the only method
  398. * documented for decrementing a Win32 semaphore, so this is
  399. * basically the best possible strategy.)
  400. */
  401. ossl_crypto_mutex_unlock(cv->int_m);
  402. continue;
  403. } else {
  404. /*
  405. * Assume we timed out. The WaitForSingleObject call may also have
  406. * failed for some other reason, which we treat as a timeout.
  407. */
  408. assert(cv->num_wait > 0);
  409. --cv->num_wait;
  410. }
  411. break;
  412. }
  413. ossl_crypto_mutex_unlock(cv->int_m);
  414. ossl_crypto_mutex_lock(ext_m);
  415. }
  416. void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *ext_m)
  417. {
  418. ossl_crypto_condvar_wait_timeout(cv, ext_m, ossl_time_infinite());
  419. }
  420. void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv_)
  421. {
  422. LEGACY_CONDVAR *cv = (LEGACY_CONDVAR *)cv_;
  423. size_t num_wake;
  424. ossl_crypto_mutex_lock(cv->int_m);
  425. num_wake = cv->num_wait;
  426. if (num_wake == 0) {
  427. ossl_crypto_mutex_unlock(cv->int_m);
  428. return;
  429. }
  430. cv->num_wake += num_wake;
  431. cv->num_wait -= num_wake;
  432. cv->closed = 1;
  433. ossl_crypto_mutex_unlock(cv->int_m);
  434. ReleaseSemaphore(cv->sema, num_wake, NULL);
  435. }
  436. void ossl_crypto_condvar_signal(CRYPTO_CONDVAR *cv_)
  437. {
  438. LEGACY_CONDVAR *cv = (LEGACY_CONDVAR *)cv_;
  439. ossl_crypto_mutex_lock(cv->int_m);
  440. if (cv->num_wait == 0) {
  441. ossl_crypto_mutex_unlock(cv->int_m);
  442. return;
  443. }
  444. /*
  445. * We do not close the condition variable when merely signalling, as there
  446. * are no guaranteed fairness semantics here, unlike for a broadcast.
  447. */
  448. --cv->num_wait;
  449. ++cv->num_wake;
  450. ossl_crypto_mutex_unlock(cv->int_m);
  451. ReleaseSemaphore(cv->sema, 1, NULL);
  452. }
  453. # else
  454. CRYPTO_CONDVAR *ossl_crypto_condvar_new(void)
  455. {
  456. CONDITION_VARIABLE *cv_p;
  457. if ((cv_p = OPENSSL_zalloc(sizeof(*cv_p))) == NULL)
  458. return NULL;
  459. InitializeConditionVariable(cv_p);
  460. return (CRYPTO_CONDVAR *)cv_p;
  461. }
  462. void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex)
  463. {
  464. CONDITION_VARIABLE *cv_p;
  465. CRITICAL_SECTION *mutex_p;
  466. cv_p = (CONDITION_VARIABLE *)cv;
  467. mutex_p = (CRITICAL_SECTION *)mutex;
  468. SleepConditionVariableCS(cv_p, mutex_p, INFINITE);
  469. }
  470. void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex,
  471. OSSL_TIME deadline)
  472. {
  473. DWORD timeout;
  474. CONDITION_VARIABLE *cv_p = (CONDITION_VARIABLE *)cv;
  475. CRITICAL_SECTION *mutex_p = (CRITICAL_SECTION *)mutex;
  476. if (!determine_timeout(deadline, &timeout))
  477. timeout = 1;
  478. SleepConditionVariableCS(cv_p, mutex_p, timeout);
  479. }
  480. void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv)
  481. {
  482. CONDITION_VARIABLE *cv_p;
  483. cv_p = (CONDITION_VARIABLE *)cv;
  484. WakeAllConditionVariable(cv_p);
  485. }
  486. void ossl_crypto_condvar_signal(CRYPTO_CONDVAR *cv)
  487. {
  488. CONDITION_VARIABLE *cv_p;
  489. cv_p = (CONDITION_VARIABLE *)cv;
  490. WakeConditionVariable(cv_p);
  491. }
  492. void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv)
  493. {
  494. CONDITION_VARIABLE **cv_p;
  495. cv_p = (CONDITION_VARIABLE **)cv;
  496. OPENSSL_free(*cv_p);
  497. *cv_p = NULL;
  498. }
  499. # endif
  500. void ossl_crypto_mem_barrier(void)
  501. {
  502. MemoryBarrier();
  503. }
  504. #endif