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