diff options
Diffstat (limited to 'C/Threads.c')
-rw-r--r-- | C/Threads.c | 86 |
1 files changed, 54 insertions, 32 deletions
diff --git a/C/Threads.c b/C/Threads.c index 58eb90f..cf52bd3 100644 --- a/C/Threads.c +++ b/C/Threads.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Threads.c -- multithreading library | 1 | /* Threads.c -- multithreading library |
2 | 2021-12-21 : Igor Pavlov : Public domain */ | 2 | 2023-03-04 : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -11,9 +11,9 @@ | |||
11 | 11 | ||
12 | #include "Threads.h" | 12 | #include "Threads.h" |
13 | 13 | ||
14 | static WRes GetError() | 14 | static WRes GetError(void) |
15 | { | 15 | { |
16 | DWORD res = GetLastError(); | 16 | const DWORD res = GetLastError(); |
17 | return res ? (WRes)res : 1; | 17 | return res ? (WRes)res : 1; |
18 | } | 18 | } |
19 | 19 | ||
@@ -173,6 +173,9 @@ WRes CriticalSection_Init(CCriticalSection *p) | |||
173 | Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception | 173 | Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception |
174 | Windows Vista+ : no exceptions */ | 174 | Windows Vista+ : no exceptions */ |
175 | #ifdef _MSC_VER | 175 | #ifdef _MSC_VER |
176 | #ifdef __clang__ | ||
177 | #pragma GCC diagnostic ignored "-Wlanguage-extension-token" | ||
178 | #endif | ||
176 | __try | 179 | __try |
177 | #endif | 180 | #endif |
178 | { | 181 | { |
@@ -193,18 +196,26 @@ WRes CriticalSection_Init(CCriticalSection *p) | |||
193 | // ---------- POSIX ---------- | 196 | // ---------- POSIX ---------- |
194 | 197 | ||
195 | #ifndef __APPLE__ | 198 | #ifndef __APPLE__ |
196 | #ifndef _7ZIP_AFFINITY_DISABLE | 199 | #ifndef Z7_AFFINITY_DISABLE |
197 | // _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET | 200 | // _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET |
201 | // clang < 3.6 : unknown warning group '-Wreserved-id-macro' | ||
202 | // clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier" | ||
203 | // clang >= 13 : do not give warning | ||
204 | #if !defined(_GNU_SOURCE) | ||
205 | #if defined(__clang__) && (__clang_major__ >= 4) && (__clang_major__ <= 12) | ||
206 | #pragma GCC diagnostic ignored "-Wreserved-id-macro" | ||
207 | #endif | ||
198 | #define _GNU_SOURCE | 208 | #define _GNU_SOURCE |
199 | #endif | 209 | #endif // !defined(_GNU_SOURCE) |
200 | #endif | 210 | #endif // Z7_AFFINITY_DISABLE |
211 | #endif // __APPLE__ | ||
201 | 212 | ||
202 | #include "Threads.h" | 213 | #include "Threads.h" |
203 | 214 | ||
204 | #include <errno.h> | 215 | #include <errno.h> |
205 | #include <stdlib.h> | 216 | #include <stdlib.h> |
206 | #include <string.h> | 217 | #include <string.h> |
207 | #ifdef _7ZIP_AFFINITY_SUPPORTED | 218 | #ifdef Z7_AFFINITY_SUPPORTED |
208 | // #include <sched.h> | 219 | // #include <sched.h> |
209 | #endif | 220 | #endif |
210 | 221 | ||
@@ -212,15 +223,12 @@ WRes CriticalSection_Init(CCriticalSection *p) | |||
212 | // #include <stdio.h> | 223 | // #include <stdio.h> |
213 | // #define PRF(p) p | 224 | // #define PRF(p) p |
214 | #define PRF(p) | 225 | #define PRF(p) |
215 | 226 | #define Print(s) PRF(printf("\n%s\n", s);) | |
216 | #define Print(s) PRF(printf("\n%s\n", s)) | ||
217 | |||
218 | // #include <stdio.h> | ||
219 | 227 | ||
220 | WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) | 228 | WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) |
221 | { | 229 | { |
222 | // new thread in Posix probably inherits affinity from parrent thread | 230 | // new thread in Posix probably inherits affinity from parrent thread |
223 | Print("Thread_Create_With_CpuSet"); | 231 | Print("Thread_Create_With_CpuSet") |
224 | 232 | ||
225 | pthread_attr_t attr; | 233 | pthread_attr_t attr; |
226 | int ret; | 234 | int ret; |
@@ -228,7 +236,7 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, | |||
228 | 236 | ||
229 | p->_created = 0; | 237 | p->_created = 0; |
230 | 238 | ||
231 | RINOK(pthread_attr_init(&attr)); | 239 | RINOK(pthread_attr_init(&attr)) |
232 | 240 | ||
233 | ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | 241 | ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); |
234 | 242 | ||
@@ -236,7 +244,7 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, | |||
236 | { | 244 | { |
237 | if (cpuSet) | 245 | if (cpuSet) |
238 | { | 246 | { |
239 | #ifdef _7ZIP_AFFINITY_SUPPORTED | 247 | #ifdef Z7_AFFINITY_SUPPORTED |
240 | 248 | ||
241 | /* | 249 | /* |
242 | printf("\n affinity :"); | 250 | printf("\n affinity :"); |
@@ -292,7 +300,7 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) | |||
292 | 300 | ||
293 | WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) | 301 | WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) |
294 | { | 302 | { |
295 | Print("Thread_Create_WithAffinity"); | 303 | Print("Thread_Create_WithAffinity") |
296 | CCpuSet cs; | 304 | CCpuSet cs; |
297 | unsigned i; | 305 | unsigned i; |
298 | CpuSet_Zero(&cs); | 306 | CpuSet_Zero(&cs); |
@@ -312,7 +320,7 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param | |||
312 | 320 | ||
313 | WRes Thread_Close(CThread *p) | 321 | WRes Thread_Close(CThread *p) |
314 | { | 322 | { |
315 | // Print("Thread_Close"); | 323 | // Print("Thread_Close") |
316 | int ret; | 324 | int ret; |
317 | if (!p->_created) | 325 | if (!p->_created) |
318 | return 0; | 326 | return 0; |
@@ -326,7 +334,7 @@ WRes Thread_Close(CThread *p) | |||
326 | 334 | ||
327 | WRes Thread_Wait_Close(CThread *p) | 335 | WRes Thread_Wait_Close(CThread *p) |
328 | { | 336 | { |
329 | // Print("Thread_Wait_Close"); | 337 | // Print("Thread_Wait_Close") |
330 | void *thread_return; | 338 | void *thread_return; |
331 | int ret; | 339 | int ret; |
332 | if (!p->_created) | 340 | if (!p->_created) |
@@ -343,8 +351,8 @@ WRes Thread_Wait_Close(CThread *p) | |||
343 | 351 | ||
344 | static WRes Event_Create(CEvent *p, int manualReset, int signaled) | 352 | static WRes Event_Create(CEvent *p, int manualReset, int signaled) |
345 | { | 353 | { |
346 | RINOK(pthread_mutex_init(&p->_mutex, NULL)); | 354 | RINOK(pthread_mutex_init(&p->_mutex, NULL)) |
347 | RINOK(pthread_cond_init(&p->_cond, NULL)); | 355 | RINOK(pthread_cond_init(&p->_cond, NULL)) |
348 | p->_manual_reset = manualReset; | 356 | p->_manual_reset = manualReset; |
349 | p->_state = (signaled ? True : False); | 357 | p->_state = (signaled ? True : False); |
350 | p->_created = 1; | 358 | p->_created = 1; |
@@ -363,7 +371,7 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) | |||
363 | 371 | ||
364 | WRes Event_Set(CEvent *p) | 372 | WRes Event_Set(CEvent *p) |
365 | { | 373 | { |
366 | RINOK(pthread_mutex_lock(&p->_mutex)); | 374 | RINOK(pthread_mutex_lock(&p->_mutex)) |
367 | p->_state = True; | 375 | p->_state = True; |
368 | int res1 = pthread_cond_broadcast(&p->_cond); | 376 | int res1 = pthread_cond_broadcast(&p->_cond); |
369 | int res2 = pthread_mutex_unlock(&p->_mutex); | 377 | int res2 = pthread_mutex_unlock(&p->_mutex); |
@@ -372,14 +380,14 @@ WRes Event_Set(CEvent *p) | |||
372 | 380 | ||
373 | WRes Event_Reset(CEvent *p) | 381 | WRes Event_Reset(CEvent *p) |
374 | { | 382 | { |
375 | RINOK(pthread_mutex_lock(&p->_mutex)); | 383 | RINOK(pthread_mutex_lock(&p->_mutex)) |
376 | p->_state = False; | 384 | p->_state = False; |
377 | return pthread_mutex_unlock(&p->_mutex); | 385 | return pthread_mutex_unlock(&p->_mutex); |
378 | } | 386 | } |
379 | 387 | ||
380 | WRes Event_Wait(CEvent *p) | 388 | WRes Event_Wait(CEvent *p) |
381 | { | 389 | { |
382 | RINOK(pthread_mutex_lock(&p->_mutex)); | 390 | RINOK(pthread_mutex_lock(&p->_mutex)) |
383 | while (p->_state == False) | 391 | while (p->_state == False) |
384 | { | 392 | { |
385 | // ETIMEDOUT | 393 | // ETIMEDOUT |
@@ -411,8 +419,8 @@ WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) | |||
411 | { | 419 | { |
412 | if (initCount > maxCount || maxCount < 1) | 420 | if (initCount > maxCount || maxCount < 1) |
413 | return EINVAL; | 421 | return EINVAL; |
414 | RINOK(pthread_mutex_init(&p->_mutex, NULL)); | 422 | RINOK(pthread_mutex_init(&p->_mutex, NULL)) |
415 | RINOK(pthread_cond_init(&p->_cond, NULL)); | 423 | RINOK(pthread_cond_init(&p->_cond, NULL)) |
416 | p->_count = initCount; | 424 | p->_count = initCount; |
417 | p->_maxCount = maxCount; | 425 | p->_maxCount = maxCount; |
418 | p->_created = 1; | 426 | p->_created = 1; |
@@ -448,7 +456,7 @@ WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) | |||
448 | if (releaseCount < 1) | 456 | if (releaseCount < 1) |
449 | return EINVAL; | 457 | return EINVAL; |
450 | 458 | ||
451 | RINOK(pthread_mutex_lock(&p->_mutex)); | 459 | RINOK(pthread_mutex_lock(&p->_mutex)) |
452 | 460 | ||
453 | newCount = p->_count + releaseCount; | 461 | newCount = p->_count + releaseCount; |
454 | if (newCount > p->_maxCount) | 462 | if (newCount > p->_maxCount) |
@@ -458,13 +466,13 @@ WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) | |||
458 | p->_count = newCount; | 466 | p->_count = newCount; |
459 | ret = pthread_cond_broadcast(&p->_cond); | 467 | ret = pthread_cond_broadcast(&p->_cond); |
460 | } | 468 | } |
461 | RINOK(pthread_mutex_unlock(&p->_mutex)); | 469 | RINOK(pthread_mutex_unlock(&p->_mutex)) |
462 | return ret; | 470 | return ret; |
463 | } | 471 | } |
464 | 472 | ||
465 | WRes Semaphore_Wait(CSemaphore *p) | 473 | WRes Semaphore_Wait(CSemaphore *p) |
466 | { | 474 | { |
467 | RINOK(pthread_mutex_lock(&p->_mutex)); | 475 | RINOK(pthread_mutex_lock(&p->_mutex)) |
468 | while (p->_count < 1) | 476 | while (p->_count < 1) |
469 | { | 477 | { |
470 | pthread_cond_wait(&p->_cond, &p->_mutex); | 478 | pthread_cond_wait(&p->_cond, &p->_mutex); |
@@ -489,7 +497,7 @@ WRes Semaphore_Close(CSemaphore *p) | |||
489 | 497 | ||
490 | WRes CriticalSection_Init(CCriticalSection *p) | 498 | WRes CriticalSection_Init(CCriticalSection *p) |
491 | { | 499 | { |
492 | // Print("CriticalSection_Init"); | 500 | // Print("CriticalSection_Init") |
493 | if (!p) | 501 | if (!p) |
494 | return EINTR; | 502 | return EINTR; |
495 | return pthread_mutex_init(&p->_mutex, NULL); | 503 | return pthread_mutex_init(&p->_mutex, NULL); |
@@ -497,7 +505,7 @@ WRes CriticalSection_Init(CCriticalSection *p) | |||
497 | 505 | ||
498 | void CriticalSection_Enter(CCriticalSection *p) | 506 | void CriticalSection_Enter(CCriticalSection *p) |
499 | { | 507 | { |
500 | // Print("CriticalSection_Enter"); | 508 | // Print("CriticalSection_Enter") |
501 | if (p) | 509 | if (p) |
502 | { | 510 | { |
503 | // int ret = | 511 | // int ret = |
@@ -507,7 +515,7 @@ void CriticalSection_Enter(CCriticalSection *p) | |||
507 | 515 | ||
508 | void CriticalSection_Leave(CCriticalSection *p) | 516 | void CriticalSection_Leave(CCriticalSection *p) |
509 | { | 517 | { |
510 | // Print("CriticalSection_Leave"); | 518 | // Print("CriticalSection_Leave") |
511 | if (p) | 519 | if (p) |
512 | { | 520 | { |
513 | // int ret = | 521 | // int ret = |
@@ -517,7 +525,7 @@ void CriticalSection_Leave(CCriticalSection *p) | |||
517 | 525 | ||
518 | void CriticalSection_Delete(CCriticalSection *p) | 526 | void CriticalSection_Delete(CCriticalSection *p) |
519 | { | 527 | { |
520 | // Print("CriticalSection_Delete"); | 528 | // Print("CriticalSection_Delete") |
521 | if (p) | 529 | if (p) |
522 | { | 530 | { |
523 | // int ret = | 531 | // int ret = |
@@ -527,14 +535,28 @@ void CriticalSection_Delete(CCriticalSection *p) | |||
527 | 535 | ||
528 | LONG InterlockedIncrement(LONG volatile *addend) | 536 | LONG InterlockedIncrement(LONG volatile *addend) |
529 | { | 537 | { |
530 | // Print("InterlockedIncrement"); | 538 | // Print("InterlockedIncrement") |
531 | #ifdef USE_HACK_UNSAFE_ATOMIC | 539 | #ifdef USE_HACK_UNSAFE_ATOMIC |
532 | LONG val = *addend + 1; | 540 | LONG val = *addend + 1; |
533 | *addend = val; | 541 | *addend = val; |
534 | return val; | 542 | return val; |
535 | #else | 543 | #else |
544 | |||
545 | #if defined(__clang__) && (__clang_major__ >= 8) | ||
546 | #pragma GCC diagnostic ignored "-Watomic-implicit-seq-cst" | ||
547 | #endif | ||
536 | return __sync_add_and_fetch(addend, 1); | 548 | return __sync_add_and_fetch(addend, 1); |
537 | #endif | 549 | #endif |
538 | } | 550 | } |
539 | 551 | ||
540 | #endif // _WIN32 | 552 | #endif // _WIN32 |
553 | |||
554 | WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) | ||
555 | { | ||
556 | if (Event_IsCreated(p)) | ||
557 | return Event_Reset(p); | ||
558 | return AutoResetEvent_CreateNotSignaled(p); | ||
559 | } | ||
560 | |||
561 | #undef PRF | ||
562 | #undef Print | ||