OLD | NEW |
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | 2 /* This Source Code Form is subject to the terms of the Mozilla Public |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | 3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | 5 |
6 /* | 6 /* |
7 ** File: ptthread.c | 7 ** File: ptthread.c |
8 ** Descritpion: Implemenation for threds using pthreds | 8 ** Descritpion: Implemenation for threds using pthreds |
9 ** Exports: ptthread.h | 9 ** Exports: ptthread.h |
10 */ | 10 */ |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include <signal.h> | 21 #include <signal.h> |
22 #include <dlfcn.h> | 22 #include <dlfcn.h> |
23 | 23 |
24 #ifdef SYMBIAN | 24 #ifdef SYMBIAN |
25 /* In Open C sched_get_priority_min/max do not work properly, so we undefine | 25 /* In Open C sched_get_priority_min/max do not work properly, so we undefine |
26 * _POSIX_THREAD_PRIORITY_SCHEDULING here. | 26 * _POSIX_THREAD_PRIORITY_SCHEDULING here. |
27 */ | 27 */ |
28 #undef _POSIX_THREAD_PRIORITY_SCHEDULING | 28 #undef _POSIX_THREAD_PRIORITY_SCHEDULING |
29 #endif | 29 #endif |
30 | 30 |
| 31 #ifdef _PR_NICE_PRIORITY_SCHEDULING |
| 32 #undef _POSIX_THREAD_PRIORITY_SCHEDULING |
| 33 #include <sys/resource.h> |
| 34 #ifndef HAVE_GETTID |
| 35 #define gettid() (syscall(SYS_gettid)) |
| 36 #endif |
| 37 #endif |
| 38 |
31 /* | 39 /* |
32 * Record whether or not we have the privilege to set the scheduling | 40 * Record whether or not we have the privilege to set the scheduling |
33 * policy and priority of threads. 0 means that privilege is available. | 41 * policy and priority of threads. 0 means that privilege is available. |
34 * EPERM means that privilege is not available. | 42 * EPERM means that privilege is not available. |
35 */ | 43 */ |
36 | 44 |
37 static PRIntn pt_schedpriv = 0; | 45 static PRIntn pt_schedpriv = 0; |
38 extern PRLock *_pr_sleeplock; | 46 extern PRLock *_pr_sleeplock; |
39 | 47 |
40 static struct _PT_Bookeeping | 48 static struct _PT_Bookeeping |
(...skipping 21 matching lines...) Expand all Loading... |
62 * for now I have just hard coded everything to run at priority 10 | 70 * for now I have just hard coded everything to run at priority 10 |
63 * until I can come up with a new algorithm. | 71 * until I can come up with a new algorithm. |
64 * Jerry.Kirk@Nexwarecorp.com | 72 * Jerry.Kirk@Nexwarecorp.com |
65 */ | 73 */ |
66 return 10; | 74 return 10; |
67 #else | 75 #else |
68 return pt_book.minPrio + | 76 return pt_book.minPrio + |
69 pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST; | 77 pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST; |
70 #endif | 78 #endif |
71 } | 79 } |
| 80 #elif defined(_PR_NICE_PRIORITY_SCHEDULING) |
| 81 /* |
| 82 * This functions maps higher priorities to lower nice values relative to the |
| 83 * nice value specified in the |nice| parameter. The corresponding relative |
| 84 * adjustments are: |
| 85 * |
| 86 * PR_PRIORITY_LOW +1 |
| 87 * PR_PRIORITY_NORMAL 0 |
| 88 * PR_PRIORITY_HIGH -1 |
| 89 * PR_PRIORITY_URGENT -2 |
| 90 */ |
| 91 static int pt_RelativePriority(int nice, PRThreadPriority pri) |
| 92 { |
| 93 return nice + (1 - pri); |
| 94 } |
72 #endif | 95 #endif |
73 | 96 |
74 /* | 97 /* |
75 ** Initialize a stack for a native pthread thread | 98 ** Initialize a stack for a native pthread thread |
76 */ | 99 */ |
77 static void _PR_InitializeStack(PRThreadStack *ts) | 100 static void _PR_InitializeStack(PRThreadStack *ts) |
78 { | 101 { |
79 if( ts && (ts->stackTop == 0) ) { | 102 if( ts && (ts->stackTop == 0) ) { |
80 ts->allocBase = (char *) &ts; | 103 ts->allocBase = (char *) &ts; |
81 ts->allocSize = ts->stackSize; | 104 ts->allocSize = ts->stackSize; |
82 | 105 |
83 /* | 106 /* |
84 ** Setup stackTop and stackBottom values. | 107 ** Setup stackTop and stackBottom values. |
85 */ | 108 */ |
86 #ifdef HAVE_STACK_GROWING_UP | 109 #ifdef HAVE_STACK_GROWING_UP |
87 ts->stackBottom = ts->allocBase + ts->stackSize; | 110 ts->stackBottom = ts->allocBase + ts->stackSize; |
88 ts->stackTop = ts->allocBase; | 111 ts->stackTop = ts->allocBase; |
89 #else | 112 #else |
90 ts->stackTop = ts->allocBase; | 113 ts->stackTop = ts->allocBase; |
91 ts->stackBottom = ts->allocBase - ts->stackSize; | 114 ts->stackBottom = ts->allocBase - ts->stackSize; |
92 #endif | 115 #endif |
93 } | 116 } |
94 } | 117 } |
95 | 118 |
96 static void *_pt_root(void *arg) | 119 static void *_pt_root(void *arg) |
97 { | 120 { |
98 PRIntn rv; | 121 PRIntn rv; |
99 PRThread *thred = (PRThread*)arg; | 122 PRThread *thred = (PRThread*)arg; |
100 PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE; | 123 PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE; |
| 124 #ifdef _PR_NICE_PRIORITY_SCHEDULING |
| 125 pid_t tid; |
| 126 #endif |
101 | 127 |
102 /* | 128 /* |
103 * Both the parent thread and this new thread set thred->id. | 129 * Both the parent thread and this new thread set thred->id. |
104 * The new thread must ensure that thred->id is set before | 130 * The new thread must ensure that thred->id is set before |
105 * it executes its startFunc. The parent thread must ensure | 131 * it executes its startFunc. The parent thread must ensure |
106 * that thred->id is set before PR_CreateThread() returns. | 132 * that thred->id is set before PR_CreateThread() returns. |
107 * Both threads set thred->id without holding a lock. Since | 133 * Both threads set thred->id without holding a lock. Since |
108 * they are writing the same value, this unprotected double | 134 * they are writing the same value, this unprotected double |
109 * write should be safe. | 135 * write should be safe. |
110 */ | 136 */ |
111 thred->id = pthread_self(); | 137 thred->id = pthread_self(); |
112 | 138 |
| 139 #ifdef _PR_NICE_PRIORITY_SCHEDULING |
| 140 /* |
| 141 * We need to know the kernel thread ID of each thread in order to |
| 142 * set its nice value hence we do it here instead of at creation time. |
| 143 */ |
| 144 tid = gettid(); |
| 145 errno = 0; |
| 146 rv = getpriority(PRIO_PROCESS, 0); |
| 147 |
| 148 /* If we cannot read the main thread's nice value don't try to change the |
| 149 * new thread's nice value. */ |
| 150 if (errno == 0) { |
| 151 setpriority(PRIO_PROCESS, tid, |
| 152 pt_RelativePriority(rv, thred->priority)); |
| 153 } |
| 154 |
| 155 PR_Lock(pt_book.ml); |
| 156 thred->tid = tid; |
| 157 PR_NotifyAllCondVar(pt_book.cv); |
| 158 PR_Unlock(pt_book.ml); |
| 159 #endif |
| 160 |
113 /* | 161 /* |
114 ** DCE Threads can't detach during creation, so do it late. | 162 ** DCE Threads can't detach during creation, so do it late. |
115 ** I would like to do it only here, but that doesn't seem | 163 ** I would like to do it only here, but that doesn't seem |
116 ** to work. | 164 ** to work. |
117 */ | 165 */ |
118 #if defined(_PR_DCETHREADS) | 166 #if defined(_PR_DCETHREADS) |
119 if (detached) | 167 if (detached) |
120 { | 168 { |
121 /* pthread_detach() modifies its argument, so we must pass a copy */ | 169 /* pthread_detach() modifies its argument, so we must pass a copy */ |
122 pthread_t self = thred->id; | 170 pthread_t self = thred->id; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 if (!_pr_initialized) return NULL; | 265 if (!_pr_initialized) return NULL; |
218 | 266 |
219 /* PR_NEWZAP must not call PR_GetCurrentThread() */ | 267 /* PR_NEWZAP must not call PR_GetCurrentThread() */ |
220 thred = PR_NEWZAP(PRThread); | 268 thred = PR_NEWZAP(PRThread); |
221 if (NULL != thred) | 269 if (NULL != thred) |
222 { | 270 { |
223 int rv; | 271 int rv; |
224 | 272 |
225 thred->priority = PR_PRIORITY_NORMAL; | 273 thred->priority = PR_PRIORITY_NORMAL; |
226 thred->id = pthread_self(); | 274 thred->id = pthread_self(); |
| 275 #ifdef _PR_NICE_PRIORITY_SCHEDULING |
| 276 thred->tid = gettid(); |
| 277 #endif |
227 rv = pthread_setspecific(pt_book.key, thred); | 278 rv = pthread_setspecific(pt_book.key, thred); |
228 PR_ASSERT(0 == rv); | 279 PR_ASSERT(0 == rv); |
229 | 280 |
230 thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN; | 281 thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN; |
231 PR_Lock(pt_book.ml); | 282 PR_Lock(pt_book.ml); |
232 | 283 |
233 /* then put it into the list */ | 284 /* then put it into the list */ |
234 thred->prev = pt_book.last; | 285 thred->prev = pt_book.last; |
235 if (pt_book.last) | 286 if (pt_book.last) |
236 pt_book.last->next = thred; | 287 pt_book.last->next = thred; |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 if (EPERM == rv) | 688 if (EPERM == rv) |
638 { | 689 { |
639 pt_schedpriv = EPERM; | 690 pt_schedpriv = EPERM; |
640 PR_LOG(_pr_thread_lm, PR_LOG_MIN, | 691 PR_LOG(_pr_thread_lm, PR_LOG_MIN, |
641 ("PR_SetThreadPriority: no thread schedu
ling privilege")); | 692 ("PR_SetThreadPriority: no thread schedu
ling privilege")); |
642 } | 693 } |
643 } | 694 } |
644 if (rv != 0) | 695 if (rv != 0) |
645 rv = -1; | 696 rv = -1; |
646 } | 697 } |
| 698 #elif defined(_PR_NICE_PRIORITY_SCHEDULING) |
| 699 PR_Lock(pt_book.ml); |
| 700 while (thred->tid == 0) |
| 701 PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); |
| 702 PR_Unlock(pt_book.ml); |
| 703 |
| 704 errno = 0; |
| 705 rv = getpriority(PRIO_PROCESS, 0); |
| 706 |
| 707 /* Do not proceed unless we know the main thread's nice value. */ |
| 708 if (errno == 0) { |
| 709 rv = setpriority(PRIO_PROCESS, thred->tid, |
| 710 pt_RelativePriority(rv, newPri)); |
| 711 |
| 712 if (rv == -1) |
| 713 { |
| 714 /* We don't set pt_schedpriv to EPERM in case errno == EPERM |
| 715 * because adjusting the nice value might be permitted for certain |
| 716 * ranges but not for others. */ |
| 717 PR_LOG(_pr_thread_lm, PR_LOG_MIN, |
| 718 ("PR_SetThreadPriority: setpriority failed with error %d", |
| 719 errno)); |
| 720 } |
| 721 } |
647 #endif | 722 #endif |
648 | 723 |
649 thred->priority = newPri; | 724 thred->priority = newPri; |
650 } /* PR_SetThreadPriority */ | 725 } /* PR_SetThreadPriority */ |
651 | 726 |
652 PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred) | 727 PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred) |
653 { | 728 { |
654 /* | 729 /* |
655 ** If the target thread indicates that it's waiting, | 730 ** If the target thread indicates that it's waiting, |
656 ** find the condition and broadcast to it. Broadcast | 731 ** find the condition and broadcast to it. Broadcast |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 #endif /* defined(DEBUG) */ | 884 #endif /* defined(DEBUG) */ |
810 PR_Free(thred); | 885 PR_Free(thred); |
811 } /* _pt_thread_death */ | 886 } /* _pt_thread_death */ |
812 | 887 |
813 void _PR_InitThreads( | 888 void _PR_InitThreads( |
814 PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) | 889 PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) |
815 { | 890 { |
816 int rv; | 891 int rv; |
817 PRThread *thred; | 892 PRThread *thred; |
818 | 893 |
| 894 PR_ASSERT(priority == PR_PRIORITY_NORMAL); |
| 895 |
819 #ifdef _PR_NEED_PTHREAD_INIT | 896 #ifdef _PR_NEED_PTHREAD_INIT |
820 /* | 897 /* |
821 * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily | 898 * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily |
822 * initialized, but pthread_self() fails to initialize | 899 * initialized, but pthread_self() fails to initialize |
823 * pthreads and hence returns a null thread ID if invoked | 900 * pthreads and hence returns a null thread ID if invoked |
824 * by the primordial thread before any other pthread call. | 901 * by the primordial thread before any other pthread call. |
825 * So we explicitly initialize pthreads here. | 902 * So we explicitly initialize pthreads here. |
826 */ | 903 */ |
827 pthread_init(); | 904 pthread_init(); |
828 #endif | 905 #endif |
(...skipping 26 matching lines...) Expand all Loading... |
855 pt_book.ml = PR_NewLock(); | 932 pt_book.ml = PR_NewLock(); |
856 PR_ASSERT(NULL != pt_book.ml); | 933 PR_ASSERT(NULL != pt_book.ml); |
857 pt_book.cv = PR_NewCondVar(pt_book.ml); | 934 pt_book.cv = PR_NewCondVar(pt_book.ml); |
858 PR_ASSERT(NULL != pt_book.cv); | 935 PR_ASSERT(NULL != pt_book.cv); |
859 thred = PR_NEWZAP(PRThread); | 936 thred = PR_NEWZAP(PRThread); |
860 PR_ASSERT(NULL != thred); | 937 PR_ASSERT(NULL != thred); |
861 thred->arg = NULL; | 938 thred->arg = NULL; |
862 thred->startFunc = NULL; | 939 thred->startFunc = NULL; |
863 thred->priority = priority; | 940 thred->priority = priority; |
864 thred->id = pthread_self(); | 941 thred->id = pthread_self(); |
| 942 #ifdef _PR_NICE_PRIORITY_SCHEDULING |
| 943 thred->tid = gettid(); |
| 944 #endif |
865 | 945 |
866 thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD); | 946 thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD); |
867 if (PR_SYSTEM_THREAD == type) | 947 if (PR_SYSTEM_THREAD == type) |
868 { | 948 { |
869 thred->state |= PT_THREAD_SYSTEM; | 949 thred->state |= PT_THREAD_SYSTEM; |
870 pt_book.system += 1; | 950 pt_book.system += 1; |
871 pt_book.this_many = 0; | 951 pt_book.this_many = 0; |
872 } | 952 } |
873 else | 953 else |
874 { | 954 { |
(...skipping 20 matching lines...) Expand all Loading... |
895 * More info - the problem is that pthreads calls the destructor | 975 * More info - the problem is that pthreads calls the destructor |
896 * eagerly as the thread returns from its root, rather than lazily | 976 * eagerly as the thread returns from its root, rather than lazily |
897 * after the thread is joined. Therefore, threads that are joining | 977 * after the thread is joined. Therefore, threads that are joining |
898 * and holding PRThread references are actually holding pointers to | 978 * and holding PRThread references are actually holding pointers to |
899 * nothing. | 979 * nothing. |
900 */ | 980 */ |
901 rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death); | 981 rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death); |
902 PR_ASSERT(0 == rv); | 982 PR_ASSERT(0 == rv); |
903 rv = pthread_setspecific(pt_book.key, thred); | 983 rv = pthread_setspecific(pt_book.key, thred); |
904 PR_ASSERT(0 == rv); | 984 PR_ASSERT(0 == rv); |
905 PR_SetThreadPriority(thred, priority); | |
906 } /* _PR_InitThreads */ | 985 } /* _PR_InitThreads */ |
907 | 986 |
908 #ifdef __GNUC__ | 987 #ifdef __GNUC__ |
909 /* | 988 /* |
910 * GCC supports the constructor and destructor attributes as of | 989 * GCC supports the constructor and destructor attributes as of |
911 * version 2.5. | 990 * version 2.5. |
912 */ | 991 */ |
913 static void _PR_Fini(void) __attribute__ ((destructor)); | 992 static void _PR_Fini(void) __attribute__ ((destructor)); |
914 #elif defined(__SUNPRO_C) | 993 #elif defined(__SUNPRO_C) |
915 /* | 994 /* |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1695 PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) | 1774 PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) |
1696 { | 1775 { |
1697 if (!thread) | 1776 if (!thread) |
1698 return NULL; | 1777 return NULL; |
1699 return thread->name; | 1778 return thread->name; |
1700 } | 1779 } |
1701 | 1780 |
1702 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ | 1781 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ |
1703 | 1782 |
1704 /* ptthread.c */ | 1783 /* ptthread.c */ |
OLD | NEW |