1370b324cSopenharmony_ci/* Threads.c -- multithreading library 2370b324cSopenharmony_ci2023-03-04 : Igor Pavlov : Public domain */ 3370b324cSopenharmony_ci 4370b324cSopenharmony_ci#include "Precomp.h" 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci#ifdef _WIN32 7370b324cSopenharmony_ci 8370b324cSopenharmony_ci#ifndef USE_THREADS_CreateThread 9370b324cSopenharmony_ci#include <process.h> 10370b324cSopenharmony_ci#endif 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#include "Threads.h" 13370b324cSopenharmony_ci 14370b324cSopenharmony_cistatic WRes GetError(void) 15370b324cSopenharmony_ci{ 16370b324cSopenharmony_ci const DWORD res = GetLastError(); 17370b324cSopenharmony_ci return res ? (WRes)res : 1; 18370b324cSopenharmony_ci} 19370b324cSopenharmony_ci 20370b324cSopenharmony_cistatic WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); } 21370b324cSopenharmony_cistatic WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } 22370b324cSopenharmony_ci 23370b324cSopenharmony_ciWRes HandlePtr_Close(HANDLE *p) 24370b324cSopenharmony_ci{ 25370b324cSopenharmony_ci if (*p != NULL) 26370b324cSopenharmony_ci { 27370b324cSopenharmony_ci if (!CloseHandle(*p)) 28370b324cSopenharmony_ci return GetError(); 29370b324cSopenharmony_ci *p = NULL; 30370b324cSopenharmony_ci } 31370b324cSopenharmony_ci return 0; 32370b324cSopenharmony_ci} 33370b324cSopenharmony_ci 34370b324cSopenharmony_ciWRes Handle_WaitObject(HANDLE h) 35370b324cSopenharmony_ci{ 36370b324cSopenharmony_ci DWORD dw = WaitForSingleObject(h, INFINITE); 37370b324cSopenharmony_ci /* 38370b324cSopenharmony_ci (dw) result: 39370b324cSopenharmony_ci WAIT_OBJECT_0 // 0 40370b324cSopenharmony_ci WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space 41370b324cSopenharmony_ci WAIT_TIMEOUT // 0x00000102 : is compatible with Win32 Error space 42370b324cSopenharmony_ci WAIT_FAILED // 0xFFFFFFFF 43370b324cSopenharmony_ci */ 44370b324cSopenharmony_ci if (dw == WAIT_FAILED) 45370b324cSopenharmony_ci { 46370b324cSopenharmony_ci dw = GetLastError(); 47370b324cSopenharmony_ci if (dw == 0) 48370b324cSopenharmony_ci return WAIT_FAILED; 49370b324cSopenharmony_ci } 50370b324cSopenharmony_ci return (WRes)dw; 51370b324cSopenharmony_ci} 52370b324cSopenharmony_ci 53370b324cSopenharmony_ci#define Thread_Wait(p) Handle_WaitObject(*(p)) 54370b324cSopenharmony_ci 55370b324cSopenharmony_ciWRes Thread_Wait_Close(CThread *p) 56370b324cSopenharmony_ci{ 57370b324cSopenharmony_ci WRes res = Thread_Wait(p); 58370b324cSopenharmony_ci WRes res2 = Thread_Close(p); 59370b324cSopenharmony_ci return (res != 0 ? res : res2); 60370b324cSopenharmony_ci} 61370b324cSopenharmony_ci 62370b324cSopenharmony_ciWRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) 63370b324cSopenharmony_ci{ 64370b324cSopenharmony_ci /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ 65370b324cSopenharmony_ci 66370b324cSopenharmony_ci #ifdef USE_THREADS_CreateThread 67370b324cSopenharmony_ci 68370b324cSopenharmony_ci DWORD threadId; 69370b324cSopenharmony_ci *p = CreateThread(NULL, 0, func, param, 0, &threadId); 70370b324cSopenharmony_ci 71370b324cSopenharmony_ci #else 72370b324cSopenharmony_ci 73370b324cSopenharmony_ci unsigned threadId; 74370b324cSopenharmony_ci *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); 75370b324cSopenharmony_ci 76370b324cSopenharmony_ci #endif 77370b324cSopenharmony_ci 78370b324cSopenharmony_ci /* maybe we must use errno here, but probably GetLastError() is also OK. */ 79370b324cSopenharmony_ci return HandleToWRes(*p); 80370b324cSopenharmony_ci} 81370b324cSopenharmony_ci 82370b324cSopenharmony_ci 83370b324cSopenharmony_ciWRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) 84370b324cSopenharmony_ci{ 85370b324cSopenharmony_ci #ifdef USE_THREADS_CreateThread 86370b324cSopenharmony_ci 87370b324cSopenharmony_ci UNUSED_VAR(affinity) 88370b324cSopenharmony_ci return Thread_Create(p, func, param); 89370b324cSopenharmony_ci 90370b324cSopenharmony_ci #else 91370b324cSopenharmony_ci 92370b324cSopenharmony_ci /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ 93370b324cSopenharmony_ci HANDLE h; 94370b324cSopenharmony_ci WRes wres; 95370b324cSopenharmony_ci unsigned threadId; 96370b324cSopenharmony_ci h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); 97370b324cSopenharmony_ci *p = h; 98370b324cSopenharmony_ci wres = HandleToWRes(h); 99370b324cSopenharmony_ci if (h) 100370b324cSopenharmony_ci { 101370b324cSopenharmony_ci { 102370b324cSopenharmony_ci // DWORD_PTR prevMask = 103370b324cSopenharmony_ci SetThreadAffinityMask(h, (DWORD_PTR)affinity); 104370b324cSopenharmony_ci /* 105370b324cSopenharmony_ci if (prevMask == 0) 106370b324cSopenharmony_ci { 107370b324cSopenharmony_ci // affinity change is non-critical error, so we can ignore it 108370b324cSopenharmony_ci // wres = GetError(); 109370b324cSopenharmony_ci } 110370b324cSopenharmony_ci */ 111370b324cSopenharmony_ci } 112370b324cSopenharmony_ci { 113370b324cSopenharmony_ci DWORD prevSuspendCount = ResumeThread(h); 114370b324cSopenharmony_ci /* ResumeThread() returns: 115370b324cSopenharmony_ci 0 : was_not_suspended 116370b324cSopenharmony_ci 1 : was_resumed 117370b324cSopenharmony_ci -1 : error 118370b324cSopenharmony_ci */ 119370b324cSopenharmony_ci if (prevSuspendCount == (DWORD)-1) 120370b324cSopenharmony_ci wres = GetError(); 121370b324cSopenharmony_ci } 122370b324cSopenharmony_ci } 123370b324cSopenharmony_ci 124370b324cSopenharmony_ci /* maybe we must use errno here, but probably GetLastError() is also OK. */ 125370b324cSopenharmony_ci return wres; 126370b324cSopenharmony_ci 127370b324cSopenharmony_ci #endif 128370b324cSopenharmony_ci} 129370b324cSopenharmony_ci 130370b324cSopenharmony_ci 131370b324cSopenharmony_cistatic WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) 132370b324cSopenharmony_ci{ 133370b324cSopenharmony_ci *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); 134370b324cSopenharmony_ci return HandleToWRes(*p); 135370b324cSopenharmony_ci} 136370b324cSopenharmony_ci 137370b324cSopenharmony_ciWRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } 138370b324cSopenharmony_ciWRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } 139370b324cSopenharmony_ci 140370b324cSopenharmony_ciWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } 141370b324cSopenharmony_ciWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } 142370b324cSopenharmony_ciWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } 143370b324cSopenharmony_ciWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } 144370b324cSopenharmony_ci 145370b324cSopenharmony_ci 146370b324cSopenharmony_ciWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) 147370b324cSopenharmony_ci{ 148370b324cSopenharmony_ci // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore() 149370b324cSopenharmony_ci *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); 150370b324cSopenharmony_ci return HandleToWRes(*p); 151370b324cSopenharmony_ci} 152370b324cSopenharmony_ci 153370b324cSopenharmony_ciWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) 154370b324cSopenharmony_ci{ 155370b324cSopenharmony_ci // if (Semaphore_IsCreated(p)) 156370b324cSopenharmony_ci { 157370b324cSopenharmony_ci WRes wres = Semaphore_Close(p); 158370b324cSopenharmony_ci if (wres != 0) 159370b324cSopenharmony_ci return wres; 160370b324cSopenharmony_ci } 161370b324cSopenharmony_ci return Semaphore_Create(p, initCount, maxCount); 162370b324cSopenharmony_ci} 163370b324cSopenharmony_ci 164370b324cSopenharmony_cistatic WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) 165370b324cSopenharmony_ci { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } 166370b324cSopenharmony_ciWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) 167370b324cSopenharmony_ci { return Semaphore_Release(p, (LONG)num, NULL); } 168370b324cSopenharmony_ciWRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } 169370b324cSopenharmony_ci 170370b324cSopenharmony_ciWRes CriticalSection_Init(CCriticalSection *p) 171370b324cSopenharmony_ci{ 172370b324cSopenharmony_ci /* InitializeCriticalSection() can raise exception: 173370b324cSopenharmony_ci Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception 174370b324cSopenharmony_ci Windows Vista+ : no exceptions */ 175370b324cSopenharmony_ci #ifdef _MSC_VER 176370b324cSopenharmony_ci #ifdef __clang__ 177370b324cSopenharmony_ci #pragma GCC diagnostic ignored "-Wlanguage-extension-token" 178370b324cSopenharmony_ci #endif 179370b324cSopenharmony_ci __try 180370b324cSopenharmony_ci #endif 181370b324cSopenharmony_ci { 182370b324cSopenharmony_ci InitializeCriticalSection(p); 183370b324cSopenharmony_ci /* InitializeCriticalSectionAndSpinCount(p, 0); */ 184370b324cSopenharmony_ci } 185370b324cSopenharmony_ci #ifdef _MSC_VER 186370b324cSopenharmony_ci __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } 187370b324cSopenharmony_ci #endif 188370b324cSopenharmony_ci return 0; 189370b324cSopenharmony_ci} 190370b324cSopenharmony_ci 191370b324cSopenharmony_ci 192370b324cSopenharmony_ci 193370b324cSopenharmony_ci 194370b324cSopenharmony_ci#else // _WIN32 195370b324cSopenharmony_ci 196370b324cSopenharmony_ci// ---------- POSIX ---------- 197370b324cSopenharmony_ci 198370b324cSopenharmony_ci#ifndef __APPLE__ 199370b324cSopenharmony_ci#ifndef Z7_AFFINITY_DISABLE 200370b324cSopenharmony_ci// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET 201370b324cSopenharmony_ci// clang < 3.6 : unknown warning group '-Wreserved-id-macro' 202370b324cSopenharmony_ci// clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier" 203370b324cSopenharmony_ci// clang >= 13 : do not give warning 204370b324cSopenharmony_ci#if !defined(_GNU_SOURCE) 205370b324cSopenharmony_ci #if defined(__clang__) && (__clang_major__ >= 4) && (__clang_major__ <= 12) 206370b324cSopenharmony_ci #pragma GCC diagnostic ignored "-Wreserved-id-macro" 207370b324cSopenharmony_ci #endif 208370b324cSopenharmony_ci#define _GNU_SOURCE 209370b324cSopenharmony_ci#endif // !defined(_GNU_SOURCE) 210370b324cSopenharmony_ci#endif // Z7_AFFINITY_DISABLE 211370b324cSopenharmony_ci#endif // __APPLE__ 212370b324cSopenharmony_ci 213370b324cSopenharmony_ci#include "Threads.h" 214370b324cSopenharmony_ci 215370b324cSopenharmony_ci#include <errno.h> 216370b324cSopenharmony_ci#include <stdlib.h> 217370b324cSopenharmony_ci#include <string.h> 218370b324cSopenharmony_ci#ifdef Z7_AFFINITY_SUPPORTED 219370b324cSopenharmony_ci// #include <sched.h> 220370b324cSopenharmony_ci#endif 221370b324cSopenharmony_ci 222370b324cSopenharmony_ci 223370b324cSopenharmony_ci// #include <stdio.h> 224370b324cSopenharmony_ci// #define PRF(p) p 225370b324cSopenharmony_ci#define PRF(p) 226370b324cSopenharmony_ci#define Print(s) PRF(printf("\n%s\n", s);) 227370b324cSopenharmony_ci 228370b324cSopenharmony_ciWRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) 229370b324cSopenharmony_ci{ 230370b324cSopenharmony_ci // new thread in Posix probably inherits affinity from parrent thread 231370b324cSopenharmony_ci Print("Thread_Create_With_CpuSet") 232370b324cSopenharmony_ci 233370b324cSopenharmony_ci pthread_attr_t attr; 234370b324cSopenharmony_ci int ret; 235370b324cSopenharmony_ci // int ret2; 236370b324cSopenharmony_ci 237370b324cSopenharmony_ci p->_created = 0; 238370b324cSopenharmony_ci 239370b324cSopenharmony_ci RINOK(pthread_attr_init(&attr)) 240370b324cSopenharmony_ci 241370b324cSopenharmony_ci ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 242370b324cSopenharmony_ci 243370b324cSopenharmony_ci if (!ret) 244370b324cSopenharmony_ci { 245370b324cSopenharmony_ci if (cpuSet) 246370b324cSopenharmony_ci { 247370b324cSopenharmony_ci #ifdef Z7_AFFINITY_SUPPORTED 248370b324cSopenharmony_ci 249370b324cSopenharmony_ci /* 250370b324cSopenharmony_ci printf("\n affinity :"); 251370b324cSopenharmony_ci unsigned i; 252370b324cSopenharmony_ci for (i = 0; i < sizeof(*cpuSet) && i < 8; i++) 253370b324cSopenharmony_ci { 254370b324cSopenharmony_ci Byte b = *((const Byte *)cpuSet + i); 255370b324cSopenharmony_ci char temp[32]; 256370b324cSopenharmony_ci #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) 257370b324cSopenharmony_ci temp[0] = GET_HEX_CHAR((b & 0xF)); 258370b324cSopenharmony_ci temp[1] = GET_HEX_CHAR((b >> 4)); 259370b324cSopenharmony_ci // temp[0] = GET_HEX_CHAR((b >> 4)); // big-endian 260370b324cSopenharmony_ci // temp[1] = GET_HEX_CHAR((b & 0xF)); // big-endian 261370b324cSopenharmony_ci temp[2] = 0; 262370b324cSopenharmony_ci printf("%s", temp); 263370b324cSopenharmony_ci } 264370b324cSopenharmony_ci printf("\n"); 265370b324cSopenharmony_ci */ 266370b324cSopenharmony_ci 267370b324cSopenharmony_ci // ret2 = 268370b324cSopenharmony_ci pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); 269370b324cSopenharmony_ci // if (ret2) ret = ret2; 270370b324cSopenharmony_ci #endif 271370b324cSopenharmony_ci } 272370b324cSopenharmony_ci 273370b324cSopenharmony_ci ret = pthread_create(&p->_tid, &attr, func, param); 274370b324cSopenharmony_ci 275370b324cSopenharmony_ci if (!ret) 276370b324cSopenharmony_ci { 277370b324cSopenharmony_ci p->_created = 1; 278370b324cSopenharmony_ci /* 279370b324cSopenharmony_ci if (cpuSet) 280370b324cSopenharmony_ci { 281370b324cSopenharmony_ci // ret2 = 282370b324cSopenharmony_ci pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet); 283370b324cSopenharmony_ci // if (ret2) ret = ret2; 284370b324cSopenharmony_ci } 285370b324cSopenharmony_ci */ 286370b324cSopenharmony_ci } 287370b324cSopenharmony_ci } 288370b324cSopenharmony_ci // ret2 = 289370b324cSopenharmony_ci pthread_attr_destroy(&attr); 290370b324cSopenharmony_ci // if (ret2 != 0) ret = ret2; 291370b324cSopenharmony_ci return ret; 292370b324cSopenharmony_ci} 293370b324cSopenharmony_ci 294370b324cSopenharmony_ci 295370b324cSopenharmony_ciWRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) 296370b324cSopenharmony_ci{ 297370b324cSopenharmony_ci return Thread_Create_With_CpuSet(p, func, param, NULL); 298370b324cSopenharmony_ci} 299370b324cSopenharmony_ci 300370b324cSopenharmony_ci 301370b324cSopenharmony_ciWRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) 302370b324cSopenharmony_ci{ 303370b324cSopenharmony_ci Print("Thread_Create_WithAffinity") 304370b324cSopenharmony_ci CCpuSet cs; 305370b324cSopenharmony_ci unsigned i; 306370b324cSopenharmony_ci CpuSet_Zero(&cs); 307370b324cSopenharmony_ci for (i = 0; i < sizeof(affinity) * 8; i++) 308370b324cSopenharmony_ci { 309370b324cSopenharmony_ci if (affinity == 0) 310370b324cSopenharmony_ci break; 311370b324cSopenharmony_ci if (affinity & 1) 312370b324cSopenharmony_ci { 313370b324cSopenharmony_ci CpuSet_Set(&cs, i); 314370b324cSopenharmony_ci } 315370b324cSopenharmony_ci affinity >>= 1; 316370b324cSopenharmony_ci } 317370b324cSopenharmony_ci return Thread_Create_With_CpuSet(p, func, param, &cs); 318370b324cSopenharmony_ci} 319370b324cSopenharmony_ci 320370b324cSopenharmony_ci 321370b324cSopenharmony_ciWRes Thread_Close(CThread *p) 322370b324cSopenharmony_ci{ 323370b324cSopenharmony_ci // Print("Thread_Close") 324370b324cSopenharmony_ci int ret; 325370b324cSopenharmony_ci if (!p->_created) 326370b324cSopenharmony_ci return 0; 327370b324cSopenharmony_ci 328370b324cSopenharmony_ci ret = pthread_detach(p->_tid); 329370b324cSopenharmony_ci p->_tid = 0; 330370b324cSopenharmony_ci p->_created = 0; 331370b324cSopenharmony_ci return ret; 332370b324cSopenharmony_ci} 333370b324cSopenharmony_ci 334370b324cSopenharmony_ci 335370b324cSopenharmony_ciWRes Thread_Wait_Close(CThread *p) 336370b324cSopenharmony_ci{ 337370b324cSopenharmony_ci // Print("Thread_Wait_Close") 338370b324cSopenharmony_ci void *thread_return; 339370b324cSopenharmony_ci int ret; 340370b324cSopenharmony_ci if (!p->_created) 341370b324cSopenharmony_ci return EINVAL; 342370b324cSopenharmony_ci 343370b324cSopenharmony_ci ret = pthread_join(p->_tid, &thread_return); 344370b324cSopenharmony_ci // probably we can't use that (_tid) after pthread_join(), so we close thread here 345370b324cSopenharmony_ci p->_created = 0; 346370b324cSopenharmony_ci p->_tid = 0; 347370b324cSopenharmony_ci return ret; 348370b324cSopenharmony_ci} 349370b324cSopenharmony_ci 350370b324cSopenharmony_ci 351370b324cSopenharmony_ci 352370b324cSopenharmony_cistatic WRes Event_Create(CEvent *p, int manualReset, int signaled) 353370b324cSopenharmony_ci{ 354370b324cSopenharmony_ci RINOK(pthread_mutex_init(&p->_mutex, NULL)) 355370b324cSopenharmony_ci RINOK(pthread_cond_init(&p->_cond, NULL)) 356370b324cSopenharmony_ci p->_manual_reset = manualReset; 357370b324cSopenharmony_ci p->_state = (signaled ? True : False); 358370b324cSopenharmony_ci p->_created = 1; 359370b324cSopenharmony_ci return 0; 360370b324cSopenharmony_ci} 361370b324cSopenharmony_ci 362370b324cSopenharmony_ciWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) 363370b324cSopenharmony_ci { return Event_Create(p, True, signaled); } 364370b324cSopenharmony_ciWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) 365370b324cSopenharmony_ci { return ManualResetEvent_Create(p, 0); } 366370b324cSopenharmony_ciWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) 367370b324cSopenharmony_ci { return Event_Create(p, False, signaled); } 368370b324cSopenharmony_ciWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) 369370b324cSopenharmony_ci { return AutoResetEvent_Create(p, 0); } 370370b324cSopenharmony_ci 371370b324cSopenharmony_ci 372370b324cSopenharmony_ciWRes Event_Set(CEvent *p) 373370b324cSopenharmony_ci{ 374370b324cSopenharmony_ci RINOK(pthread_mutex_lock(&p->_mutex)) 375370b324cSopenharmony_ci p->_state = True; 376370b324cSopenharmony_ci int res1 = pthread_cond_broadcast(&p->_cond); 377370b324cSopenharmony_ci int res2 = pthread_mutex_unlock(&p->_mutex); 378370b324cSopenharmony_ci return (res2 ? res2 : res1); 379370b324cSopenharmony_ci} 380370b324cSopenharmony_ci 381370b324cSopenharmony_ciWRes Event_Reset(CEvent *p) 382370b324cSopenharmony_ci{ 383370b324cSopenharmony_ci RINOK(pthread_mutex_lock(&p->_mutex)) 384370b324cSopenharmony_ci p->_state = False; 385370b324cSopenharmony_ci return pthread_mutex_unlock(&p->_mutex); 386370b324cSopenharmony_ci} 387370b324cSopenharmony_ci 388370b324cSopenharmony_ciWRes Event_Wait(CEvent *p) 389370b324cSopenharmony_ci{ 390370b324cSopenharmony_ci RINOK(pthread_mutex_lock(&p->_mutex)) 391370b324cSopenharmony_ci while (p->_state == False) 392370b324cSopenharmony_ci { 393370b324cSopenharmony_ci // ETIMEDOUT 394370b324cSopenharmony_ci // ret = 395370b324cSopenharmony_ci pthread_cond_wait(&p->_cond, &p->_mutex); 396370b324cSopenharmony_ci // if (ret != 0) break; 397370b324cSopenharmony_ci } 398370b324cSopenharmony_ci if (p->_manual_reset == False) 399370b324cSopenharmony_ci { 400370b324cSopenharmony_ci p->_state = False; 401370b324cSopenharmony_ci } 402370b324cSopenharmony_ci return pthread_mutex_unlock(&p->_mutex); 403370b324cSopenharmony_ci} 404370b324cSopenharmony_ci 405370b324cSopenharmony_ciWRes Event_Close(CEvent *p) 406370b324cSopenharmony_ci{ 407370b324cSopenharmony_ci if (!p->_created) 408370b324cSopenharmony_ci return 0; 409370b324cSopenharmony_ci p->_created = 0; 410370b324cSopenharmony_ci { 411370b324cSopenharmony_ci int res1 = pthread_mutex_destroy(&p->_mutex); 412370b324cSopenharmony_ci int res2 = pthread_cond_destroy(&p->_cond); 413370b324cSopenharmony_ci return (res1 ? res1 : res2); 414370b324cSopenharmony_ci } 415370b324cSopenharmony_ci} 416370b324cSopenharmony_ci 417370b324cSopenharmony_ci 418370b324cSopenharmony_ciWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) 419370b324cSopenharmony_ci{ 420370b324cSopenharmony_ci if (initCount > maxCount || maxCount < 1) 421370b324cSopenharmony_ci return EINVAL; 422370b324cSopenharmony_ci RINOK(pthread_mutex_init(&p->_mutex, NULL)) 423370b324cSopenharmony_ci RINOK(pthread_cond_init(&p->_cond, NULL)) 424370b324cSopenharmony_ci p->_count = initCount; 425370b324cSopenharmony_ci p->_maxCount = maxCount; 426370b324cSopenharmony_ci p->_created = 1; 427370b324cSopenharmony_ci return 0; 428370b324cSopenharmony_ci} 429370b324cSopenharmony_ci 430370b324cSopenharmony_ci 431370b324cSopenharmony_ciWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) 432370b324cSopenharmony_ci{ 433370b324cSopenharmony_ci if (Semaphore_IsCreated(p)) 434370b324cSopenharmony_ci { 435370b324cSopenharmony_ci /* 436370b324cSopenharmony_ci WRes wres = Semaphore_Close(p); 437370b324cSopenharmony_ci if (wres != 0) 438370b324cSopenharmony_ci return wres; 439370b324cSopenharmony_ci */ 440370b324cSopenharmony_ci if (initCount > maxCount || maxCount < 1) 441370b324cSopenharmony_ci return EINVAL; 442370b324cSopenharmony_ci // return EINVAL; // for debug 443370b324cSopenharmony_ci p->_count = initCount; 444370b324cSopenharmony_ci p->_maxCount = maxCount; 445370b324cSopenharmony_ci return 0; 446370b324cSopenharmony_ci } 447370b324cSopenharmony_ci return Semaphore_Create(p, initCount, maxCount); 448370b324cSopenharmony_ci} 449370b324cSopenharmony_ci 450370b324cSopenharmony_ci 451370b324cSopenharmony_ciWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) 452370b324cSopenharmony_ci{ 453370b324cSopenharmony_ci UInt32 newCount; 454370b324cSopenharmony_ci int ret; 455370b324cSopenharmony_ci 456370b324cSopenharmony_ci if (releaseCount < 1) 457370b324cSopenharmony_ci return EINVAL; 458370b324cSopenharmony_ci 459370b324cSopenharmony_ci RINOK(pthread_mutex_lock(&p->_mutex)) 460370b324cSopenharmony_ci 461370b324cSopenharmony_ci newCount = p->_count + releaseCount; 462370b324cSopenharmony_ci if (newCount > p->_maxCount) 463370b324cSopenharmony_ci ret = ERROR_TOO_MANY_POSTS; // EINVAL; 464370b324cSopenharmony_ci else 465370b324cSopenharmony_ci { 466370b324cSopenharmony_ci p->_count = newCount; 467370b324cSopenharmony_ci ret = pthread_cond_broadcast(&p->_cond); 468370b324cSopenharmony_ci } 469370b324cSopenharmony_ci RINOK(pthread_mutex_unlock(&p->_mutex)) 470370b324cSopenharmony_ci return ret; 471370b324cSopenharmony_ci} 472370b324cSopenharmony_ci 473370b324cSopenharmony_ciWRes Semaphore_Wait(CSemaphore *p) 474370b324cSopenharmony_ci{ 475370b324cSopenharmony_ci RINOK(pthread_mutex_lock(&p->_mutex)) 476370b324cSopenharmony_ci while (p->_count < 1) 477370b324cSopenharmony_ci { 478370b324cSopenharmony_ci pthread_cond_wait(&p->_cond, &p->_mutex); 479370b324cSopenharmony_ci } 480370b324cSopenharmony_ci p->_count--; 481370b324cSopenharmony_ci return pthread_mutex_unlock(&p->_mutex); 482370b324cSopenharmony_ci} 483370b324cSopenharmony_ci 484370b324cSopenharmony_ciWRes Semaphore_Close(CSemaphore *p) 485370b324cSopenharmony_ci{ 486370b324cSopenharmony_ci if (!p->_created) 487370b324cSopenharmony_ci return 0; 488370b324cSopenharmony_ci p->_created = 0; 489370b324cSopenharmony_ci { 490370b324cSopenharmony_ci int res1 = pthread_mutex_destroy(&p->_mutex); 491370b324cSopenharmony_ci int res2 = pthread_cond_destroy(&p->_cond); 492370b324cSopenharmony_ci return (res1 ? res1 : res2); 493370b324cSopenharmony_ci } 494370b324cSopenharmony_ci} 495370b324cSopenharmony_ci 496370b324cSopenharmony_ci 497370b324cSopenharmony_ci 498370b324cSopenharmony_ciWRes CriticalSection_Init(CCriticalSection *p) 499370b324cSopenharmony_ci{ 500370b324cSopenharmony_ci // Print("CriticalSection_Init") 501370b324cSopenharmony_ci if (!p) 502370b324cSopenharmony_ci return EINTR; 503370b324cSopenharmony_ci return pthread_mutex_init(&p->_mutex, NULL); 504370b324cSopenharmony_ci} 505370b324cSopenharmony_ci 506370b324cSopenharmony_civoid CriticalSection_Enter(CCriticalSection *p) 507370b324cSopenharmony_ci{ 508370b324cSopenharmony_ci // Print("CriticalSection_Enter") 509370b324cSopenharmony_ci if (p) 510370b324cSopenharmony_ci { 511370b324cSopenharmony_ci // int ret = 512370b324cSopenharmony_ci pthread_mutex_lock(&p->_mutex); 513370b324cSopenharmony_ci } 514370b324cSopenharmony_ci} 515370b324cSopenharmony_ci 516370b324cSopenharmony_civoid CriticalSection_Leave(CCriticalSection *p) 517370b324cSopenharmony_ci{ 518370b324cSopenharmony_ci // Print("CriticalSection_Leave") 519370b324cSopenharmony_ci if (p) 520370b324cSopenharmony_ci { 521370b324cSopenharmony_ci // int ret = 522370b324cSopenharmony_ci pthread_mutex_unlock(&p->_mutex); 523370b324cSopenharmony_ci } 524370b324cSopenharmony_ci} 525370b324cSopenharmony_ci 526370b324cSopenharmony_civoid CriticalSection_Delete(CCriticalSection *p) 527370b324cSopenharmony_ci{ 528370b324cSopenharmony_ci // Print("CriticalSection_Delete") 529370b324cSopenharmony_ci if (p) 530370b324cSopenharmony_ci { 531370b324cSopenharmony_ci // int ret = 532370b324cSopenharmony_ci pthread_mutex_destroy(&p->_mutex); 533370b324cSopenharmony_ci } 534370b324cSopenharmony_ci} 535370b324cSopenharmony_ci 536370b324cSopenharmony_ciLONG InterlockedIncrement(LONG volatile *addend) 537370b324cSopenharmony_ci{ 538370b324cSopenharmony_ci // Print("InterlockedIncrement") 539370b324cSopenharmony_ci #ifdef USE_HACK_UNSAFE_ATOMIC 540370b324cSopenharmony_ci LONG val = *addend + 1; 541370b324cSopenharmony_ci *addend = val; 542370b324cSopenharmony_ci return val; 543370b324cSopenharmony_ci #else 544370b324cSopenharmony_ci 545370b324cSopenharmony_ci #if defined(__clang__) && (__clang_major__ >= 8) 546370b324cSopenharmony_ci #pragma GCC diagnostic ignored "-Watomic-implicit-seq-cst" 547370b324cSopenharmony_ci #endif 548370b324cSopenharmony_ci return __sync_add_and_fetch(addend, 1); 549370b324cSopenharmony_ci #endif 550370b324cSopenharmony_ci} 551370b324cSopenharmony_ci 552370b324cSopenharmony_ci#endif // _WIN32 553370b324cSopenharmony_ci 554370b324cSopenharmony_ciWRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) 555370b324cSopenharmony_ci{ 556370b324cSopenharmony_ci if (Event_IsCreated(p)) 557370b324cSopenharmony_ci return Event_Reset(p); 558370b324cSopenharmony_ci return AutoResetEvent_CreateNotSignaled(p); 559370b324cSopenharmony_ci} 560370b324cSopenharmony_ci 561370b324cSopenharmony_ci#undef PRF 562370b324cSopenharmony_ci#undef Print 563