xref: /third_party/node/deps/uv/src/win/thread.c (revision 1cb0ef41)
11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include <assert.h>
231cb0ef41Sopenharmony_ci#include <limits.h>
241cb0ef41Sopenharmony_ci#include <stdlib.h>
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci#if defined(__MINGW64_VERSION_MAJOR)
271cb0ef41Sopenharmony_ci/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may
281cb0ef41Sopenharmony_ci * require this header in some versions of mingw64. */
291cb0ef41Sopenharmony_ci#include <intrin.h>
301cb0ef41Sopenharmony_ci#endif
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#include "uv.h"
331cb0ef41Sopenharmony_ci#include "internal.h"
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cistatic void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
361cb0ef41Sopenharmony_ci  DWORD result;
371cb0ef41Sopenharmony_ci  HANDLE existing_event, created_event;
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  created_event = CreateEvent(NULL, 1, 0, NULL);
401cb0ef41Sopenharmony_ci  if (created_event == 0) {
411cb0ef41Sopenharmony_ci    /* Could fail in a low-memory situation? */
421cb0ef41Sopenharmony_ci    uv_fatal_error(GetLastError(), "CreateEvent");
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  existing_event = InterlockedCompareExchangePointer(&guard->event,
461cb0ef41Sopenharmony_ci                                                     created_event,
471cb0ef41Sopenharmony_ci                                                     NULL);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  if (existing_event == NULL) {
501cb0ef41Sopenharmony_ci    /* We won the race */
511cb0ef41Sopenharmony_ci    callback();
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci    result = SetEvent(created_event);
541cb0ef41Sopenharmony_ci    assert(result);
551cb0ef41Sopenharmony_ci    guard->ran = 1;
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  } else {
581cb0ef41Sopenharmony_ci    /* We lost the race. Destroy the event we created and wait for the existing
591cb0ef41Sopenharmony_ci     * one to become signaled. */
601cb0ef41Sopenharmony_ci    CloseHandle(created_event);
611cb0ef41Sopenharmony_ci    result = WaitForSingleObject(existing_event, INFINITE);
621cb0ef41Sopenharmony_ci    assert(result == WAIT_OBJECT_0);
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci}
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_civoid uv_once(uv_once_t* guard, void (*callback)(void)) {
681cb0ef41Sopenharmony_ci  /* Fast case - avoid WaitForSingleObject. */
691cb0ef41Sopenharmony_ci  if (guard->ran) {
701cb0ef41Sopenharmony_ci    return;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  uv__once_inner(guard, callback);
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci/* Verify that uv_thread_t can be stored in a TLS slot. */
781cb0ef41Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_cistatic uv_key_t uv__current_thread_key;
811cb0ef41Sopenharmony_cistatic uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_cistatic void uv__init_current_thread_key(void) {
851cb0ef41Sopenharmony_ci  if (uv_key_create(&uv__current_thread_key))
861cb0ef41Sopenharmony_ci    abort();
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_cistruct thread_ctx {
911cb0ef41Sopenharmony_ci  void (*entry)(void* arg);
921cb0ef41Sopenharmony_ci  void* arg;
931cb0ef41Sopenharmony_ci  uv_thread_t self;
941cb0ef41Sopenharmony_ci};
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_cistatic UINT __stdcall uv__thread_start(void* arg) {
981cb0ef41Sopenharmony_ci  struct thread_ctx *ctx_p;
991cb0ef41Sopenharmony_ci  struct thread_ctx ctx;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  ctx_p = arg;
1021cb0ef41Sopenharmony_ci  ctx = *ctx_p;
1031cb0ef41Sopenharmony_ci  uv__free(ctx_p);
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
1061cb0ef41Sopenharmony_ci  uv_key_set(&uv__current_thread_key, ctx.self);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  ctx.entry(ctx.arg);
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  return 0;
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ciint uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
1151cb0ef41Sopenharmony_ci  uv_thread_options_t params;
1161cb0ef41Sopenharmony_ci  params.flags = UV_THREAD_NO_FLAGS;
1171cb0ef41Sopenharmony_ci  return uv_thread_create_ex(tid, &params, entry, arg);
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ciint uv_thread_create_ex(uv_thread_t* tid,
1211cb0ef41Sopenharmony_ci                        const uv_thread_options_t* params,
1221cb0ef41Sopenharmony_ci                        void (*entry)(void *arg),
1231cb0ef41Sopenharmony_ci                        void *arg) {
1241cb0ef41Sopenharmony_ci  struct thread_ctx* ctx;
1251cb0ef41Sopenharmony_ci  int err;
1261cb0ef41Sopenharmony_ci  HANDLE thread;
1271cb0ef41Sopenharmony_ci  SYSTEM_INFO sysinfo;
1281cb0ef41Sopenharmony_ci  size_t stack_size;
1291cb0ef41Sopenharmony_ci  size_t pagesize;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  stack_size =
1321cb0ef41Sopenharmony_ci      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  if (stack_size != 0) {
1351cb0ef41Sopenharmony_ci    GetNativeSystemInfo(&sysinfo);
1361cb0ef41Sopenharmony_ci    pagesize = (size_t)sysinfo.dwPageSize;
1371cb0ef41Sopenharmony_ci    /* Round up to the nearest page boundary. */
1381cb0ef41Sopenharmony_ci    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci    if ((unsigned)stack_size != stack_size)
1411cb0ef41Sopenharmony_ci      return UV_EINVAL;
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  ctx = uv__malloc(sizeof(*ctx));
1451cb0ef41Sopenharmony_ci  if (ctx == NULL)
1461cb0ef41Sopenharmony_ci    return UV_ENOMEM;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  ctx->entry = entry;
1491cb0ef41Sopenharmony_ci  ctx->arg = arg;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  /* Create the thread in suspended state so we have a chance to pass
1521cb0ef41Sopenharmony_ci   * its own creation handle to it */
1531cb0ef41Sopenharmony_ci  thread = (HANDLE) _beginthreadex(NULL,
1541cb0ef41Sopenharmony_ci                                   (unsigned)stack_size,
1551cb0ef41Sopenharmony_ci                                   uv__thread_start,
1561cb0ef41Sopenharmony_ci                                   ctx,
1571cb0ef41Sopenharmony_ci                                   CREATE_SUSPENDED,
1581cb0ef41Sopenharmony_ci                                   NULL);
1591cb0ef41Sopenharmony_ci  if (thread == NULL) {
1601cb0ef41Sopenharmony_ci    err = errno;
1611cb0ef41Sopenharmony_ci    uv__free(ctx);
1621cb0ef41Sopenharmony_ci  } else {
1631cb0ef41Sopenharmony_ci    err = 0;
1641cb0ef41Sopenharmony_ci    *tid = thread;
1651cb0ef41Sopenharmony_ci    ctx->self = thread;
1661cb0ef41Sopenharmony_ci    ResumeThread(thread);
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  switch (err) {
1701cb0ef41Sopenharmony_ci    case 0:
1711cb0ef41Sopenharmony_ci      return 0;
1721cb0ef41Sopenharmony_ci    case EACCES:
1731cb0ef41Sopenharmony_ci      return UV_EACCES;
1741cb0ef41Sopenharmony_ci    case EAGAIN:
1751cb0ef41Sopenharmony_ci      return UV_EAGAIN;
1761cb0ef41Sopenharmony_ci    case EINVAL:
1771cb0ef41Sopenharmony_ci      return UV_EINVAL;
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  return UV_EIO;
1811cb0ef41Sopenharmony_ci}
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ciuv_thread_t uv_thread_self(void) {
1851cb0ef41Sopenharmony_ci  uv_thread_t key;
1861cb0ef41Sopenharmony_ci  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
1871cb0ef41Sopenharmony_ci  key = uv_key_get(&uv__current_thread_key);
1881cb0ef41Sopenharmony_ci  if (key == NULL) {
1891cb0ef41Sopenharmony_ci      /* If the thread wasn't started by uv_thread_create (such as the main
1901cb0ef41Sopenharmony_ci       * thread), we assign an id to it now. */
1911cb0ef41Sopenharmony_ci      if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1921cb0ef41Sopenharmony_ci                           GetCurrentProcess(), &key, 0,
1931cb0ef41Sopenharmony_ci                           FALSE, DUPLICATE_SAME_ACCESS)) {
1941cb0ef41Sopenharmony_ci          uv_fatal_error(GetLastError(), "DuplicateHandle");
1951cb0ef41Sopenharmony_ci      }
1961cb0ef41Sopenharmony_ci      uv_key_set(&uv__current_thread_key, key);
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci  return key;
1991cb0ef41Sopenharmony_ci}
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ciint uv_thread_join(uv_thread_t *tid) {
2031cb0ef41Sopenharmony_ci  if (WaitForSingleObject(*tid, INFINITE))
2041cb0ef41Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
2051cb0ef41Sopenharmony_ci  else {
2061cb0ef41Sopenharmony_ci    CloseHandle(*tid);
2071cb0ef41Sopenharmony_ci    *tid = 0;
2081cb0ef41Sopenharmony_ci    MemoryBarrier();  /* For feature parity with pthread_join(). */
2091cb0ef41Sopenharmony_ci    return 0;
2101cb0ef41Sopenharmony_ci  }
2111cb0ef41Sopenharmony_ci}
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ciint uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
2151cb0ef41Sopenharmony_ci  return *t1 == *t2;
2161cb0ef41Sopenharmony_ci}
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ciint uv_mutex_init(uv_mutex_t* mutex) {
2201cb0ef41Sopenharmony_ci  InitializeCriticalSection(mutex);
2211cb0ef41Sopenharmony_ci  return 0;
2221cb0ef41Sopenharmony_ci}
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ciint uv_mutex_init_recursive(uv_mutex_t* mutex) {
2261cb0ef41Sopenharmony_ci  return uv_mutex_init(mutex);
2271cb0ef41Sopenharmony_ci}
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_civoid uv_mutex_destroy(uv_mutex_t* mutex) {
2311cb0ef41Sopenharmony_ci  DeleteCriticalSection(mutex);
2321cb0ef41Sopenharmony_ci}
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_civoid uv_mutex_lock(uv_mutex_t* mutex) {
2361cb0ef41Sopenharmony_ci  EnterCriticalSection(mutex);
2371cb0ef41Sopenharmony_ci}
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ciint uv_mutex_trylock(uv_mutex_t* mutex) {
2411cb0ef41Sopenharmony_ci  if (TryEnterCriticalSection(mutex))
2421cb0ef41Sopenharmony_ci    return 0;
2431cb0ef41Sopenharmony_ci  else
2441cb0ef41Sopenharmony_ci    return UV_EBUSY;
2451cb0ef41Sopenharmony_ci}
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_civoid uv_mutex_unlock(uv_mutex_t* mutex) {
2491cb0ef41Sopenharmony_ci  LeaveCriticalSection(mutex);
2501cb0ef41Sopenharmony_ci}
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci/* Ensure that the ABI for this type remains stable in v1.x */
2531cb0ef41Sopenharmony_ci#ifdef _WIN64
2541cb0ef41Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_rwlock_t) == 80);
2551cb0ef41Sopenharmony_ci#else
2561cb0ef41Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_rwlock_t) == 48);
2571cb0ef41Sopenharmony_ci#endif
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ciint uv_rwlock_init(uv_rwlock_t* rwlock) {
2601cb0ef41Sopenharmony_ci  memset(rwlock, 0, sizeof(*rwlock));
2611cb0ef41Sopenharmony_ci  InitializeSRWLock(&rwlock->read_write_lock_);
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  return 0;
2641cb0ef41Sopenharmony_ci}
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_civoid uv_rwlock_destroy(uv_rwlock_t* rwlock) {
2681cb0ef41Sopenharmony_ci  /* SRWLock does not need explicit destruction so long as there are no waiting threads
2691cb0ef41Sopenharmony_ci     See: https://docs.microsoft.com/windows/win32/api/synchapi/nf-synchapi-initializesrwlock#remarks */
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_civoid uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
2741cb0ef41Sopenharmony_ci  AcquireSRWLockShared(&rwlock->read_write_lock_);
2751cb0ef41Sopenharmony_ci}
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ciint uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
2791cb0ef41Sopenharmony_ci  if (!TryAcquireSRWLockShared(&rwlock->read_write_lock_))
2801cb0ef41Sopenharmony_ci    return UV_EBUSY;
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci  return 0;
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_civoid uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
2871cb0ef41Sopenharmony_ci  ReleaseSRWLockShared(&rwlock->read_write_lock_);
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_civoid uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
2921cb0ef41Sopenharmony_ci  AcquireSRWLockExclusive(&rwlock->read_write_lock_);
2931cb0ef41Sopenharmony_ci}
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ciint uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
2971cb0ef41Sopenharmony_ci  if (!TryAcquireSRWLockExclusive(&rwlock->read_write_lock_))
2981cb0ef41Sopenharmony_ci    return UV_EBUSY;
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  return 0;
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_civoid uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
3051cb0ef41Sopenharmony_ci  ReleaseSRWLockExclusive(&rwlock->read_write_lock_);
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ciint uv_sem_init(uv_sem_t* sem, unsigned int value) {
3101cb0ef41Sopenharmony_ci  *sem = CreateSemaphore(NULL, value, INT_MAX, NULL);
3111cb0ef41Sopenharmony_ci  if (*sem == NULL)
3121cb0ef41Sopenharmony_ci    return uv_translate_sys_error(GetLastError());
3131cb0ef41Sopenharmony_ci  else
3141cb0ef41Sopenharmony_ci    return 0;
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_civoid uv_sem_destroy(uv_sem_t* sem) {
3191cb0ef41Sopenharmony_ci  if (!CloseHandle(*sem))
3201cb0ef41Sopenharmony_ci    abort();
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_civoid uv_sem_post(uv_sem_t* sem) {
3251cb0ef41Sopenharmony_ci  if (!ReleaseSemaphore(*sem, 1, NULL))
3261cb0ef41Sopenharmony_ci    abort();
3271cb0ef41Sopenharmony_ci}
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_civoid uv_sem_wait(uv_sem_t* sem) {
3311cb0ef41Sopenharmony_ci  if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0)
3321cb0ef41Sopenharmony_ci    abort();
3331cb0ef41Sopenharmony_ci}
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ciint uv_sem_trywait(uv_sem_t* sem) {
3371cb0ef41Sopenharmony_ci  DWORD r = WaitForSingleObject(*sem, 0);
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci  if (r == WAIT_OBJECT_0)
3401cb0ef41Sopenharmony_ci    return 0;
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci  if (r == WAIT_TIMEOUT)
3431cb0ef41Sopenharmony_ci    return UV_EAGAIN;
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci  abort();
3461cb0ef41Sopenharmony_ci  return -1; /* Satisfy the compiler. */
3471cb0ef41Sopenharmony_ci}
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ciint uv_cond_init(uv_cond_t* cond) {
3511cb0ef41Sopenharmony_ci  InitializeConditionVariable(&cond->cond_var);
3521cb0ef41Sopenharmony_ci  return 0;
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_civoid uv_cond_destroy(uv_cond_t* cond) {
3571cb0ef41Sopenharmony_ci  /* nothing to do */
3581cb0ef41Sopenharmony_ci  (void) &cond;
3591cb0ef41Sopenharmony_ci}
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_civoid uv_cond_signal(uv_cond_t* cond) {
3631cb0ef41Sopenharmony_ci  WakeConditionVariable(&cond->cond_var);
3641cb0ef41Sopenharmony_ci}
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_civoid uv_cond_broadcast(uv_cond_t* cond) {
3681cb0ef41Sopenharmony_ci  WakeAllConditionVariable(&cond->cond_var);
3691cb0ef41Sopenharmony_ci}
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_civoid uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
3731cb0ef41Sopenharmony_ci  if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
3741cb0ef41Sopenharmony_ci    abort();
3751cb0ef41Sopenharmony_ci}
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ciint uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
3781cb0ef41Sopenharmony_ci  if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
3791cb0ef41Sopenharmony_ci    return 0;
3801cb0ef41Sopenharmony_ci  if (GetLastError() != ERROR_TIMEOUT)
3811cb0ef41Sopenharmony_ci    abort();
3821cb0ef41Sopenharmony_ci  return UV_ETIMEDOUT;
3831cb0ef41Sopenharmony_ci}
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ciint uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
3871cb0ef41Sopenharmony_ci  int err;
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  barrier->n = count;
3901cb0ef41Sopenharmony_ci  barrier->count = 0;
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci  err = uv_mutex_init(&barrier->mutex);
3931cb0ef41Sopenharmony_ci  if (err)
3941cb0ef41Sopenharmony_ci    return err;
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  err = uv_sem_init(&barrier->turnstile1, 0);
3971cb0ef41Sopenharmony_ci  if (err)
3981cb0ef41Sopenharmony_ci    goto error2;
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci  err = uv_sem_init(&barrier->turnstile2, 1);
4011cb0ef41Sopenharmony_ci  if (err)
4021cb0ef41Sopenharmony_ci    goto error;
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  return 0;
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_cierror:
4071cb0ef41Sopenharmony_ci  uv_sem_destroy(&barrier->turnstile1);
4081cb0ef41Sopenharmony_cierror2:
4091cb0ef41Sopenharmony_ci  uv_mutex_destroy(&barrier->mutex);
4101cb0ef41Sopenharmony_ci  return err;
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci}
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_civoid uv_barrier_destroy(uv_barrier_t* barrier) {
4161cb0ef41Sopenharmony_ci  uv_sem_destroy(&barrier->turnstile2);
4171cb0ef41Sopenharmony_ci  uv_sem_destroy(&barrier->turnstile1);
4181cb0ef41Sopenharmony_ci  uv_mutex_destroy(&barrier->mutex);
4191cb0ef41Sopenharmony_ci}
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ciint uv_barrier_wait(uv_barrier_t* barrier) {
4231cb0ef41Sopenharmony_ci  int serial_thread;
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ci  uv_mutex_lock(&barrier->mutex);
4261cb0ef41Sopenharmony_ci  if (++barrier->count == barrier->n) {
4271cb0ef41Sopenharmony_ci    uv_sem_wait(&barrier->turnstile2);
4281cb0ef41Sopenharmony_ci    uv_sem_post(&barrier->turnstile1);
4291cb0ef41Sopenharmony_ci  }
4301cb0ef41Sopenharmony_ci  uv_mutex_unlock(&barrier->mutex);
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  uv_sem_wait(&barrier->turnstile1);
4331cb0ef41Sopenharmony_ci  uv_sem_post(&barrier->turnstile1);
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci  uv_mutex_lock(&barrier->mutex);
4361cb0ef41Sopenharmony_ci  serial_thread = (--barrier->count == 0);
4371cb0ef41Sopenharmony_ci  if (serial_thread) {
4381cb0ef41Sopenharmony_ci    uv_sem_wait(&barrier->turnstile1);
4391cb0ef41Sopenharmony_ci    uv_sem_post(&barrier->turnstile2);
4401cb0ef41Sopenharmony_ci  }
4411cb0ef41Sopenharmony_ci  uv_mutex_unlock(&barrier->mutex);
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci  uv_sem_wait(&barrier->turnstile2);
4441cb0ef41Sopenharmony_ci  uv_sem_post(&barrier->turnstile2);
4451cb0ef41Sopenharmony_ci  return serial_thread;
4461cb0ef41Sopenharmony_ci}
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ciint uv_key_create(uv_key_t* key) {
4501cb0ef41Sopenharmony_ci  key->tls_index = TlsAlloc();
4511cb0ef41Sopenharmony_ci  if (key->tls_index == TLS_OUT_OF_INDEXES)
4521cb0ef41Sopenharmony_ci    return UV_ENOMEM;
4531cb0ef41Sopenharmony_ci  return 0;
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_civoid uv_key_delete(uv_key_t* key) {
4581cb0ef41Sopenharmony_ci  if (TlsFree(key->tls_index) == FALSE)
4591cb0ef41Sopenharmony_ci    abort();
4601cb0ef41Sopenharmony_ci  key->tls_index = TLS_OUT_OF_INDEXES;
4611cb0ef41Sopenharmony_ci}
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_civoid* uv_key_get(uv_key_t* key) {
4651cb0ef41Sopenharmony_ci  void* value;
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  value = TlsGetValue(key->tls_index);
4681cb0ef41Sopenharmony_ci  if (value == NULL)
4691cb0ef41Sopenharmony_ci    if (GetLastError() != ERROR_SUCCESS)
4701cb0ef41Sopenharmony_ci      abort();
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  return value;
4731cb0ef41Sopenharmony_ci}
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_civoid uv_key_set(uv_key_t* key, void* value) {
4771cb0ef41Sopenharmony_ci  if (TlsSetValue(key->tls_index, value) == FALSE)
4781cb0ef41Sopenharmony_ci    abort();
4791cb0ef41Sopenharmony_ci}
480