aboutsummaryrefslogtreecommitdiff
path: root/src/threading.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2022-02-07 08:56:39 +0100
committerBenoit Germain <bnt.germain@gmail.com>2022-02-07 08:56:39 +0100
commit621fb024b5f887ef9e81e2f28bf087386f5300e1 (patch)
tree3ed681e2db07a0516904b2cda4e7144c714d19e0 /src/threading.c
parent00c84df3adc0b295ef20bc35bc8df9632e3b93e7 (diff)
downloadlanes-621fb024b5f887ef9e81e2f28bf087386f5300e1.tar.gz
lanes-621fb024b5f887ef9e81e2f28bf087386f5300e1.tar.bz2
lanes-621fb024b5f887ef9e81e2f28bf087386f5300e1.zip
Changed all indentations to all whitespaces
Tabs mess up alignment of stack contents comments, so I'm done with them.
Diffstat (limited to 'src/threading.c')
-rw-r--r--src/threading.c910
1 files changed, 455 insertions, 455 deletions
diff --git a/src/threading.c b/src/threading.c
index 84a6fcd..183dc87 100644
--- a/src/threading.c
+++ b/src/threading.c
@@ -104,16 +104,16 @@ THE SOFTWARE.
104static void FAIL( char const* funcname, int rc) 104static void FAIL( char const* funcname, int rc)
105{ 105{
106#if defined( PLATFORM_XBOX) 106#if defined( PLATFORM_XBOX)
107 fprintf( stderr, "%s() failed! (%d)\n", funcname, rc ); 107 fprintf( stderr, "%s() failed! (%d)\n", funcname, rc );
108#else // PLATFORM_XBOX 108#else // PLATFORM_XBOX
109 char buf[256]; 109 char buf[256];
110 FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL); 110 FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
111 fprintf( stderr, "%s() failed! [GetLastError() -> %d] '%s'", funcname, rc, buf); 111 fprintf( stderr, "%s() failed! [GetLastError() -> %d] '%s'", funcname, rc, buf);
112#endif // PLATFORM_XBOX 112#endif // PLATFORM_XBOX
113#ifdef _MSC_VER 113#ifdef _MSC_VER
114 __debugbreak(); // give a chance to the debugger! 114 __debugbreak(); // give a chance to the debugger!
115#endif // _MSC_VER 115#endif // _MSC_VER
116 abort(); 116 abort();
117} 117}
118#endif // win32 build 118#endif // win32 build
119 119
@@ -278,14 +278,14 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) {
278 if (!CloseHandle(*ref)) FAIL( "CloseHandle (mutex)", GetLastError() ); 278 if (!CloseHandle(*ref)) FAIL( "CloseHandle (mutex)", GetLastError() );
279 *ref= NULL; 279 *ref= NULL;
280 } 280 }
281 void MUTEX_LOCK( MUTEX_T *ref ) 281 void MUTEX_LOCK( MUTEX_T *ref )
282 { 282 {
283 DWORD rc = WaitForSingleObject( *ref, INFINITE); 283 DWORD rc = WaitForSingleObject( *ref, INFINITE);
284 // ERROR_WAIT_NO_CHILDREN means a thread was killed (lane terminated because of error raised during a linda transfer for example) while having grabbed this mutex 284 // ERROR_WAIT_NO_CHILDREN means a thread was killed (lane terminated because of error raised during a linda transfer for example) while having grabbed this mutex
285 // this is not a big problem as we will grab it just the same, so ignore this particular error 285 // this is not a big problem as we will grab it just the same, so ignore this particular error
286 if( rc != 0 && rc != ERROR_WAIT_NO_CHILDREN) 286 if( rc != 0 && rc != ERROR_WAIT_NO_CHILDREN)
287 FAIL( "WaitForSingleObject", (rc == WAIT_FAILED) ? GetLastError() : rc); 287 FAIL( "WaitForSingleObject", (rc == WAIT_FAILED) ? GetLastError() : rc);
288 } 288 }
289 void MUTEX_UNLOCK( MUTEX_T *ref ) { 289 void MUTEX_UNLOCK( MUTEX_T *ref ) {
290 if (!ReleaseMutex(*ref)) 290 if (!ReleaseMutex(*ref))
291 FAIL( "ReleaseMutex", GetLastError() ); 291 FAIL( "ReleaseMutex", GetLastError() );
@@ -294,13 +294,13 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) {
294 294
295static int const gs_prio_remap[] = 295static int const gs_prio_remap[] =
296{ 296{
297 THREAD_PRIORITY_IDLE, 297 THREAD_PRIORITY_IDLE,
298 THREAD_PRIORITY_LOWEST, 298 THREAD_PRIORITY_LOWEST,
299 THREAD_PRIORITY_BELOW_NORMAL, 299 THREAD_PRIORITY_BELOW_NORMAL,
300 THREAD_PRIORITY_NORMAL, 300 THREAD_PRIORITY_NORMAL,
301 THREAD_PRIORITY_ABOVE_NORMAL, 301 THREAD_PRIORITY_ABOVE_NORMAL,
302 THREAD_PRIORITY_HIGHEST, 302 THREAD_PRIORITY_HIGHEST,
303 THREAD_PRIORITY_TIME_CRITICAL 303 THREAD_PRIORITY_TIME_CRITICAL
304}; 304};
305 305
306/* MSDN: "If you would like to use the CRT in ThreadProc, use the 306/* MSDN: "If you would like to use the CRT in ThreadProc, use the
@@ -310,43 +310,43 @@ MSDN: "you can create at most 2028 threads"
310// Note: Visual C++ requires '__stdcall' where it is 310// Note: Visual C++ requires '__stdcall' where it is
311void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (__stdcall *func)( void*), void* data, int prio /* -3..+3 */) 311void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (__stdcall *func)( void*), void* data, int prio /* -3..+3 */)
312{ 312{
313 HANDLE h = (HANDLE) _beginthreadex( NULL, // security 313 HANDLE h = (HANDLE) _beginthreadex( NULL, // security
314 _THREAD_STACK_SIZE, 314 _THREAD_STACK_SIZE,
315 func, 315 func,
316 data, 316 data,
317 0, // flags (0/CREATE_SUSPENDED) 317 0, // flags (0/CREATE_SUSPENDED)
318 NULL // thread id (not used) 318 NULL // thread id (not used)
319 ); 319 );
320 320
321 if( h == NULL) // _beginthreadex returns 0L on failure instead of -1L (like _beginthread) 321 if( h == NULL) // _beginthreadex returns 0L on failure instead of -1L (like _beginthread)
322 { 322 {
323 FAIL( "CreateThread", GetLastError()); 323 FAIL( "CreateThread", GetLastError());
324 } 324 }
325 325
326 if (!SetThreadPriority( h, gs_prio_remap[prio + 3])) 326 if (!SetThreadPriority( h, gs_prio_remap[prio + 3]))
327 { 327 {
328 FAIL( "SetThreadPriority", GetLastError()); 328 FAIL( "SetThreadPriority", GetLastError());
329 } 329 }
330 330
331 *ref = h; 331 *ref = h;
332} 332}
333 333
334 334
335void THREAD_SET_PRIORITY( int prio) 335void THREAD_SET_PRIORITY( int prio)
336{ 336{
337 // prio range [-3,+3] was checked by the caller 337 // prio range [-3,+3] was checked by the caller
338 if (!SetThreadPriority( GetCurrentThread(), gs_prio_remap[prio + 3])) 338 if (!SetThreadPriority( GetCurrentThread(), gs_prio_remap[prio + 3]))
339 { 339 {
340 FAIL( "THREAD_SET_PRIORITY", GetLastError()); 340 FAIL( "THREAD_SET_PRIORITY", GetLastError());
341 } 341 }
342} 342}
343 343
344void THREAD_SET_AFFINITY( unsigned int aff) 344void THREAD_SET_AFFINITY( unsigned int aff)
345{ 345{
346 if( !SetThreadAffinityMask( GetCurrentThread(), aff)) 346 if( !SetThreadAffinityMask( GetCurrentThread(), aff))
347 { 347 {
348 FAIL( "THREAD_SET_AFFINITY", GetLastError()); 348 FAIL( "THREAD_SET_AFFINITY", GetLastError());
349 } 349 }
350} 350}
351 351
352bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) 352bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
@@ -366,200 +366,200 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
366 return TRUE; 366 return TRUE;
367 } 367 }
368 // 368 //
369 void THREAD_KILL( THREAD_T *ref ) 369 void THREAD_KILL( THREAD_T *ref )
370 { 370 {
371 // nonexistent on Xbox360, simply disable until a better solution is found 371 // nonexistent on Xbox360, simply disable until a better solution is found
372 #if !defined( PLATFORM_XBOX) 372 #if !defined( PLATFORM_XBOX)
373 // in theory no-one should call this as it is very dangerous (memory and mutex leaks, no notification of DLLs, etc.) 373 // in theory no-one should call this as it is very dangerous (memory and mutex leaks, no notification of DLLs, etc.)
374 if (!TerminateThread( *ref, 0 )) FAIL("TerminateThread", GetLastError()); 374 if (!TerminateThread( *ref, 0 )) FAIL("TerminateThread", GetLastError());
375 #endif // PLATFORM_XBOX 375 #endif // PLATFORM_XBOX
376 *ref= NULL; 376 *ref= NULL;
377 } 377 }
378 378
379 void THREAD_MAKE_ASYNCH_CANCELLABLE() {} // nothing to do for windows threads, we can cancel them anytime we want 379 void THREAD_MAKE_ASYNCH_CANCELLABLE() {} // nothing to do for windows threads, we can cancel them anytime we want
380 380
381#if !defined __GNUC__ 381#if !defined __GNUC__
382 //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx 382 //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
383 #define MS_VC_EXCEPTION 0x406D1388 383 #define MS_VC_EXCEPTION 0x406D1388
384 #pragma pack(push,8) 384 #pragma pack(push,8)
385 typedef struct tagTHREADNAME_INFO 385 typedef struct tagTHREADNAME_INFO
386 { 386 {
387 DWORD dwType; // Must be 0x1000. 387 DWORD dwType; // Must be 0x1000.
388 LPCSTR szName; // Pointer to name (in user addr space). 388 LPCSTR szName; // Pointer to name (in user addr space).
389 DWORD dwThreadID; // Thread ID (-1=caller thread). 389 DWORD dwThreadID; // Thread ID (-1=caller thread).
390 DWORD dwFlags; // Reserved for future use, must be zero. 390 DWORD dwFlags; // Reserved for future use, must be zero.
391 } THREADNAME_INFO; 391 } THREADNAME_INFO;
392 #pragma pack(pop) 392 #pragma pack(pop)
393#endif // !__GNUC__ 393#endif // !__GNUC__
394 394
395 void THREAD_SETNAME( char const* _name) 395 void THREAD_SETNAME( char const* _name)
396 { 396 {
397#if !defined __GNUC__ 397#if !defined __GNUC__
398 THREADNAME_INFO info; 398 THREADNAME_INFO info;
399 info.dwType = 0x1000; 399 info.dwType = 0x1000;
400 info.szName = _name; 400 info.szName = _name;
401 info.dwThreadID = GetCurrentThreadId(); 401 info.dwThreadID = GetCurrentThreadId();
402 info.dwFlags = 0; 402 info.dwFlags = 0;
403 403
404 __try 404 __try
405 { 405 {
406 RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); 406 RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
407 } 407 }
408 __except(EXCEPTION_EXECUTE_HANDLER) 408 __except(EXCEPTION_EXECUTE_HANDLER)
409 { 409 {
410 } 410 }
411#endif // !__GNUC__ 411#endif // !__GNUC__
412 } 412 }
413 413
414#if _WIN32_WINNT < 0x0600 // CONDITION_VARIABLE aren't available 414#if _WIN32_WINNT < 0x0600 // CONDITION_VARIABLE aren't available
415 415
416 void SIGNAL_INIT( SIGNAL_T* ref) 416 void SIGNAL_INIT( SIGNAL_T* ref)
417 { 417 {
418 InitializeCriticalSection( &ref->signalCS); 418 InitializeCriticalSection( &ref->signalCS);
419 InitializeCriticalSection( &ref->countCS); 419 InitializeCriticalSection( &ref->countCS);
420 if( 0 == (ref->waitEvent = CreateEvent( 0, TRUE, FALSE, 0))) // manual-reset 420 if( 0 == (ref->waitEvent = CreateEvent( 0, TRUE, FALSE, 0))) // manual-reset
421 FAIL( "CreateEvent", GetLastError()); 421 FAIL( "CreateEvent", GetLastError());
422 if( 0 == (ref->waitDoneEvent = CreateEvent( 0, FALSE, FALSE, 0))) // auto-reset 422 if( 0 == (ref->waitDoneEvent = CreateEvent( 0, FALSE, FALSE, 0))) // auto-reset
423 FAIL( "CreateEvent", GetLastError()); 423 FAIL( "CreateEvent", GetLastError());
424 ref->waitersCount = 0; 424 ref->waitersCount = 0;
425 } 425 }
426 426
427 void SIGNAL_FREE( SIGNAL_T* ref) 427 void SIGNAL_FREE( SIGNAL_T* ref)
428 { 428 {
429 CloseHandle( ref->waitDoneEvent); 429 CloseHandle( ref->waitDoneEvent);
430 CloseHandle( ref->waitEvent); 430 CloseHandle( ref->waitEvent);
431 DeleteCriticalSection( &ref->countCS); 431 DeleteCriticalSection( &ref->countCS);
432 DeleteCriticalSection( &ref->signalCS); 432 DeleteCriticalSection( &ref->signalCS);
433 } 433 }
434 434
435 bool_t SIGNAL_WAIT( SIGNAL_T* ref, MUTEX_T* mu_ref, time_d abs_secs) 435 bool_t SIGNAL_WAIT( SIGNAL_T* ref, MUTEX_T* mu_ref, time_d abs_secs)
436 { 436 {
437 DWORD errc; 437 DWORD errc;
438 DWORD ms; 438 DWORD ms;
439 439
440 if( abs_secs < 0.0) 440 if( abs_secs < 0.0)
441 ms = INFINITE; 441 ms = INFINITE;
442 else if( abs_secs == 0.0) 442 else if( abs_secs == 0.0)
443 ms = 0; 443 ms = 0;
444 else 444 else
445 { 445 {
446 time_d msd = (abs_secs - now_secs()) * 1000.0 + 0.5; 446 time_d msd = (abs_secs - now_secs()) * 1000.0 + 0.5;
447 // If the time already passed, still try once (ms==0). A short timeout 447 // If the time already passed, still try once (ms==0). A short timeout
448 // may have turned negative or 0 because of the two time samples done. 448 // may have turned negative or 0 because of the two time samples done.
449 ms = msd <= 0.0 ? 0 : (DWORD)msd; 449 ms = msd <= 0.0 ? 0 : (DWORD)msd;
450 } 450 }
451 451
452 EnterCriticalSection( &ref->signalCS); 452 EnterCriticalSection( &ref->signalCS);
453 EnterCriticalSection( &ref->countCS); 453 EnterCriticalSection( &ref->countCS);
454 ++ ref->waitersCount; 454 ++ ref->waitersCount;
455 LeaveCriticalSection( &ref->countCS); 455 LeaveCriticalSection( &ref->countCS);
456 LeaveCriticalSection( &ref->signalCS); 456 LeaveCriticalSection( &ref->signalCS);
457 457
458 errc = SignalObjectAndWait( *mu_ref, ref->waitEvent, ms, FALSE); 458 errc = SignalObjectAndWait( *mu_ref, ref->waitEvent, ms, FALSE);
459 459
460 EnterCriticalSection( &ref->countCS); 460 EnterCriticalSection( &ref->countCS);
461 if( 0 == -- ref->waitersCount) 461 if( 0 == -- ref->waitersCount)
462 { 462 {
463 // we're the last one leaving... 463 // we're the last one leaving...
464 ResetEvent( ref->waitEvent); 464 ResetEvent( ref->waitEvent);
465 SetEvent( ref->waitDoneEvent); 465 SetEvent( ref->waitDoneEvent);
466 } 466 }
467 LeaveCriticalSection( &ref->countCS); 467 LeaveCriticalSection( &ref->countCS);
468 MUTEX_LOCK( mu_ref); 468 MUTEX_LOCK( mu_ref);
469 469
470 switch( errc) 470 switch( errc)
471 { 471 {
472 case WAIT_TIMEOUT: 472 case WAIT_TIMEOUT:
473 return FALSE; 473 return FALSE;
474 case WAIT_OBJECT_0: 474 case WAIT_OBJECT_0:
475 return TRUE; 475 return TRUE;
476 } 476 }
477 477
478 FAIL( "SignalObjectAndWait", GetLastError()); 478 FAIL( "SignalObjectAndWait", GetLastError());
479 return FALSE; 479 return FALSE;
480 } 480 }
481 481
482 void SIGNAL_ALL( SIGNAL_T* ref) 482 void SIGNAL_ALL( SIGNAL_T* ref)
483 { 483 {
484 DWORD errc = WAIT_OBJECT_0; 484 DWORD errc = WAIT_OBJECT_0;
485 485
486 EnterCriticalSection( &ref->signalCS); 486 EnterCriticalSection( &ref->signalCS);
487 EnterCriticalSection( &ref->countCS); 487 EnterCriticalSection( &ref->countCS);
488 488
489 if( ref->waitersCount > 0) 489 if( ref->waitersCount > 0)
490 { 490 {
491 ResetEvent( ref->waitDoneEvent); 491 ResetEvent( ref->waitDoneEvent);
492 SetEvent( ref->waitEvent); 492 SetEvent( ref->waitEvent);
493 LeaveCriticalSection( &ref->countCS); 493 LeaveCriticalSection( &ref->countCS);
494 errc = WaitForSingleObject( ref->waitDoneEvent, INFINITE); 494 errc = WaitForSingleObject( ref->waitDoneEvent, INFINITE);
495 } 495 }
496 else 496 else
497 { 497 {
498 LeaveCriticalSection( &ref->countCS); 498 LeaveCriticalSection( &ref->countCS);
499 } 499 }
500 500
501 LeaveCriticalSection( &ref->signalCS); 501 LeaveCriticalSection( &ref->signalCS);
502 502
503 if( WAIT_OBJECT_0 != errc) 503 if( WAIT_OBJECT_0 != errc)
504 FAIL( "WaitForSingleObject", GetLastError()); 504 FAIL( "WaitForSingleObject", GetLastError());
505 } 505 }
506 506
507#else // CONDITION_VARIABLE are available, use them 507#else // CONDITION_VARIABLE are available, use them
508 508
509 // 509 //
510 void SIGNAL_INIT( SIGNAL_T *ref ) 510 void SIGNAL_INIT( SIGNAL_T *ref )
511 { 511 {
512 InitializeConditionVariable( ref); 512 InitializeConditionVariable( ref);
513 } 513 }
514 514
515 void SIGNAL_FREE( SIGNAL_T *ref ) 515 void SIGNAL_FREE( SIGNAL_T *ref )
516 { 516 {
517 // nothing to do 517 // nothing to do
518 (void)ref; 518 (void)ref;
519 } 519 }
520 520
521 bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu_ref, time_d abs_secs) 521 bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu_ref, time_d abs_secs)
522 { 522 {
523 long ms; 523 long ms;
524 524
525 if( abs_secs < 0.0) 525 if( abs_secs < 0.0)
526 ms = INFINITE; 526 ms = INFINITE;
527 else if( abs_secs == 0.0) 527 else if( abs_secs == 0.0)
528 ms = 0; 528 ms = 0;
529 else 529 else
530 { 530 {
531 ms = (long) ((abs_secs - now_secs())*1000.0 + 0.5); 531 ms = (long) ((abs_secs - now_secs())*1000.0 + 0.5);
532 532
533 // If the time already passed, still try once (ms==0). A short timeout 533 // If the time already passed, still try once (ms==0). A short timeout
534 // may have turned negative or 0 because of the two time samples done. 534 // may have turned negative or 0 because of the two time samples done.
535 // 535 //
536 if( ms < 0) 536 if( ms < 0)
537 ms = 0; 537 ms = 0;
538 } 538 }
539 539
540 if( !SleepConditionVariableCS( ref, mu_ref, ms)) 540 if( !SleepConditionVariableCS( ref, mu_ref, ms))
541 { 541 {
542 if( GetLastError() == ERROR_TIMEOUT) 542 if( GetLastError() == ERROR_TIMEOUT)
543 { 543 {
544 return FALSE; 544 return FALSE;
545 } 545 }
546 else 546 else
547 { 547 {
548 FAIL( "SleepConditionVariableCS", GetLastError()); 548 FAIL( "SleepConditionVariableCS", GetLastError());
549 } 549 }
550 } 550 }
551 return TRUE; 551 return TRUE;
552 } 552 }
553 553
554 void SIGNAL_ONE( SIGNAL_T *ref ) 554 void SIGNAL_ONE( SIGNAL_T *ref )
555 { 555 {
556 WakeConditionVariable( ref); 556 WakeConditionVariable( ref);
557 } 557 }
558 558
559 void SIGNAL_ALL( SIGNAL_T *ref ) 559 void SIGNAL_ALL( SIGNAL_T *ref )
560 { 560 {
561 WakeAllConditionVariable( ref); 561 WakeAllConditionVariable( ref);
562 } 562 }
563 563
564#endif // CONDITION_VARIABLE are available 564#endif // CONDITION_VARIABLE are available
565 565
@@ -574,20 +574,20 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
574 574
575# if (defined(__MINGW32__) || defined(__MINGW64__)) && defined pthread_attr_setschedpolicy 575# if (defined(__MINGW32__) || defined(__MINGW64__)) && defined pthread_attr_setschedpolicy
576# if pthread_attr_setschedpolicy( A, S) == ENOTSUP 576# if pthread_attr_setschedpolicy( A, S) == ENOTSUP
577 // from the mingw-w64 team: 577 // from the mingw-w64 team:
578 // Well, we support pthread_setschedparam by which you can specify 578 // Well, we support pthread_setschedparam by which you can specify
579 // threading-policy. Nevertheless, yes we lack this function. In 579 // threading-policy. Nevertheless, yes we lack this function. In
580 // general its implementation is pretty much trivial, as on Win32 target 580 // general its implementation is pretty much trivial, as on Win32 target
581 // just SCHED_OTHER can be supported. 581 // just SCHED_OTHER can be supported.
582 #undef pthread_attr_setschedpolicy 582 #undef pthread_attr_setschedpolicy
583 static int pthread_attr_setschedpolicy( pthread_attr_t* attr, int policy) 583 static int pthread_attr_setschedpolicy( pthread_attr_t* attr, int policy)
584 { 584 {
585 if( policy != SCHED_OTHER) 585 if( policy != SCHED_OTHER)
586 { 586 {
587 return ENOTSUP; 587 return ENOTSUP;
588 } 588 }
589 return 0; 589 return 0;
590 } 590 }
591# endif // pthread_attr_setschedpolicy() 591# endif // pthread_attr_setschedpolicy()
592# endif // defined(__MINGW32__) || defined(__MINGW64__) 592# endif // defined(__MINGW32__) || defined(__MINGW64__)
593 593
@@ -646,94 +646,94 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
646// array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range 646// array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range
647static int const gs_prio_remap[] = 647static int const gs_prio_remap[] =
648{ 648{
649 // NB: PThreads priority handling is about as twisty as one can get it 649 // NB: PThreads priority handling is about as twisty as one can get it
650 // (and then some). DON*T TRUST ANYTHING YOU READ ON THE NET!!! 650 // (and then some). DON*T TRUST ANYTHING YOU READ ON THE NET!!!
651 651
652 //--- 652 //---
653 // "Select the scheduling policy for the thread: one of SCHED_OTHER 653 // "Select the scheduling policy for the thread: one of SCHED_OTHER
654 // (regular, non-real-time scheduling), SCHED_RR (real-time, 654 // (regular, non-real-time scheduling), SCHED_RR (real-time,
655 // round-robin) or SCHED_FIFO (real-time, first-in first-out)." 655 // round-robin) or SCHED_FIFO (real-time, first-in first-out)."
656 // 656 //
657 // "Using the RR policy ensures that all threads having the same 657 // "Using the RR policy ensures that all threads having the same
658 // priority level will be scheduled equally, regardless of their activity." 658 // priority level will be scheduled equally, regardless of their activity."
659 // 659 //
660 // "For SCHED_FIFO and SCHED_RR, the only required member of the 660 // "For SCHED_FIFO and SCHED_RR, the only required member of the
661 // sched_param structure is the priority sched_priority. For SCHED_OTHER, 661 // sched_param structure is the priority sched_priority. For SCHED_OTHER,
662 // the affected scheduling parameters are implementation-defined." 662 // the affected scheduling parameters are implementation-defined."
663 // 663 //
664 // "The priority of a thread is specified as a delta which is added to 664 // "The priority of a thread is specified as a delta which is added to
665 // the priority of the process." 665 // the priority of the process."
666 // 666 //
667 // ".. priority is an integer value, in the range from 1 to 127. 667 // ".. priority is an integer value, in the range from 1 to 127.
668 // 1 is the least-favored priority, 127 is the most-favored." 668 // 1 is the least-favored priority, 127 is the most-favored."
669 // 669 //
670 // "Priority level 0 cannot be used: it is reserved for the system." 670 // "Priority level 0 cannot be used: it is reserved for the system."
671 // 671 //
672 // "When you use specify a priority of -99 in a call to 672 // "When you use specify a priority of -99 in a call to
673 // pthread_setschedparam(), the priority of the target thread is 673 // pthread_setschedparam(), the priority of the target thread is
674 // lowered to the lowest possible value." 674 // lowered to the lowest possible value."
675 // 675 //
676 // ... 676 // ...
677 677
678 // ** CONCLUSION ** 678 // ** CONCLUSION **
679 // 679 //
680 // PThread priorities are _hugely_ system specific, and we need at 680 // PThread priorities are _hugely_ system specific, and we need at
681 // least OS specific settings. Hopefully, Linuxes and OS X versions 681 // least OS specific settings. Hopefully, Linuxes and OS X versions
682 // are uniform enough, among each other... 682 // are uniform enough, among each other...
683 // 683 //
684# if defined PLATFORM_OSX 684# if defined PLATFORM_OSX
685 // AK 10-Apr-07 (OS X PowerPC 10.4.9): 685 // AK 10-Apr-07 (OS X PowerPC 10.4.9):
686 // 686 //
687 // With SCHED_RR, 26 seems to be the "normal" priority, where setting 687 // With SCHED_RR, 26 seems to be the "normal" priority, where setting
688 // it does not seem to affect the order of threads processed. 688 // it does not seem to affect the order of threads processed.
689 // 689 //
690 // With SCHED_OTHER, the range 25..32 is normal (maybe the same 26, 690 // With SCHED_OTHER, the range 25..32 is normal (maybe the same 26,
691 // but the difference is not so clear with OTHER). 691 // but the difference is not so clear with OTHER).
692 // 692 //
693 // 'sched_get_priority_min()' and '..max()' give 15, 47 as the 693 // 'sched_get_priority_min()' and '..max()' give 15, 47 as the
694 // priority limits. This could imply, user mode applications won't 694 // priority limits. This could imply, user mode applications won't
695 // be able to use values outside of that range. 695 // be able to use values outside of that range.
696 // 696 //
697# define _PRIO_MODE SCHED_OTHER 697# define _PRIO_MODE SCHED_OTHER
698 698
699 // OS X 10.4.9 (PowerPC) gives ENOTSUP for process scope 699 // OS X 10.4.9 (PowerPC) gives ENOTSUP for process scope
700 //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS 700 //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS
701 701
702# define _PRIO_HI 32 // seems to work (_carefully_ picked!) 702# define _PRIO_HI 32 // seems to work (_carefully_ picked!)
703# define _PRIO_0 26 // detected 703# define _PRIO_0 26 // detected
704# define _PRIO_LO 1 // seems to work (tested) 704# define _PRIO_LO 1 // seems to work (tested)
705 705
706# elif defined PLATFORM_LINUX 706# elif defined PLATFORM_LINUX
707 // (based on Ubuntu Linux 2.6.15 kernel) 707 // (based on Ubuntu Linux 2.6.15 kernel)
708 // 708 //
709 // SCHED_OTHER is the default policy, but does not allow for priorities. 709 // SCHED_OTHER is the default policy, but does not allow for priorities.
710 // SCHED_RR allows priorities, all of which (1..99) are higher than 710 // SCHED_RR allows priorities, all of which (1..99) are higher than
711 // a thread with SCHED_OTHER policy. 711 // a thread with SCHED_OTHER policy.
712 // 712 //
713 // <http://kerneltrap.org/node/6080> 713 // <http://kerneltrap.org/node/6080>
714 // <http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library> 714 // <http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library>
715 // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> 715 // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html>
716 // 716 //
717 // Manuals suggest checking #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING, 717 // Manuals suggest checking #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING,
718 // but even Ubuntu does not seem to define it. 718 // but even Ubuntu does not seem to define it.
719 // 719 //
720# define _PRIO_MODE SCHED_RR 720# define _PRIO_MODE SCHED_RR
721 721
722 // NTLP 2.5: only system scope allowed (being the basic reason why 722 // NTLP 2.5: only system scope allowed (being the basic reason why
723 // root privileges are required..) 723 // root privileges are required..)
724 //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS 724 //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS
725 725
726# define _PRIO_HI 99 726# define _PRIO_HI 99
727# define _PRIO_0 50 727# define _PRIO_0 50
728# define _PRIO_LO 1 728# define _PRIO_LO 1
729 729
730# elif defined(PLATFORM_BSD) 730# elif defined(PLATFORM_BSD)
731 // 731 //
732 // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> 732 // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html>
733 // 733 //
734 // "When control over the thread scheduling is desired, then FreeBSD 734 // "When control over the thread scheduling is desired, then FreeBSD
735 // with the libpthread implementation is by far the best choice .." 735 // with the libpthread implementation is by far the best choice .."
736 // 736 //
737# define _PRIO_MODE SCHED_OTHER 737# define _PRIO_MODE SCHED_OTHER
738# define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS 738# define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS
739# define _PRIO_HI 31 739# define _PRIO_HI 31
@@ -741,16 +741,16 @@ static int const gs_prio_remap[] =
741# define _PRIO_LO 1 741# define _PRIO_LO 1
742 742
743# elif defined(PLATFORM_CYGWIN) 743# elif defined(PLATFORM_CYGWIN)
744 // 744 //
745 // TBD: Find right values for Cygwin 745 // TBD: Find right values for Cygwin
746 // 746 //
747# elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 747# elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)
748 // any other value not supported by win32-pthread as of version 2.9.1 748 // any other value not supported by win32-pthread as of version 2.9.1
749# define _PRIO_MODE SCHED_OTHER 749# define _PRIO_MODE SCHED_OTHER
750 750
751 // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1 751 // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1
752 //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with? 752 //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with?
753 THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL 753 THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
754 754
755# else 755# else
756# error "Unknown OS: not implemented!" 756# error "Unknown OS: not implemented!"
@@ -760,163 +760,163 @@ static int const gs_prio_remap[] =
760# define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2)) 760# define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2))
761# define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2)) 761# define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2))
762 762
763 _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI 763 _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI
764#endif // _PRIO_0 764#endif // _PRIO_0
765}; 765};
766 766
767void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */) 767void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */)
768{ 768{
769 pthread_attr_t a; 769 pthread_attr_t a;
770 bool_t const normal = 770 bool_t const normal =
771#if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) 771#if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR)
772 !sudo; // with sudo, even normal thread must use SCHED_RR 772 !sudo; // with sudo, even normal thread must use SCHED_RR
773#else 773#else
774 (prio == 0); 774 (prio == 0);
775#endif 775#endif
776 776
777 PT_CALL( pthread_attr_init( &a)); 777 PT_CALL( pthread_attr_init( &a));
778 778
779#ifndef PTHREAD_TIMEDJOIN 779#ifndef PTHREAD_TIMEDJOIN
780 // We create a NON-JOINABLE thread. This is mainly due to the lack of 780 // We create a NON-JOINABLE thread. This is mainly due to the lack of
781 // 'pthread_timedjoin()', but does offer other benefits (s.a. earlier 781 // 'pthread_timedjoin()', but does offer other benefits (s.a. earlier
782 // freeing of the thread's resources). 782 // freeing of the thread's resources).
783 // 783 //
784 PT_CALL( pthread_attr_setdetachstate( &a, PTHREAD_CREATE_DETACHED)); 784 PT_CALL( pthread_attr_setdetachstate( &a, PTHREAD_CREATE_DETACHED));
785#endif // PTHREAD_TIMEDJOIN 785#endif // PTHREAD_TIMEDJOIN
786 786
787 // Use this to find a system's default stack size (DEBUG) 787 // Use this to find a system's default stack size (DEBUG)
788#if 0 788#if 0
789 { 789 {
790 size_t n; 790 size_t n;
791 pthread_attr_getstacksize( &a, &n); 791 pthread_attr_getstacksize( &a, &n);
792 fprintf( stderr, "Getstack: %u\n", (unsigned int)n); 792 fprintf( stderr, "Getstack: %u\n", (unsigned int)n);
793 } 793 }
794 // 524288 on OS X 794 // 524288 on OS X
795 // 2097152 on Linux x86 (Ubuntu 7.04) 795 // 2097152 on Linux x86 (Ubuntu 7.04)
796 // 1048576 on FreeBSD 6.2 SMP i386 796 // 1048576 on FreeBSD 6.2 SMP i386
797#endif // 0 797#endif // 0
798 798
799#if defined _THREAD_STACK_SIZE && _THREAD_STACK_SIZE > 0 799#if defined _THREAD_STACK_SIZE && _THREAD_STACK_SIZE > 0
800 PT_CALL( pthread_attr_setstacksize( &a, _THREAD_STACK_SIZE)); 800 PT_CALL( pthread_attr_setstacksize( &a, _THREAD_STACK_SIZE));
801#endif 801#endif
802 802
803 if( !normal) 803 if( !normal)
804 { 804 {
805 struct sched_param sp; 805 struct sched_param sp;
806 // "The specified scheduling parameters are only used if the scheduling 806 // "The specified scheduling parameters are only used if the scheduling
807 // parameter inheritance attribute is PTHREAD_EXPLICIT_SCHED." 807 // parameter inheritance attribute is PTHREAD_EXPLICIT_SCHED."
808 // 808 //
809#if !defined __ANDROID__ || ( defined __ANDROID__ && __ANDROID_API__ >= 28 ) 809#if !defined __ANDROID__ || ( defined __ANDROID__ && __ANDROID_API__ >= 28 )
810 PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED)); 810 PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED));
811#endif 811#endif
812 812
813#ifdef _PRIO_SCOPE 813#ifdef _PRIO_SCOPE
814 PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE)); 814 PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE));
815#endif // _PRIO_SCOPE 815#endif // _PRIO_SCOPE
816 816
817 PT_CALL( pthread_attr_setschedpolicy( &a, _PRIO_MODE)); 817 PT_CALL( pthread_attr_setschedpolicy( &a, _PRIO_MODE));
818 818
819 // prio range [-3,+3] was checked by the caller 819 // prio range [-3,+3] was checked by the caller
820 sp.sched_priority = gs_prio_remap[ prio + 3]; 820 sp.sched_priority = gs_prio_remap[ prio + 3];
821 PT_CALL( pthread_attr_setschedparam( &a, &sp)); 821 PT_CALL( pthread_attr_setschedparam( &a, &sp));
822 } 822 }
823 823
824 //--- 824 //---
825 // Seems on OS X, _POSIX_THREAD_THREADS_MAX is some kind of system 825 // Seems on OS X, _POSIX_THREAD_THREADS_MAX is some kind of system
826 // thread limit (not userland thread). Actual limit for us is way higher. 826 // thread limit (not userland thread). Actual limit for us is way higher.
827 // PTHREAD_THREADS_MAX is not defined (even though man page refers to it!) 827 // PTHREAD_THREADS_MAX is not defined (even though man page refers to it!)
828 // 828 //
829# ifndef THREAD_CREATE_RETRIES_MAX 829# ifndef THREAD_CREATE_RETRIES_MAX
830 // Don't bother with retries; a failure is a failure 830 // Don't bother with retries; a failure is a failure
831 // 831 //
832 { 832 {
833 int rc = pthread_create( ref, &a, func, data); 833 int rc = pthread_create( ref, &a, func, data);
834 if( rc) _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ - 1); 834 if( rc) _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ - 1);
835 } 835 }
836# else 836# else
837# error "This code deprecated" 837# error "This code deprecated"
838 /* 838 /*
839 // Wait slightly if thread creation has exchausted the system 839 // Wait slightly if thread creation has exchausted the system
840 // 840 //
841 { uint_t retries; 841 { uint_t retries;
842 for( retries=0; retries<THREAD_CREATE_RETRIES_MAX; retries++ ) { 842 for( retries=0; retries<THREAD_CREATE_RETRIES_MAX; retries++ ) {
843 843
844 int rc= pthread_create( ref, &a, func, data ); 844 int rc= pthread_create( ref, &a, func, data );
845 // 845 //
846 // OS X / Linux: 846 // OS X / Linux:
847 // EAGAIN: ".. lacked the necessary resources to create 847 // EAGAIN: ".. lacked the necessary resources to create
848 // another thread, or the system-imposed limit on the 848 // another thread, or the system-imposed limit on the
849 // total number of threads in a process 849 // total number of threads in a process
850 // [PTHREAD_THREADS_MAX] would be exceeded." 850 // [PTHREAD_THREADS_MAX] would be exceeded."
851 // EINVAL: attr is invalid 851 // EINVAL: attr is invalid
852 // Linux: 852 // Linux:
853 // EPERM: no rights for given parameters or scheduling (no sudo) 853 // EPERM: no rights for given parameters or scheduling (no sudo)
854 // ENOMEM: (known to fail with this code, too - not listed in man) 854 // ENOMEM: (known to fail with this code, too - not listed in man)
855 855
856 if (rc==0) break; // ok! 856 if (rc==0) break; // ok!
857 857
858 // In practise, exhaustion seems to be coming from memory, not a 858 // In practise, exhaustion seems to be coming from memory, not a
859 // maximum number of threads. Keep tuning... ;) 859 // maximum number of threads. Keep tuning... ;)
860 // 860 //
861 if (rc==EAGAIN) { 861 if (rc==EAGAIN) {
862 //fprintf( stderr, "Looping (retries=%d) ", retries ); // DEBUG 862 //fprintf( stderr, "Looping (retries=%d) ", retries ); // DEBUG
863 863
864 // Try again, later. 864 // Try again, later.
865 865
866 Yield(); 866 Yield();
867 } else { 867 } else {
868 _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ ); 868 _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ );
869 } 869 }
870 } 870 }
871 } 871 }
872 */ 872 */
873# endif 873# endif
874 874
875 PT_CALL( pthread_attr_destroy( &a)); 875 PT_CALL( pthread_attr_destroy( &a));
876} 876}
877 877
878 878
879void THREAD_SET_PRIORITY( int prio) 879void THREAD_SET_PRIORITY( int prio)
880{ 880{
881#if defined PLATFORM_LINUX && defined LINUX_SCHED_RR 881#if defined PLATFORM_LINUX && defined LINUX_SCHED_RR
882 if( sudo) // only root-privileged process can change priorities 882 if( sudo) // only root-privileged process can change priorities
883#endif // defined PLATFORM_LINUX && defined LINUX_SCHED_RR 883#endif // defined PLATFORM_LINUX && defined LINUX_SCHED_RR
884 { 884 {
885 struct sched_param sp; 885 struct sched_param sp;
886 // prio range [-3,+3] was checked by the caller 886 // prio range [-3,+3] was checked by the caller
887 sp.sched_priority = gs_prio_remap[ prio + 3]; 887 sp.sched_priority = gs_prio_remap[ prio + 3];
888 PT_CALL( pthread_setschedparam( pthread_self(), _PRIO_MODE, &sp)); 888 PT_CALL( pthread_setschedparam( pthread_self(), _PRIO_MODE, &sp));
889 } 889 }
890} 890}
891 891
892void THREAD_SET_AFFINITY( unsigned int aff) 892void THREAD_SET_AFFINITY( unsigned int aff)
893{ 893{
894 int bit = 0; 894 int bit = 0;
895#ifdef __NetBSD__ 895#ifdef __NetBSD__
896 cpuset_t *cpuset = cpuset_create(); 896 cpuset_t *cpuset = cpuset_create();
897 if( cpuset == NULL) 897 if( cpuset == NULL)
898 _PT_FAIL( errno, "cpuset_create", __FILE__, __LINE__-2 ); 898 _PT_FAIL( errno, "cpuset_create", __FILE__, __LINE__-2 );
899#define CPU_SET(b, s) cpuset_set(b, *(s)) 899#define CPU_SET(b, s) cpuset_set(b, *(s))
900#else 900#else
901 cpu_set_t cpuset; 901 cpu_set_t cpuset;
902 CPU_ZERO( &cpuset); 902 CPU_ZERO( &cpuset);
903#endif 903#endif
904 while( aff != 0) 904 while( aff != 0)
905 { 905 {
906 if( aff & 1) 906 if( aff & 1)
907 { 907 {
908 CPU_SET( bit, &cpuset); 908 CPU_SET( bit, &cpuset);
909 } 909 }
910 ++ bit; 910 ++ bit;
911 aff >>= 1; 911 aff >>= 1;
912 } 912 }
913#ifdef __ANDROID__ 913#ifdef __ANDROID__
914 PT_CALL( sched_setaffinity( pthread_self(), sizeof(cpu_set_t), &cpuset)); 914 PT_CALL( sched_setaffinity( pthread_self(), sizeof(cpu_set_t), &cpuset));
915#elif defined(__NetBSD__) 915#elif defined(__NetBSD__)
916 PT_CALL( pthread_setaffinity_np( pthread_self(), cpuset_size(cpuset), cpuset)); 916 PT_CALL( pthread_setaffinity_np( pthread_self(), cpuset_size(cpuset), cpuset));
917 cpuset_destroy( cpuset); 917 cpuset_destroy( cpuset);
918#else 918#else
919 PT_CALL( pthread_setaffinity_np( pthread_self(), sizeof(cpu_set_t), &cpuset)); 919 PT_CALL( pthread_setaffinity_np( pthread_self(), sizeof(cpu_set_t), &cpuset));
920#endif 920#endif
921} 921}
922 922
@@ -986,47 +986,47 @@ bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T *
986#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR 986#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
987 return done; 987 return done;
988 } 988 }
989 // 989 //
990 void THREAD_KILL( THREAD_T *ref ) { 990 void THREAD_KILL( THREAD_T *ref ) {
991#ifdef __ANDROID__ 991#ifdef __ANDROID__
992 __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Cannot kill thread!"); 992 __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Cannot kill thread!");
993#else 993#else
994 pthread_cancel( *ref ); 994 pthread_cancel( *ref );
995#endif 995#endif
996 } 996 }
997 997
998 void THREAD_MAKE_ASYNCH_CANCELLABLE() 998 void THREAD_MAKE_ASYNCH_CANCELLABLE()
999 { 999 {
1000#ifdef __ANDROID__ 1000#ifdef __ANDROID__
1001 __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Cannot make thread async cancellable!"); 1001 __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Cannot make thread async cancellable!");
1002#else 1002#else
1003 // that's the default, but just in case... 1003 // that's the default, but just in case...
1004 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 1004 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1005 // we want cancellation to take effect immediately if possible, instead of waiting for a cancellation point (which is the default) 1005 // we want cancellation to take effect immediately if possible, instead of waiting for a cancellation point (which is the default)
1006 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 1006 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
1007#endif 1007#endif
1008 } 1008 }
1009 1009
1010 void THREAD_SETNAME( char const* _name) 1010 void THREAD_SETNAME( char const* _name)
1011 { 1011 {
1012 // exact API to set the thread name is platform-dependant 1012 // exact API to set the thread name is platform-dependant
1013 // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github. 1013 // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github.
1014#if defined PLATFORM_BSD && !defined __NetBSD__ 1014#if defined PLATFORM_BSD && !defined __NetBSD__
1015 pthread_set_name_np( pthread_self(), _name); 1015 pthread_set_name_np( pthread_self(), _name);
1016#elif defined PLATFORM_BSD && defined __NetBSD__ 1016#elif defined PLATFORM_BSD && defined __NetBSD__
1017 pthread_setname_np( pthread_self(), "%s", (void *)_name); 1017 pthread_setname_np( pthread_self(), "%s", (void *)_name);
1018#elif defined PLATFORM_LINUX 1018#elif defined PLATFORM_LINUX
1019 #if LINUX_USE_PTHREAD_SETNAME_NP 1019 #if LINUX_USE_PTHREAD_SETNAME_NP
1020 pthread_setname_np( pthread_self(), _name); 1020 pthread_setname_np( pthread_self(), _name);
1021 #else // LINUX_USE_PTHREAD_SETNAME_NP 1021 #else // LINUX_USE_PTHREAD_SETNAME_NP
1022 prctl(PR_SET_NAME, _name, 0, 0, 0); 1022 prctl(PR_SET_NAME, _name, 0, 0, 0);
1023 #endif // LINUX_USE_PTHREAD_SETNAME_NP 1023 #endif // LINUX_USE_PTHREAD_SETNAME_NP
1024#elif defined PLATFORM_QNX || defined PLATFORM_CYGWIN 1024#elif defined PLATFORM_QNX || defined PLATFORM_CYGWIN
1025 pthread_setname_np( pthread_self(), _name); 1025 pthread_setname_np( pthread_self(), _name);
1026#elif defined PLATFORM_OSX 1026#elif defined PLATFORM_OSX
1027 pthread_setname_np(_name); 1027 pthread_setname_np(_name);
1028#elif defined PLATFORM_WIN32 || defined PLATFORM_POCKETPC 1028#elif defined PLATFORM_WIN32 || defined PLATFORM_POCKETPC
1029 PT_CALL( pthread_setname_np( pthread_self(), _name)); 1029 PT_CALL( pthread_setname_np( pthread_self(), _name));
1030#endif 1030#endif
1031 } 1031 }
1032#endif // THREADAPI == THREADAPI_PTHREAD 1032#endif // THREADAPI == THREADAPI_PTHREAD