11cb0ef41Sopenharmony_ci/* MIT License 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Copyright (c) 2023 Brad House 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights 81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 111cb0ef41Sopenharmony_ci * 121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next 131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 141cb0ef41Sopenharmony_ci * Software. 151cb0ef41Sopenharmony_ci * 161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 221cb0ef41Sopenharmony_ci * SOFTWARE. 231cb0ef41Sopenharmony_ci * 241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 251cb0ef41Sopenharmony_ci */ 261cb0ef41Sopenharmony_ci#include "ares_setup.h" 271cb0ef41Sopenharmony_ci#include "ares.h" 281cb0ef41Sopenharmony_ci#include "ares_private.h" 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#ifdef CARES_THREADS 311cb0ef41Sopenharmony_ci# ifdef _WIN32 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_cistruct ares__thread_mutex { 341cb0ef41Sopenharmony_ci CRITICAL_SECTION mutex; 351cb0ef41Sopenharmony_ci}; 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ciares__thread_mutex_t *ares__thread_mutex_create(void) 381cb0ef41Sopenharmony_ci{ 391cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut = ares_malloc_zero(sizeof(*mut)); 401cb0ef41Sopenharmony_ci if (mut == NULL) { 411cb0ef41Sopenharmony_ci return NULL; 421cb0ef41Sopenharmony_ci } 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci InitializeCriticalSection(&mut->mutex); 451cb0ef41Sopenharmony_ci return mut; 461cb0ef41Sopenharmony_ci} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_civoid ares__thread_mutex_destroy(ares__thread_mutex_t *mut) 491cb0ef41Sopenharmony_ci{ 501cb0ef41Sopenharmony_ci if (mut == NULL) { 511cb0ef41Sopenharmony_ci return; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci DeleteCriticalSection(&mut->mutex); 541cb0ef41Sopenharmony_ci ares_free(mut); 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_civoid ares__thread_mutex_lock(ares__thread_mutex_t *mut) 581cb0ef41Sopenharmony_ci{ 591cb0ef41Sopenharmony_ci if (mut == NULL) { 601cb0ef41Sopenharmony_ci return; 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci EnterCriticalSection(&mut->mutex); 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_civoid ares__thread_mutex_unlock(ares__thread_mutex_t *mut) 661cb0ef41Sopenharmony_ci{ 671cb0ef41Sopenharmony_ci if (mut == NULL) { 681cb0ef41Sopenharmony_ci return; 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci LeaveCriticalSection(&mut->mutex); 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_cistruct ares__thread_cond { 741cb0ef41Sopenharmony_ci CONDITION_VARIABLE cond; 751cb0ef41Sopenharmony_ci}; 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciares__thread_cond_t *ares__thread_cond_create(void) 781cb0ef41Sopenharmony_ci{ 791cb0ef41Sopenharmony_ci ares__thread_cond_t *cond = ares_malloc_zero(sizeof(*cond)); 801cb0ef41Sopenharmony_ci if (cond == NULL) { 811cb0ef41Sopenharmony_ci return NULL; 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci InitializeConditionVariable(&cond->cond); 841cb0ef41Sopenharmony_ci return cond; 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_civoid ares__thread_cond_destroy(ares__thread_cond_t *cond) 881cb0ef41Sopenharmony_ci{ 891cb0ef41Sopenharmony_ci if (cond == NULL) { 901cb0ef41Sopenharmony_ci return; 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci ares_free(cond); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_civoid ares__thread_cond_signal(ares__thread_cond_t *cond) 961cb0ef41Sopenharmony_ci{ 971cb0ef41Sopenharmony_ci if (cond == NULL) { 981cb0ef41Sopenharmony_ci return; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci WakeConditionVariable(&cond->cond); 1011cb0ef41Sopenharmony_ci} 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_civoid ares__thread_cond_broadcast(ares__thread_cond_t *cond) 1041cb0ef41Sopenharmony_ci{ 1051cb0ef41Sopenharmony_ci if (cond == NULL) { 1061cb0ef41Sopenharmony_ci return; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci WakeAllConditionVariable(&cond->cond); 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ciares_status_t ares__thread_cond_wait(ares__thread_cond_t *cond, 1121cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut) 1131cb0ef41Sopenharmony_ci{ 1141cb0ef41Sopenharmony_ci if (cond == NULL || mut == NULL) { 1151cb0ef41Sopenharmony_ci return ARES_EFORMERR; 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci SleepConditionVariableCS(&cond->cond, &mut->mutex, INFINITE); 1191cb0ef41Sopenharmony_ci return ARES_SUCCESS; 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ciares_status_t ares__thread_cond_timedwait(ares__thread_cond_t *cond, 1231cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut, 1241cb0ef41Sopenharmony_ci unsigned long timeout_ms) 1251cb0ef41Sopenharmony_ci{ 1261cb0ef41Sopenharmony_ci if (cond == NULL || mut == NULL) { 1271cb0ef41Sopenharmony_ci return ARES_EFORMERR; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci if (!SleepConditionVariableCS(&cond->cond, &mut->mutex, timeout_ms)) { 1311cb0ef41Sopenharmony_ci return ARES_ETIMEOUT; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci return ARES_SUCCESS; 1351cb0ef41Sopenharmony_ci} 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_cistruct ares__thread { 1381cb0ef41Sopenharmony_ci HANDLE thread; 1391cb0ef41Sopenharmony_ci DWORD id; 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci void *(*func)(void *arg); 1421cb0ef41Sopenharmony_ci void *arg; 1431cb0ef41Sopenharmony_ci void *rv; 1441cb0ef41Sopenharmony_ci}; 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci/* Wrap for pthread compatibility */ 1471cb0ef41Sopenharmony_cistatic DWORD WINAPI ares__thread_func(LPVOID lpParameter) 1481cb0ef41Sopenharmony_ci{ 1491cb0ef41Sopenharmony_ci ares__thread_t *thread = lpParameter; 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci thread->rv = thread->func(thread->arg); 1521cb0ef41Sopenharmony_ci return 0; 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ciares_status_t ares__thread_create(ares__thread_t **thread, 1561cb0ef41Sopenharmony_ci ares__thread_func_t func, void *arg) 1571cb0ef41Sopenharmony_ci{ 1581cb0ef41Sopenharmony_ci ares__thread_t *thr = NULL; 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci if (func == NULL || thread == NULL) { 1611cb0ef41Sopenharmony_ci return ARES_EFORMERR; 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci thr = ares_malloc_zero(sizeof(*thr)); 1651cb0ef41Sopenharmony_ci if (thr == NULL) { 1661cb0ef41Sopenharmony_ci return ARES_ENOMEM; 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci thr->func = func; 1701cb0ef41Sopenharmony_ci thr->arg = arg; 1711cb0ef41Sopenharmony_ci thr->thread = CreateThread(NULL, 0, ares__thread_func, thr, 0, &thr->id); 1721cb0ef41Sopenharmony_ci if (thr->thread == NULL) { 1731cb0ef41Sopenharmony_ci ares_free(thr); 1741cb0ef41Sopenharmony_ci return ARES_ESERVFAIL; 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci *thread = thr; 1781cb0ef41Sopenharmony_ci return ARES_SUCCESS; 1791cb0ef41Sopenharmony_ci} 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ciares_status_t ares__thread_join(ares__thread_t *thread, void **rv) 1821cb0ef41Sopenharmony_ci{ 1831cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci if (thread == NULL) { 1861cb0ef41Sopenharmony_ci return ARES_EFORMERR; 1871cb0ef41Sopenharmony_ci } 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci if (WaitForSingleObject(thread->thread, INFINITE) != WAIT_OBJECT_0) { 1901cb0ef41Sopenharmony_ci status = ARES_ENOTFOUND; 1911cb0ef41Sopenharmony_ci } else { 1921cb0ef41Sopenharmony_ci CloseHandle(thread->thread); 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci if (status == ARES_SUCCESS && rv != NULL) { 1961cb0ef41Sopenharmony_ci *rv = thread->rv; 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci ares_free(thread); 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci return status; 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci# else /* !WIN32 == PTHREAD */ 2041cb0ef41Sopenharmony_ci# include <pthread.h> 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci/* for clock_gettime() */ 2071cb0ef41Sopenharmony_ci# ifdef HAVE_TIME_H 2081cb0ef41Sopenharmony_ci# include <time.h> 2091cb0ef41Sopenharmony_ci# endif 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci/* for gettimeofday() */ 2121cb0ef41Sopenharmony_ci# ifdef HAVE_SYS_TIME_H 2131cb0ef41Sopenharmony_ci# include <sys/time.h> 2141cb0ef41Sopenharmony_ci# endif 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_cistruct ares__thread_mutex { 2171cb0ef41Sopenharmony_ci pthread_mutex_t mutex; 2181cb0ef41Sopenharmony_ci}; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ciares__thread_mutex_t *ares__thread_mutex_create(void) 2211cb0ef41Sopenharmony_ci{ 2221cb0ef41Sopenharmony_ci pthread_mutexattr_t attr; 2231cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut = ares_malloc_zero(sizeof(*mut)); 2241cb0ef41Sopenharmony_ci if (mut == NULL) { 2251cb0ef41Sopenharmony_ci return NULL; 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci if (pthread_mutexattr_init(&attr) != 0) { 2291cb0ef41Sopenharmony_ci ares_free(mut); 2301cb0ef41Sopenharmony_ci return NULL; 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) { 2341cb0ef41Sopenharmony_ci goto fail; 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci if (pthread_mutex_init(&mut->mutex, &attr) != 0) { 2381cb0ef41Sopenharmony_ci goto fail; 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci pthread_mutexattr_destroy(&attr); 2421cb0ef41Sopenharmony_ci return mut; 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_cifail: 2451cb0ef41Sopenharmony_ci pthread_mutexattr_destroy(&attr); 2461cb0ef41Sopenharmony_ci ares_free(mut); 2471cb0ef41Sopenharmony_ci return NULL; 2481cb0ef41Sopenharmony_ci} 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_civoid ares__thread_mutex_destroy(ares__thread_mutex_t *mut) 2511cb0ef41Sopenharmony_ci{ 2521cb0ef41Sopenharmony_ci if (mut == NULL) { 2531cb0ef41Sopenharmony_ci return; 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci pthread_mutex_destroy(&mut->mutex); 2561cb0ef41Sopenharmony_ci ares_free(mut); 2571cb0ef41Sopenharmony_ci} 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_civoid ares__thread_mutex_lock(ares__thread_mutex_t *mut) 2601cb0ef41Sopenharmony_ci{ 2611cb0ef41Sopenharmony_ci if (mut == NULL) { 2621cb0ef41Sopenharmony_ci return; 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci pthread_mutex_lock(&mut->mutex); 2651cb0ef41Sopenharmony_ci} 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_civoid ares__thread_mutex_unlock(ares__thread_mutex_t *mut) 2681cb0ef41Sopenharmony_ci{ 2691cb0ef41Sopenharmony_ci if (mut == NULL) { 2701cb0ef41Sopenharmony_ci return; 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci pthread_mutex_unlock(&mut->mutex); 2731cb0ef41Sopenharmony_ci} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_cistruct ares__thread_cond { 2761cb0ef41Sopenharmony_ci pthread_cond_t cond; 2771cb0ef41Sopenharmony_ci}; 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ciares__thread_cond_t *ares__thread_cond_create(void) 2801cb0ef41Sopenharmony_ci{ 2811cb0ef41Sopenharmony_ci ares__thread_cond_t *cond = ares_malloc_zero(sizeof(*cond)); 2821cb0ef41Sopenharmony_ci if (cond == NULL) { 2831cb0ef41Sopenharmony_ci return NULL; 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci pthread_cond_init(&cond->cond, NULL); 2861cb0ef41Sopenharmony_ci return cond; 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_civoid ares__thread_cond_destroy(ares__thread_cond_t *cond) 2901cb0ef41Sopenharmony_ci{ 2911cb0ef41Sopenharmony_ci if (cond == NULL) { 2921cb0ef41Sopenharmony_ci return; 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci pthread_cond_destroy(&cond->cond); 2951cb0ef41Sopenharmony_ci ares_free(cond); 2961cb0ef41Sopenharmony_ci} 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_civoid ares__thread_cond_signal(ares__thread_cond_t *cond) 2991cb0ef41Sopenharmony_ci{ 3001cb0ef41Sopenharmony_ci if (cond == NULL) { 3011cb0ef41Sopenharmony_ci return; 3021cb0ef41Sopenharmony_ci } 3031cb0ef41Sopenharmony_ci pthread_cond_signal(&cond->cond); 3041cb0ef41Sopenharmony_ci} 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_civoid ares__thread_cond_broadcast(ares__thread_cond_t *cond) 3071cb0ef41Sopenharmony_ci{ 3081cb0ef41Sopenharmony_ci if (cond == NULL) { 3091cb0ef41Sopenharmony_ci return; 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci pthread_cond_broadcast(&cond->cond); 3121cb0ef41Sopenharmony_ci} 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ciares_status_t ares__thread_cond_wait(ares__thread_cond_t *cond, 3151cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut) 3161cb0ef41Sopenharmony_ci{ 3171cb0ef41Sopenharmony_ci if (cond == NULL || mut == NULL) { 3181cb0ef41Sopenharmony_ci return ARES_EFORMERR; 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci pthread_cond_wait(&cond->cond, &mut->mutex); 3221cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3231cb0ef41Sopenharmony_ci} 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_cistatic void ares__timespec_timeout(struct timespec *ts, unsigned long add_ms) 3261cb0ef41Sopenharmony_ci{ 3271cb0ef41Sopenharmony_ci# if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) 3281cb0ef41Sopenharmony_ci clock_gettime(CLOCK_REALTIME, ts); 3291cb0ef41Sopenharmony_ci# elif defined(HAVE_GETTIMEOFDAY) 3301cb0ef41Sopenharmony_ci struct timeval tv; 3311cb0ef41Sopenharmony_ci gettimeofday(&tv, NULL); 3321cb0ef41Sopenharmony_ci ts->tv_sec = tv.tv_sec; 3331cb0ef41Sopenharmony_ci ts->tv_nsec = tv.tv_usec * 1000; 3341cb0ef41Sopenharmony_ci# else 3351cb0ef41Sopenharmony_ci# error cannot determine current system time 3361cb0ef41Sopenharmony_ci# endif 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci ts->tv_sec += add_ms / 1000; 3391cb0ef41Sopenharmony_ci ts->tv_nsec += (add_ms % 1000) * 1000000; 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci /* Normalize if needed */ 3421cb0ef41Sopenharmony_ci if (ts->tv_nsec >= 1000000000) { 3431cb0ef41Sopenharmony_ci ts->tv_sec += ts->tv_nsec / 1000000000; 3441cb0ef41Sopenharmony_ci ts->tv_nsec %= 1000000000; 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci} 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ciares_status_t ares__thread_cond_timedwait(ares__thread_cond_t *cond, 3491cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut, 3501cb0ef41Sopenharmony_ci unsigned long timeout_ms) 3511cb0ef41Sopenharmony_ci{ 3521cb0ef41Sopenharmony_ci struct timespec ts; 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci if (cond == NULL || mut == NULL) { 3551cb0ef41Sopenharmony_ci return ARES_EFORMERR; 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci ares__timespec_timeout(&ts, timeout_ms); 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci if (pthread_cond_timedwait(&cond->cond, &mut->mutex, &ts) != 0) { 3611cb0ef41Sopenharmony_ci return ARES_ETIMEOUT; 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_cistruct ares__thread { 3681cb0ef41Sopenharmony_ci pthread_t thread; 3691cb0ef41Sopenharmony_ci}; 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ciares_status_t ares__thread_create(ares__thread_t **thread, 3721cb0ef41Sopenharmony_ci ares__thread_func_t func, void *arg) 3731cb0ef41Sopenharmony_ci{ 3741cb0ef41Sopenharmony_ci ares__thread_t *thr = NULL; 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci if (func == NULL || thread == NULL) { 3771cb0ef41Sopenharmony_ci return ARES_EFORMERR; 3781cb0ef41Sopenharmony_ci } 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ci thr = ares_malloc_zero(sizeof(*thr)); 3811cb0ef41Sopenharmony_ci if (thr == NULL) { 3821cb0ef41Sopenharmony_ci return ARES_ENOMEM; 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci if (pthread_create(&thr->thread, NULL, func, arg) != 0) { 3851cb0ef41Sopenharmony_ci ares_free(thr); 3861cb0ef41Sopenharmony_ci return ARES_ESERVFAIL; 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci *thread = thr; 3901cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3911cb0ef41Sopenharmony_ci} 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ciares_status_t ares__thread_join(ares__thread_t *thread, void **rv) 3941cb0ef41Sopenharmony_ci{ 3951cb0ef41Sopenharmony_ci void *ret = NULL; 3961cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci if (thread == NULL) { 3991cb0ef41Sopenharmony_ci return ARES_EFORMERR; 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci if (pthread_join(thread->thread, &ret) != 0) { 4031cb0ef41Sopenharmony_ci status = ARES_ENOTFOUND; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci ares_free(thread); 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci if (status == ARES_SUCCESS && rv != NULL) { 4081cb0ef41Sopenharmony_ci *rv = ret; 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci return status; 4111cb0ef41Sopenharmony_ci} 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci# endif 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ciares_bool_t ares_threadsafety(void) 4161cb0ef41Sopenharmony_ci{ 4171cb0ef41Sopenharmony_ci return ARES_TRUE; 4181cb0ef41Sopenharmony_ci} 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci#else /* !CARES_THREADS */ 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci/* NoOp */ 4231cb0ef41Sopenharmony_ciares__thread_mutex_t *ares__thread_mutex_create(void) 4241cb0ef41Sopenharmony_ci{ 4251cb0ef41Sopenharmony_ci return NULL; 4261cb0ef41Sopenharmony_ci} 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_civoid ares__thread_mutex_destroy(ares__thread_mutex_t *mut) 4291cb0ef41Sopenharmony_ci{ 4301cb0ef41Sopenharmony_ci (void)mut; 4311cb0ef41Sopenharmony_ci} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_civoid ares__thread_mutex_lock(ares__thread_mutex_t *mut) 4341cb0ef41Sopenharmony_ci{ 4351cb0ef41Sopenharmony_ci (void)mut; 4361cb0ef41Sopenharmony_ci} 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_civoid ares__thread_mutex_unlock(ares__thread_mutex_t *mut) 4391cb0ef41Sopenharmony_ci{ 4401cb0ef41Sopenharmony_ci (void)mut; 4411cb0ef41Sopenharmony_ci} 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ciares__thread_cond_t *ares__thread_cond_create(void) 4441cb0ef41Sopenharmony_ci{ 4451cb0ef41Sopenharmony_ci return NULL; 4461cb0ef41Sopenharmony_ci} 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_civoid ares__thread_cond_destroy(ares__thread_cond_t *cond) 4491cb0ef41Sopenharmony_ci{ 4501cb0ef41Sopenharmony_ci (void)cond; 4511cb0ef41Sopenharmony_ci} 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_civoid ares__thread_cond_signal(ares__thread_cond_t *cond) 4541cb0ef41Sopenharmony_ci{ 4551cb0ef41Sopenharmony_ci (void)cond; 4561cb0ef41Sopenharmony_ci} 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_civoid ares__thread_cond_broadcast(ares__thread_cond_t *cond) 4591cb0ef41Sopenharmony_ci{ 4601cb0ef41Sopenharmony_ci (void)cond; 4611cb0ef41Sopenharmony_ci} 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ciares_status_t ares__thread_cond_wait(ares__thread_cond_t *cond, 4641cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut) 4651cb0ef41Sopenharmony_ci{ 4661cb0ef41Sopenharmony_ci (void)cond; 4671cb0ef41Sopenharmony_ci (void)mut; 4681cb0ef41Sopenharmony_ci return ARES_ENOTIMP; 4691cb0ef41Sopenharmony_ci} 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ciares_status_t ares__thread_cond_timedwait(ares__thread_cond_t *cond, 4721cb0ef41Sopenharmony_ci ares__thread_mutex_t *mut, 4731cb0ef41Sopenharmony_ci unsigned long timeout_ms) 4741cb0ef41Sopenharmony_ci{ 4751cb0ef41Sopenharmony_ci (void)cond; 4761cb0ef41Sopenharmony_ci (void)mut; 4771cb0ef41Sopenharmony_ci (void)timeout_ms; 4781cb0ef41Sopenharmony_ci return ARES_ENOTIMP; 4791cb0ef41Sopenharmony_ci} 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ciares_status_t ares__thread_create(ares__thread_t **thread, 4821cb0ef41Sopenharmony_ci ares__thread_func_t func, void *arg) 4831cb0ef41Sopenharmony_ci{ 4841cb0ef41Sopenharmony_ci (void)thread; 4851cb0ef41Sopenharmony_ci (void)func; 4861cb0ef41Sopenharmony_ci (void)arg; 4871cb0ef41Sopenharmony_ci return ARES_ENOTIMP; 4881cb0ef41Sopenharmony_ci} 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ciares_status_t ares__thread_join(ares__thread_t *thread, void **rv) 4911cb0ef41Sopenharmony_ci{ 4921cb0ef41Sopenharmony_ci (void)thread; 4931cb0ef41Sopenharmony_ci (void)rv; 4941cb0ef41Sopenharmony_ci return ARES_ENOTIMP; 4951cb0ef41Sopenharmony_ci} 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ciares_bool_t ares_threadsafety(void) 4981cb0ef41Sopenharmony_ci{ 4991cb0ef41Sopenharmony_ci return ARES_FALSE; 5001cb0ef41Sopenharmony_ci} 5011cb0ef41Sopenharmony_ci#endif 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci 5041cb0ef41Sopenharmony_ciares_status_t ares__channel_threading_init(ares_channel_t *channel) 5051cb0ef41Sopenharmony_ci{ 5061cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci /* Threading is optional! */ 5091cb0ef41Sopenharmony_ci if (!ares_threadsafety()) { 5101cb0ef41Sopenharmony_ci return ARES_SUCCESS; 5111cb0ef41Sopenharmony_ci } 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci channel->lock = ares__thread_mutex_create(); 5141cb0ef41Sopenharmony_ci if (channel->lock == NULL) { 5151cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 5161cb0ef41Sopenharmony_ci goto done; 5171cb0ef41Sopenharmony_ci } 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ci channel->cond_empty = ares__thread_cond_create(); 5201cb0ef41Sopenharmony_ci if (channel->cond_empty == NULL) { 5211cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 5221cb0ef41Sopenharmony_ci goto done; 5231cb0ef41Sopenharmony_ci } 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_cidone: 5261cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5271cb0ef41Sopenharmony_ci ares__channel_threading_destroy(channel); 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci return status; 5301cb0ef41Sopenharmony_ci} 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_civoid ares__channel_threading_destroy(ares_channel_t *channel) 5331cb0ef41Sopenharmony_ci{ 5341cb0ef41Sopenharmony_ci ares__thread_mutex_destroy(channel->lock); 5351cb0ef41Sopenharmony_ci channel->lock = NULL; 5361cb0ef41Sopenharmony_ci ares__thread_cond_destroy(channel->cond_empty); 5371cb0ef41Sopenharmony_ci channel->cond_empty = NULL; 5381cb0ef41Sopenharmony_ci} 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_civoid ares__channel_lock(ares_channel_t *channel) 5411cb0ef41Sopenharmony_ci{ 5421cb0ef41Sopenharmony_ci ares__thread_mutex_lock(channel->lock); 5431cb0ef41Sopenharmony_ci} 5441cb0ef41Sopenharmony_ci 5451cb0ef41Sopenharmony_civoid ares__channel_unlock(ares_channel_t *channel) 5461cb0ef41Sopenharmony_ci{ 5471cb0ef41Sopenharmony_ci ares__thread_mutex_unlock(channel->lock); 5481cb0ef41Sopenharmony_ci} 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci/* Must not be holding a channel lock already, public function only */ 5511cb0ef41Sopenharmony_ciares_status_t ares_queue_wait_empty(ares_channel_t *channel, int timeout_ms) 5521cb0ef41Sopenharmony_ci{ 5531cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 5541cb0ef41Sopenharmony_ci struct timeval tout; 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci if (!ares_threadsafety()) { 5571cb0ef41Sopenharmony_ci return ARES_ENOTIMP; 5581cb0ef41Sopenharmony_ci } 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ci if (channel == NULL) { 5611cb0ef41Sopenharmony_ci return ARES_EFORMERR; 5621cb0ef41Sopenharmony_ci } 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ci if (timeout_ms >= 0) { 5651cb0ef41Sopenharmony_ci tout = ares__tvnow(); 5661cb0ef41Sopenharmony_ci tout.tv_sec += timeout_ms / 1000; 5671cb0ef41Sopenharmony_ci tout.tv_usec += (timeout_ms % 1000) * 1000; 5681cb0ef41Sopenharmony_ci } 5691cb0ef41Sopenharmony_ci 5701cb0ef41Sopenharmony_ci ares__thread_mutex_lock(channel->lock); 5711cb0ef41Sopenharmony_ci while (ares__llist_len(channel->all_queries)) { 5721cb0ef41Sopenharmony_ci if (timeout_ms < 0) { 5731cb0ef41Sopenharmony_ci ares__thread_cond_wait(channel->cond_empty, channel->lock); 5741cb0ef41Sopenharmony_ci } else { 5751cb0ef41Sopenharmony_ci struct timeval tv_remaining; 5761cb0ef41Sopenharmony_ci struct timeval tv_now = ares__tvnow(); 5771cb0ef41Sopenharmony_ci unsigned long tms; 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci ares__timeval_remaining(&tv_remaining, &tv_now, &tout); 5801cb0ef41Sopenharmony_ci tms = (unsigned long)((tv_remaining.tv_sec * 1000) + 5811cb0ef41Sopenharmony_ci (tv_remaining.tv_usec / 1000)); 5821cb0ef41Sopenharmony_ci if (tms == 0) { 5831cb0ef41Sopenharmony_ci status = ARES_ETIMEOUT; 5841cb0ef41Sopenharmony_ci } else { 5851cb0ef41Sopenharmony_ci status = 5861cb0ef41Sopenharmony_ci ares__thread_cond_timedwait(channel->cond_empty, channel->lock, tms); 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci } 5891cb0ef41Sopenharmony_ci } 5901cb0ef41Sopenharmony_ci ares__thread_mutex_unlock(channel->lock); 5911cb0ef41Sopenharmony_ci return status; 5921cb0ef41Sopenharmony_ci} 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_civoid ares_queue_notify_empty(ares_channel_t *channel) 5951cb0ef41Sopenharmony_ci{ 5961cb0ef41Sopenharmony_ci if (channel == NULL) { 5971cb0ef41Sopenharmony_ci return; 5981cb0ef41Sopenharmony_ci } 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci /* We are guaranteed to be holding a channel lock already */ 6011cb0ef41Sopenharmony_ci if (ares__llist_len(channel->all_queries)) { 6021cb0ef41Sopenharmony_ci return; 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ci /* Notify all waiters of the conditional */ 6061cb0ef41Sopenharmony_ci ares__thread_cond_broadcast(channel->cond_empty); 6071cb0ef41Sopenharmony_ci} 608