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, ¶ms, 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