diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2013-12-02 14:40:08 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2013-12-02 14:40:08 +0100 |
| commit | 370494d2e260e717990427180c6ab16d3746607e (patch) | |
| tree | b4b855be3de324acf00fcf0f028506613f8649a8 /src | |
| parent | 6d124b90b637b0a85341646a68fdb11dc9079abf (diff) | |
| download | lanes-370494d2e260e717990427180c6ab16d3746607e.tar.gz lanes-370494d2e260e717990427180c6ab16d3746607e.tar.bz2 lanes-370494d2e260e717990427180c6ab16d3746607e.zip | |
pthread thread priority refacto: threading.c
Diffstat (limited to 'src')
| -rw-r--r-- | src/threading.c | 428 |
1 files changed, 212 insertions, 216 deletions
diff --git a/src/threading.c b/src/threading.c index d50207e..18eef87 100644 --- a/src/threading.c +++ b/src/threading.c | |||
| @@ -525,7 +525,8 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) | |||
| 525 | // | 525 | // |
| 526 | #include <errno.h> | 526 | #include <errno.h> |
| 527 | 527 | ||
| 528 | # if ((defined(__MINGW32__) || defined(__MINGW64__)) && pthread_attr_setschedpolicy( A, S) == ENOTSUP) | 528 | # if (defined(__MINGW32__) || defined(__MINGW64__)) && defined pthread_attr_setschedpolicy |
| 529 | # if pthread_attr_setschedpolicy( A, S) == ENOTSUP | ||
| 529 | // from the mingw-w64 team: | 530 | // from the mingw-w64 team: |
| 530 | // Well, we support pthread_setschedparam by which you can specify | 531 | // Well, we support pthread_setschedparam by which you can specify |
| 531 | // threading-policy. Nevertheless, yes we lack this function. In | 532 | // threading-policy. Nevertheless, yes we lack this function. In |
| @@ -540,6 +541,7 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) | |||
| 540 | } | 541 | } |
| 541 | return 0; | 542 | return 0; |
| 542 | } | 543 | } |
| 544 | # endif // pthread_attr_setschedpolicy() | ||
| 543 | # endif // defined(__MINGW32__) || defined(__MINGW64__) | 545 | # endif // defined(__MINGW32__) || defined(__MINGW64__) |
| 544 | 546 | ||
| 545 | static void _PT_FAIL( int rc, const char *name, const char *file, uint_t line ) { | 547 | static void _PT_FAIL( int rc, const char *name, const char *file, uint_t line ) { |
| @@ -593,245 +595,239 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) | |||
| 593 | void SIGNAL_ALL( SIGNAL_T *ref ) { | 595 | void SIGNAL_ALL( SIGNAL_T *ref ) { |
| 594 | PT_CALL( pthread_cond_broadcast(ref) ); // wake up ALL waiting threads | 596 | PT_CALL( pthread_cond_broadcast(ref) ); // wake up ALL waiting threads |
| 595 | } | 597 | } |
| 596 | // | ||
| 597 | void THREAD_CREATE( THREAD_T* ref, | ||
| 598 | THREAD_RETURN_T (*func)( void * ), | ||
| 599 | void *data, int prio /* -2..+2 */ ) { | ||
| 600 | pthread_attr_t _a; | ||
| 601 | pthread_attr_t *a= &_a; | ||
| 602 | struct sched_param sp; | ||
| 603 | bool_t normal; | ||
| 604 | 598 | ||
| 605 | PT_CALL( pthread_attr_init(a) ); | 599 | // array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range |
| 600 | static int const gs_prio_remap[] = | ||
| 601 | { | ||
| 602 | // NB: PThreads priority handling is about as twisty as one can get it | ||
| 603 | // (and then some). DON*T TRUST ANYTHING YOU READ ON THE NET!!! | ||
| 606 | 604 | ||
| 607 | #ifndef PTHREAD_TIMEDJOIN | 605 | //--- |
| 608 | // We create a NON-JOINABLE thread. This is mainly due to the lack of | 606 | // "Select the scheduling policy for the thread: one of SCHED_OTHER |
| 609 | // 'pthread_timedjoin()', but does offer other benefits (s.a. earlier | 607 | // (regular, non-real-time scheduling), SCHED_RR (real-time, |
| 610 | // freeing of the thread's resources). | 608 | // round-robin) or SCHED_FIFO (real-time, first-in first-out)." |
| 611 | // | 609 | // |
| 612 | PT_CALL( pthread_attr_setdetachstate(a,PTHREAD_CREATE_DETACHED) ); | 610 | // "Using the RR policy ensures that all threads having the same |
| 613 | #endif | 611 | // priority level will be scheduled equally, regardless of their activity." |
| 612 | // | ||
| 613 | // "For SCHED_FIFO and SCHED_RR, the only required member of the | ||
| 614 | // sched_param structure is the priority sched_priority. For SCHED_OTHER, | ||
| 615 | // the affected scheduling parameters are implementation-defined." | ||
| 616 | // | ||
| 617 | // "The priority of a thread is specified as a delta which is added to | ||
| 618 | // the priority of the process." | ||
| 619 | // | ||
| 620 | // ".. priority is an integer value, in the range from 1 to 127. | ||
| 621 | // 1 is the least-favored priority, 127 is the most-favored." | ||
| 622 | // | ||
| 623 | // "Priority level 0 cannot be used: it is reserved for the system." | ||
| 624 | // | ||
| 625 | // "When you use specify a priority of -99 in a call to | ||
| 626 | // pthread_setschedparam(), the priority of the target thread is | ||
| 627 | // lowered to the lowest possible value." | ||
| 628 | // | ||
| 629 | // ... | ||
| 614 | 630 | ||
| 615 | // Use this to find a system's default stack size (DEBUG) | 631 | // ** CONCLUSION ** |
| 616 | #if 0 | 632 | // |
| 617 | { size_t n; pthread_attr_getstacksize( a, &n ); | 633 | // PThread priorities are _hugely_ system specific, and we need at |
| 618 | fprintf( stderr, "Getstack: %u\n", (unsigned int)n ); } | 634 | // least OS specific settings. Hopefully, Linuxes and OS X versions |
| 619 | // 524288 on OS X | 635 | // are uniform enough, among each other... |
| 620 | // 2097152 on Linux x86 (Ubuntu 7.04) | 636 | // |
| 621 | // 1048576 on FreeBSD 6.2 SMP i386 | 637 | # if defined PLATFORM_OSX |
| 622 | #endif | 638 | // AK 10-Apr-07 (OS X PowerPC 10.4.9): |
| 639 | // | ||
| 640 | // With SCHED_RR, 26 seems to be the "normal" priority, where setting | ||
| 641 | // it does not seem to affect the order of threads processed. | ||
| 642 | // | ||
| 643 | // With SCHED_OTHER, the range 25..32 is normal (maybe the same 26, | ||
| 644 | // but the difference is not so clear with OTHER). | ||
| 645 | // | ||
| 646 | // 'sched_get_priority_min()' and '..max()' give 15, 47 as the | ||
| 647 | // priority limits. This could imply, user mode applications won't | ||
| 648 | // be able to use values outside of that range. | ||
| 649 | // | ||
| 650 | # define _PRIO_MODE SCHED_OTHER | ||
| 651 | |||
| 652 | // OS X 10.4.9 (PowerPC) gives ENOTSUP for process scope | ||
| 653 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | ||
| 654 | |||
| 655 | # define _PRIO_HI 32 // seems to work (_carefully_ picked!) | ||
| 656 | # define _PRIO_0 26 // detected | ||
| 657 | # define _PRIO_LO 1 // seems to work (tested) | ||
| 658 | |||
| 659 | # elif defined PLATFORM_LINUX | ||
| 660 | // (based on Ubuntu Linux 2.6.15 kernel) | ||
| 661 | // | ||
| 662 | // SCHED_OTHER is the default policy, but does not allow for priorities. | ||
| 663 | // SCHED_RR allows priorities, all of which (1..99) are higher than | ||
| 664 | // a thread with SCHED_OTHER policy. | ||
| 665 | // | ||
| 666 | // <http://kerneltrap.org/node/6080> | ||
| 667 | // <http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library> | ||
| 668 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> | ||
| 669 | // | ||
| 670 | // Manuals suggest checking #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING, | ||
| 671 | // but even Ubuntu does not seem to define it. | ||
| 672 | // | ||
| 673 | # define _PRIO_MODE SCHED_RR | ||
| 623 | 674 | ||
| 624 | #if (defined _THREAD_STACK_SIZE) && (_THREAD_STACK_SIZE > 0) | 675 | // NTLP 2.5: only system scope allowed (being the basic reason why |
| 625 | PT_CALL( pthread_attr_setstacksize( a, _THREAD_STACK_SIZE ) ); | 676 | // root privileges are required..) |
| 626 | #endif | 677 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS |
| 627 | |||
| 628 | normal= | ||
| 629 | #if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) | ||
| 630 | !sudo; // with sudo, even normal thread must use SCHED_RR | ||
| 631 | #else | ||
| 632 | prio == 0; // create a default thread if | ||
| 633 | #endif | ||
| 634 | if (!normal) { | ||
| 635 | // NB: PThreads priority handling is about as twisty as one can get it | ||
| 636 | // (and then some). DON*T TRUST ANYTHING YOU READ ON THE NET!!! | ||
| 637 | 678 | ||
| 638 | // "The specified scheduling parameters are only used if the scheduling | 679 | # define _PRIO_HI 99 |
| 639 | // parameter inheritance attribute is PTHREAD_EXPLICIT_SCHED." | 680 | # define _PRIO_0 50 |
| 640 | // | 681 | # define _PRIO_LO 1 |
| 641 | PT_CALL( pthread_attr_setinheritsched( a, PTHREAD_EXPLICIT_SCHED ) ); | ||
| 642 | 682 | ||
| 643 | //--- | 683 | # elif defined(PLATFORM_BSD) |
| 644 | // "Select the scheduling policy for the thread: one of SCHED_OTHER | 684 | // |
| 645 | // (regular, non-real-time scheduling), SCHED_RR (real-time, | 685 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> |
| 646 | // round-robin) or SCHED_FIFO (real-time, first-in first-out)." | 686 | // |
| 647 | // | 687 | // "When control over the thread scheduling is desired, then FreeBSD |
| 648 | // "Using the RR policy ensures that all threads having the same | 688 | // with the libpthread implementation is by far the best choice .." |
| 649 | // priority level will be scheduled equally, regardless of their activity." | 689 | // |
| 650 | // | 690 | # define _PRIO_MODE SCHED_OTHER |
| 651 | // "For SCHED_FIFO and SCHED_RR, the only required member of the | 691 | # define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS |
| 652 | // sched_param structure is the priority sched_priority. For SCHED_OTHER, | 692 | # define _PRIO_HI 31 |
| 653 | // the affected scheduling parameters are implementation-defined." | 693 | # define _PRIO_0 15 |
| 654 | // | 694 | # define _PRIO_LO 1 |
| 655 | // "The priority of a thread is specified as a delta which is added to | ||
| 656 | // the priority of the process." | ||
| 657 | // | ||
| 658 | // ".. priority is an integer value, in the range from 1 to 127. | ||
| 659 | // 1 is the least-favored priority, 127 is the most-favored." | ||
| 660 | // | ||
| 661 | // "Priority level 0 cannot be used: it is reserved for the system." | ||
| 662 | // | ||
| 663 | // "When you use specify a priority of -99 in a call to | ||
| 664 | // pthread_setschedparam(), the priority of the target thread is | ||
| 665 | // lowered to the lowest possible value." | ||
| 666 | // | ||
| 667 | // ... | ||
| 668 | 695 | ||
| 669 | // ** CONCLUSION ** | 696 | # elif defined(PLATFORM_CYGWIN) |
| 670 | // | 697 | // |
| 671 | // PThread priorities are _hugely_ system specific, and we need at | 698 | // TBD: Find right values for Cygwin |
| 672 | // least OS specific settings. Hopefully, Linuxes and OS X versions | 699 | // |
| 673 | // are uniform enough, among each other... | 700 | # elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) |
| 674 | // | 701 | // any other value not supported by win32-pthread as of version 2.9.1 |
| 675 | #ifdef PLATFORM_OSX | 702 | # define _PRIO_MODE SCHED_OTHER |
| 676 | // AK 10-Apr-07 (OS X PowerPC 10.4.9): | ||
| 677 | // | ||
| 678 | // With SCHED_RR, 26 seems to be the "normal" priority, where setting | ||
| 679 | // it does not seem to affect the order of threads processed. | ||
| 680 | // | ||
| 681 | // With SCHED_OTHER, the range 25..32 is normal (maybe the same 26, | ||
| 682 | // but the difference is not so clear with OTHER). | ||
| 683 | // | ||
| 684 | // 'sched_get_priority_min()' and '..max()' give 15, 47 as the | ||
| 685 | // priority limits. This could imply, user mode applications won't | ||
| 686 | // be able to use values outside of that range. | ||
| 687 | // | ||
| 688 | #define _PRIO_MODE SCHED_OTHER | ||
| 689 | |||
| 690 | // OS X 10.4.9 (PowerPC) gives ENOTSUP for process scope | ||
| 691 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | ||
| 692 | 703 | ||
| 693 | #define _PRIO_HI 32 // seems to work (_carefully_ picked!) | 704 | // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1 |
| 694 | #define _PRIO_0 26 // detected | 705 | //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with? |
| 695 | #define _PRIO_LO 1 // seems to work (tested) | 706 | THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL |
| 696 | 707 | ||
| 697 | #elif defined(PLATFORM_LINUX) | 708 | # else |
| 698 | // (based on Ubuntu Linux 2.6.15 kernel) | 709 | # error "Unknown OS: not implemented!" |
| 699 | // | 710 | # endif |
| 700 | // SCHED_OTHER is the default policy, but does not allow for priorities. | ||
| 701 | // SCHED_RR allows priorities, all of which (1..99) are higher than | ||
| 702 | // a thread with SCHED_OTHER policy. | ||
| 703 | // | ||
| 704 | // <http://kerneltrap.org/node/6080> | ||
| 705 | // <http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library> | ||
| 706 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> | ||
| 707 | // | ||
| 708 | // Manuals suggest checking #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING, | ||
| 709 | // but even Ubuntu does not seem to define it. | ||
| 710 | // | ||
| 711 | #define _PRIO_MODE SCHED_RR | ||
| 712 | |||
| 713 | // NTLP 2.5: only system scope allowed (being the basic reason why | ||
| 714 | // root privileges are required..) | ||
| 715 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | ||
| 716 | 711 | ||
| 717 | #define _PRIO_HI 99 | 712 | #if defined _PRIO_0 |
| 718 | #define _PRIO_0 50 | 713 | # define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2) ) |
| 719 | #define _PRIO_LO 1 | 714 | # define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2) ) |
| 720 | 715 | ||
| 721 | #elif defined(PLATFORM_BSD) | 716 | _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI |
| 722 | // | 717 | #endif // _PRIO_0 |
| 723 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> | 718 | }; |
| 724 | // | ||
| 725 | // "When control over the thread scheduling is desired, then FreeBSD | ||
| 726 | // with the libpthread implementation is by far the best choice .." | ||
| 727 | // | ||
| 728 | #define _PRIO_MODE SCHED_OTHER | ||
| 729 | #define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | ||
| 730 | #define _PRIO_HI 31 | ||
| 731 | #define _PRIO_0 15 | ||
| 732 | #define _PRIO_LO 1 | ||
| 733 | 719 | ||
| 734 | #elif defined(PLATFORM_CYGWIN) | 720 | // |
| 735 | // | 721 | void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void * ), void *data, int prio /* -2..+2 */) |
| 736 | // TBD: Find right values for Cygwin | 722 | { |
| 737 | // | 723 | pthread_attr_t a; |
| 738 | #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) | 724 | bool_t const normal = |
| 739 | // any other value not supported by win32-pthread as of version 2.9.1 | 725 | #if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) |
| 740 | #define _PRIO_MODE SCHED_OTHER | 726 | !sudo; // with sudo, even normal thread must use SCHED_RR |
| 741 | |||
| 742 | // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1 | ||
| 743 | //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with? | ||
| 744 | |||
| 745 | #if defined __WINPTHREADS_VERSION | ||
| 746 | // see http://sourceforge.net/p/mingw-w64/code/6370/tree/trunk/mingw-w64-libraries/winpthreads/src/sched.c#l128 | ||
| 747 | #define _PRIO_HI (+15) | ||
| 748 | #define _PRIO_0 (0) | ||
| 749 | #define _PRIO_LO (-15) | ||
| 750 | #else | ||
| 751 | // win32-pthread seems happy with direct -2..+2 instead of some other remapping | ||
| 752 | #define _PRIO_HI (+2) | ||
| 753 | #define _PRIO_0 (0) | ||
| 754 | #define _PRIO_LO (-2) | ||
| 755 | #endif | ||
| 756 | #else | 727 | #else |
| 757 | #error "Unknown OS: not implemented!" | 728 | (prio == 0); |
| 758 | #endif | 729 | #endif |
| 759 | 730 | ||
| 760 | #ifdef _PRIO_SCOPE | 731 | PT_CALL( pthread_attr_init( &a)); |
| 761 | PT_CALL( pthread_attr_setscope( a, _PRIO_SCOPE ) ); | ||
| 762 | #endif | ||
| 763 | PT_CALL( pthread_attr_setschedpolicy( a, _PRIO_MODE ) ); | ||
| 764 | 732 | ||
| 765 | #define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2) ) | 733 | #ifndef PTHREAD_TIMEDJOIN |
| 766 | #define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2) ) | 734 | // We create a NON-JOINABLE thread. This is mainly due to the lack of |
| 735 | // 'pthread_timedjoin()', but does offer other benefits (s.a. earlier | ||
| 736 | // freeing of the thread's resources). | ||
| 737 | // | ||
| 738 | PT_CALL( pthread_attr_setdetachstate( &a, PTHREAD_CREATE_DETACHED)); | ||
| 739 | #endif // PTHREAD_TIMEDJOIN | ||
| 767 | 740 | ||
| 768 | sp.sched_priority= | 741 | // Use this to find a system's default stack size (DEBUG) |
| 769 | (prio == +2) ? _PRIO_HI : | 742 | #if 0 |
| 770 | (prio == +1) ? _PRIO_AN : | 743 | { |
| 771 | #if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) | 744 | size_t n; |
| 772 | (prio == 0) ? _PRIO_0 : | 745 | pthread_attr_getstacksize( &a, &n); |
| 746 | fprintf( stderr, "Getstack: %u\n", (unsigned int)n); | ||
| 747 | } | ||
| 748 | // 524288 on OS X | ||
| 749 | // 2097152 on Linux x86 (Ubuntu 7.04) | ||
| 750 | // 1048576 on FreeBSD 6.2 SMP i386 | ||
| 751 | #endif // 0 | ||
| 752 | |||
| 753 | #if defined _THREAD_STACK_SIZE && _THREAD_STACK_SIZE > 0 | ||
| 754 | PT_CALL( pthread_attr_setstacksize( &a, _THREAD_STACK_SIZE)); | ||
| 773 | #endif | 755 | #endif |
| 774 | (prio == -1) ? _PRIO_BN : _PRIO_LO; | ||
| 775 | 756 | ||
| 776 | PT_CALL( pthread_attr_setschedparam( a, &sp ) ); | 757 | if( !normal) |
| 777 | } | 758 | { |
| 759 | struct sched_param sp; | ||
| 760 | // "The specified scheduling parameters are only used if the scheduling | ||
| 761 | // parameter inheritance attribute is PTHREAD_EXPLICIT_SCHED." | ||
| 762 | // | ||
| 763 | PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED)); | ||
| 778 | 764 | ||
| 779 | //--- | ||
| 780 | // Seems on OS X, _POSIX_THREAD_THREADS_MAX is some kind of system | ||
| 781 | // thread limit (not userland thread). Actual limit for us is way higher. | ||
| 782 | // PTHREAD_THREADS_MAX is not defined (even though man page refers to it!) | ||
| 783 | // | ||
| 784 | # ifndef THREAD_CREATE_RETRIES_MAX | ||
| 785 | // Don't bother with retries; a failure is a failure | ||
| 786 | // | ||
| 787 | { | ||
| 788 | int rc= pthread_create( ref, a, func, data ); | ||
| 789 | if (rc) _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__-1 ); | ||
| 790 | } | ||
| 791 | # else | ||
| 792 | # error "This code deprecated" | ||
| 793 | /* | ||
| 794 | // Wait slightly if thread creation has exchausted the system | ||
| 795 | // | ||
| 796 | { uint_t retries; | ||
| 797 | for( retries=0; retries<THREAD_CREATE_RETRIES_MAX; retries++ ) { | ||
| 798 | |||
| 799 | int rc= pthread_create( ref, a, func, data ); | ||
| 800 | // | ||
| 801 | // OS X / Linux: | ||
| 802 | // EAGAIN: ".. lacked the necessary resources to create | ||
| 803 | // another thread, or the system-imposed limit on the | ||
| 804 | // total number of threads in a process | ||
| 805 | // [PTHREAD_THREADS_MAX] would be exceeded." | ||
| 806 | // EINVAL: attr is invalid | ||
| 807 | // Linux: | ||
| 808 | // EPERM: no rights for given parameters or scheduling (no sudo) | ||
| 809 | // ENOMEM: (known to fail with this code, too - not listed in man) | ||
| 810 | |||
| 811 | if (rc==0) break; // ok! | ||
| 812 | |||
| 813 | // In practise, exhaustion seems to be coming from memory, not a | ||
| 814 | // maximum number of threads. Keep tuning... ;) | ||
| 815 | // | ||
| 816 | if (rc==EAGAIN) { | ||
| 817 | //fprintf( stderr, "Looping (retries=%d) ", retries ); // DEBUG | ||
| 818 | 765 | ||
| 819 | // Try again, later. | 766 | #ifdef _PRIO_SCOPE |
| 767 | PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE)); | ||
| 768 | #endif // _PRIO_SCOPE | ||
| 820 | 769 | ||
| 821 | Yield(); | 770 | PT_CALL( pthread_attr_setschedpolicy( &a, _PRIO_MODE)); |
| 822 | } else { | 771 | |
| 823 | _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ ); | 772 | // prio range [-3,+3] was checked by the caller |
| 824 | } | 773 | sp.sched_priority = gs_prio_remap[ prio + 3]; |
| 825 | } | 774 | PT_CALL( pthread_attr_setschedparam( &a, &sp)); |
| 826 | } | 775 | } |
| 827 | */ | 776 | |
| 777 | //--- | ||
| 778 | // Seems on OS X, _POSIX_THREAD_THREADS_MAX is some kind of system | ||
| 779 | // thread limit (not userland thread). Actual limit for us is way higher. | ||
| 780 | // PTHREAD_THREADS_MAX is not defined (even though man page refers to it!) | ||
| 781 | // | ||
| 782 | # ifndef THREAD_CREATE_RETRIES_MAX | ||
| 783 | // Don't bother with retries; a failure is a failure | ||
| 784 | // | ||
| 785 | { | ||
| 786 | int rc = pthread_create( ref, &a, func, data); | ||
| 787 | if( rc) _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ - 1); | ||
| 788 | } | ||
| 789 | # else | ||
| 790 | # error "This code deprecated" | ||
| 791 | /* | ||
| 792 | // Wait slightly if thread creation has exchausted the system | ||
| 793 | // | ||
| 794 | { uint_t retries; | ||
| 795 | for( retries=0; retries<THREAD_CREATE_RETRIES_MAX; retries++ ) { | ||
| 796 | |||
| 797 | int rc= pthread_create( ref, &a, func, data ); | ||
| 798 | // | ||
| 799 | // OS X / Linux: | ||
| 800 | // EAGAIN: ".. lacked the necessary resources to create | ||
| 801 | // another thread, or the system-imposed limit on the | ||
| 802 | // total number of threads in a process | ||
| 803 | // [PTHREAD_THREADS_MAX] would be exceeded." | ||
| 804 | // EINVAL: attr is invalid | ||
| 805 | // Linux: | ||
| 806 | // EPERM: no rights for given parameters or scheduling (no sudo) | ||
| 807 | // ENOMEM: (known to fail with this code, too - not listed in man) | ||
| 808 | |||
| 809 | if (rc==0) break; // ok! | ||
| 810 | |||
| 811 | // In practise, exhaustion seems to be coming from memory, not a | ||
| 812 | // maximum number of threads. Keep tuning... ;) | ||
| 813 | // | ||
| 814 | if (rc==EAGAIN) { | ||
| 815 | //fprintf( stderr, "Looping (retries=%d) ", retries ); // DEBUG | ||
| 816 | |||
| 817 | // Try again, later. | ||
| 818 | |||
| 819 | Yield(); | ||
| 820 | } else { | ||
| 821 | _PT_FAIL( rc, "pthread_create()", __FILE__, __LINE__ ); | ||
| 822 | } | ||
| 823 | } | ||
| 824 | } | ||
| 825 | */ | ||
| 828 | # endif | 826 | # endif |
| 829 | 827 | ||
| 830 | if (a) { | 828 | PT_CALL( pthread_attr_destroy( &a)); |
| 831 | PT_CALL( pthread_attr_destroy(a) ); | 829 | } |
| 832 | } | 830 | |
| 833 | } | ||
| 834 | // | ||
| 835 | /* | 831 | /* |
| 836 | * Wait for a thread to finish. | 832 | * Wait for a thread to finish. |
| 837 | * | 833 | * |
