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 | * |