Bug 841651: Implement PR_SetThreadPriority() on Linux-based platforms

using per-thread nice values. The patch is contributed by Gabriele
Svelto <gsvelto@mozilla.com>. r=wtc.
Modified Files:
	configure configure.in pr/include/private/primpl.h
	pr/src/pthreads/ptthread.c


git-svn-id: svn://10.0.0.236/trunk@264795 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
wtc%google.com 2013-03-14 17:34:33 +00:00
parent 486e82c2e0
commit f3d6bd7194
4 changed files with 77 additions and 3 deletions

View File

@ -5621,7 +5621,7 @@ fi
_SAVE_LIBS="$LIBS"
LIBS="$LIBS $OS_LIBS"
for ac_func in lchown strerror dladdr
for ac_func in dladdr gettid lchown setpriority strerror syscall
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5628: checking for $ac_func" >&5

View File

@ -2588,7 +2588,7 @@ dnl ========================================================
AC_PROG_GCC_TRADITIONAL
_SAVE_LIBS="$LIBS"
LIBS="$LIBS $OS_LIBS"
AC_CHECK_FUNCS(lchown strerror dladdr)
AC_CHECK_FUNCS(dladdr gettid lchown setpriority strerror syscall)
LIBS="$_SAVE_LIBS"
dnl AC_FUNC_MEMCMP

View File

@ -50,6 +50,10 @@ typedef struct PRSegment PRSegment;
#include <sys/sem.h>
#endif
#ifdef HAVE_SYSCALL
#include <sys/syscall.h>
#endif
/*************************************************************************
***** A Word about Model Dependent Function Naming Convention ***********
*************************************************************************/
@ -186,6 +190,17 @@ typedef struct PTDebug
NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);
/*
* On Linux and its derivatives POSIX priority scheduling works only for
* real-time threads. On those platforms we set thread's nice values
* instead which requires us to track kernel thread IDs for each POSIX
* thread we create.
*/
#if defined(LINUX) && defined(HAVE_SETPRIORITY) && \
((defined(HAVE_SYSCALL) && defined(SYS_gettid)) || defined(HAVE_GETTID))
#define _PR_NICE_PRIORITY_SCHEDULING
#endif
#else /* defined(_PR_PTHREADS) */
NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);
@ -1540,6 +1555,9 @@ struct PRThread {
#if defined(_PR_PTHREADS)
pthread_t id; /* pthread identifier for the thread */
#ifdef _PR_NICE_PRIORITY_SCHEDULING
pid_t tid; /* Linux-specific kernel thread ID */
#endif
PRBool okToDelete; /* ok to delete the PRThread struct? */
PRCondVar *waiting; /* where the thread is waiting | NULL */
void *sp; /* recorded sp for garbage collection */

View File

@ -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.
@ -54,7 +62,9 @@ static void _pt_thread_death(void *arg);
static void _pt_thread_death_internal(void *arg, PRBool callDestructors);
static void init_pthread_gc_support(void);
#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
#if defined(_PR_DCETHREADS) || \
defined(_POSIX_THREAD_PRIORITY_SCHEDULING) || \
defined(_PR_NICE_PRIORITY_SCHEDULING)
static PRIntn pt_PriorityMap(PRThreadPriority pri)
{
#ifdef NTO
@ -64,6 +74,13 @@ static PRIntn pt_PriorityMap(PRThreadPriority pri)
* Jerry.Kirk@Nexwarecorp.com
*/
return 10;
#elif defined(_PR_NICE_PRIORITY_SCHEDULING)
/* This maps high priorities to low nice values:
* PR_PRIORITY_LOW 1
* PR_PRIORITY_NORMAL 0
* PR_PRIORITY_HIGH -1
* PR_PRIORITY_URGENT -2 */
return 1 - pri;
#else
return pt_book.minPrio +
pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST;
@ -98,6 +115,9 @@ static void *_pt_root(void *arg)
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,6 +130,21 @@ static void *_pt_root(void *arg)
*/
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 priority hence we do it here instead of at creation time.
*/
tid = gettid();
rv = setpriority(PRIO_PROCESS, tid, pt_PriorityMap(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
@ -224,6 +259,9 @@ static PRThread* pt_AttachThread(void)
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 +682,21 @@ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri
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);
rv = setpriority(PRIO_PROCESS, thred->tid, pt_PriorityMap(newPri));
if (rv == -1 && errno == EPERM)
{
/* We don't set pt_schedpriv to EPERM because adjusting the nice
* value might be permitted for certain ranges but not others */
PR_LOG(_pr_thread_lm, PR_LOG_MIN,
("PR_SetThreadPriority: no thread scheduling privilege"));
}
#endif
thred->priority = newPri;
@ -862,6 +915,9 @@ void _PR_InitThreads(
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)