Index: nspr/pr/src/pthreads/ptthread.c |
=================================================================== |
--- nspr/pr/src/pthreads/ptthread.c (revision 233722) |
+++ nspr/pr/src/pthreads/ptthread.c (working copy) |
@@ -28,6 +28,14 @@ |
#undef _POSIX_THREAD_PRIORITY_SCHEDULING |
#endif |
+#ifdef _PR_NICE_PRIORITY_SCHEDULING |
+#undef _POSIX_THREAD_PRIORITY_SCHEDULING |
+#include <sys/resource.h> |
+#ifndef HAVE_GETTID |
+#define gettid() (syscall(SYS_gettid)) |
+#endif |
+#endif |
+ |
/* |
* Record whether or not we have the privilege to set the scheduling |
* policy and priority of threads. 0 means that privilege is available. |
@@ -69,6 +77,21 @@ |
pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST; |
#endif |
} |
+#elif defined(_PR_NICE_PRIORITY_SCHEDULING) |
+/* |
+ * This functions maps higher priorities to lower nice values relative to the |
+ * nice value specified in the |nice| parameter. The corresponding relative |
+ * adjustments are: |
+ * |
+ * PR_PRIORITY_LOW +1 |
+ * PR_PRIORITY_NORMAL 0 |
+ * PR_PRIORITY_HIGH -1 |
+ * PR_PRIORITY_URGENT -2 |
+ */ |
+static int pt_RelativePriority(int nice, PRThreadPriority pri) |
+{ |
+ return nice + (1 - pri); |
+} |
#endif |
/* |
@@ -98,6 +121,9 @@ |
PRIntn rv; |
PRThread *thred = (PRThread*)arg; |
PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE; |
+#ifdef _PR_NICE_PRIORITY_SCHEDULING |
+ pid_t tid; |
+#endif |
/* |
* Both the parent thread and this new thread set thred->id. |
@@ -110,7 +136,29 @@ |
*/ |
thred->id = pthread_self(); |
+#ifdef _PR_NICE_PRIORITY_SCHEDULING |
/* |
+ * We need to know the kernel thread ID of each thread in order to |
+ * set its nice value hence we do it here instead of at creation time. |
+ */ |
+ tid = gettid(); |
+ errno = 0; |
+ rv = getpriority(PRIO_PROCESS, 0); |
+ |
+ /* If we cannot read the main thread's nice value don't try to change the |
+ * new thread's nice value. */ |
+ if (errno == 0) { |
+ setpriority(PRIO_PROCESS, tid, |
+ pt_RelativePriority(rv, thred->priority)); |
+ } |
+ |
+ PR_Lock(pt_book.ml); |
+ thred->tid = tid; |
+ PR_NotifyAllCondVar(pt_book.cv); |
+ PR_Unlock(pt_book.ml); |
+#endif |
+ |
+ /* |
** DCE Threads can't detach during creation, so do it late. |
** I would like to do it only here, but that doesn't seem |
** to work. |
@@ -224,6 +272,9 @@ |
thred->priority = PR_PRIORITY_NORMAL; |
thred->id = pthread_self(); |
+#ifdef _PR_NICE_PRIORITY_SCHEDULING |
+ thred->tid = gettid(); |
+#endif |
rv = pthread_setspecific(pt_book.key, thred); |
PR_ASSERT(0 == rv); |
@@ -644,6 +695,30 @@ |
if (rv != 0) |
rv = -1; |
} |
+#elif defined(_PR_NICE_PRIORITY_SCHEDULING) |
+ PR_Lock(pt_book.ml); |
+ while (thred->tid == 0) |
+ PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); |
+ PR_Unlock(pt_book.ml); |
+ |
+ errno = 0; |
+ rv = getpriority(PRIO_PROCESS, 0); |
+ |
+ /* Do not proceed unless we know the main thread's nice value. */ |
+ if (errno == 0) { |
+ rv = setpriority(PRIO_PROCESS, thred->tid, |
+ pt_RelativePriority(rv, newPri)); |
+ |
+ if (rv == -1) |
+ { |
+ /* We don't set pt_schedpriv to EPERM in case errno == EPERM |
+ * because adjusting the nice value might be permitted for certain |
+ * ranges but not for others. */ |
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN, |
+ ("PR_SetThreadPriority: setpriority failed with error %d", |
+ errno)); |
+ } |
+ } |
#endif |
thred->priority = newPri; |
@@ -816,6 +891,8 @@ |
int rv; |
PRThread *thred; |
+ PR_ASSERT(priority == PR_PRIORITY_NORMAL); |
+ |
#ifdef _PR_NEED_PTHREAD_INIT |
/* |
* On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily |
@@ -862,6 +939,9 @@ |
thred->startFunc = NULL; |
thred->priority = priority; |
thred->id = pthread_self(); |
+#ifdef _PR_NICE_PRIORITY_SCHEDULING |
+ thred->tid = gettid(); |
+#endif |
thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD); |
if (PR_SYSTEM_THREAD == type) |
@@ -902,7 +982,6 @@ |
PR_ASSERT(0 == rv); |
rv = pthread_setspecific(pt_book.key, thred); |
PR_ASSERT(0 == rv); |
- PR_SetThreadPriority(thred, priority); |
} /* _PR_InitThreads */ |
#ifdef __GNUC__ |