# HG changeset patch # User phh # Date 1327626366 18000 # Node ID de268c8a8075ceffd5d6896f8fbc8603e70cd641 # Parent 6db63e782d3d076df3311cf165849211ff8e9eb9 7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11 Summary: Add CriticalPriority == MaxPriority+1 and enable scheduling class as well as thread priority to change on Solaris. Reviewed-by: dholmes, dcubed diff -r 6db63e782d3d -r de268c8a8075 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3589,26 +3589,28 @@ // It is only used when ThreadPriorityPolicy=1 and requires root privilege. #if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 19, // 0 Entry should never be used 0, // 1 MinPriority 3, // 2 6, // 3 - 10, // 4 - 15, // 5 NormPriority - 18, // 6 - - 21, // 7 - 25, // 8 - 28, // 9 NearMaxPriority - - 31 // 10 MaxPriority + 10, // 4 + 15, // 5 NormPriority + 18, // 6 + + 21, // 7 + 25, // 8 + 28, // 9 NearMaxPriority + + 31, // 10 MaxPriority + + 31 // 11 CriticalPriority }; #elif defined(__APPLE__) /* Using Mach high-level priority assignments */ -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 0, // 0 Entry should never be used (MINPRI_USER) 27, // 1 MinPriority @@ -3623,10 +3625,12 @@ 34, // 8 35, // 9 NearMaxPriority - 36 // 10 MaxPriority + 36, // 10 MaxPriority + + 36 // 11 CriticalPriority }; #else -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 19, // 0 Entry should never be used 4, // 1 MinPriority @@ -3641,7 +3645,9 @@ -3, // 8 -4, // 9 NearMaxPriority - -5 // 10 MaxPriority + -5, // 10 MaxPriority + + -5 // 11 CriticalPriority }; #endif @@ -3657,6 +3663,9 @@ ThreadPriorityPolicy = 0; } } + if (UseCriticalJavaThreadPriority) { + os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority]; + } return 0; } diff -r 6db63e782d3d -r de268c8a8075 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/os/linux/vm/os_linux.cpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3383,7 +3383,7 @@ // this reason, the code should not be used as default (ThreadPriorityPolicy=0). // It is only used when ThreadPriorityPolicy=1 and requires root privilege. -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 19, // 0 Entry should never be used 4, // 1 MinPriority @@ -3398,7 +3398,9 @@ -3, // 8 -4, // 9 NearMaxPriority - -5 // 10 MaxPriority + -5, // 10 MaxPriority + + -5 // 11 CriticalPriority }; static int prio_init() { @@ -3413,6 +3415,9 @@ ThreadPriorityPolicy = 0; } } + if (UseCriticalJavaThreadPriority) { + os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority]; + } return 0; } diff -r 6db63e782d3d -r de268c8a8075 src/os/solaris/vm/osThread_solaris.hpp --- a/src/os/solaris/vm/osThread_solaris.hpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/os/solaris/vm/osThread_solaris.hpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,17 +28,17 @@ // This is embedded via include into the class OSThread private: - - thread_t _thread_id; // Solaris thread id - unsigned int _lwp_id; // lwp ID, only used with bound threads - sigset_t _caller_sigmask; // Caller's signal mask - bool _vm_created_thread; // true if the VM create this thread - // false if primary thread or attached thread + thread_t _thread_id; // Solaris thread id + uint _lwp_id; // lwp ID, only used with bound threads + int _native_priority; // Saved native priority when starting + // a bound thread + sigset_t _caller_sigmask; // Caller's signal mask + bool _vm_created_thread; // true if the VM created this thread, + // false if primary thread or attached thread public: - - thread_t thread_id() const { return _thread_id; } - - unsigned int lwp_id() const { return _lwp_id; } + thread_t thread_id() const { return _thread_id; } + uint lwp_id() const { return _lwp_id; } + int native_priority() const { return _native_priority; } // Set and get state of _vm_created_thread flag void set_vm_created() { _vm_created_thread = true; } @@ -62,8 +62,9 @@ return true; } #endif - void set_thread_id(thread_t id) { _thread_id = id; } - void set_lwp_id(unsigned int id){ _lwp_id = id; } + void set_thread_id(thread_t id) { _thread_id = id; } + void set_lwp_id(uint id) { _lwp_id = id; } + void set_native_priority(int prio) { _native_priority = prio; } // *************************************************************** // interrupt support. interrupts (using signals) are used to get diff -r 6db63e782d3d -r de268c8a8075 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,7 @@ # include # include # include +# include # include # include # include @@ -129,8 +130,8 @@ #ifdef _GNU_SOURCE // See bug #6514594 extern "C" int madvise(caddr_t, size_t, int); -extern "C" int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg, - int attr, int mask); +extern "C" int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg, + int attr, int mask); #endif //_GNU_SOURCE /* @@ -215,8 +216,9 @@ #define MaximumPriority 127 // Values for ThreadPriorityPolicy == 1 -int prio_policy1[MaxPriority+1] = { -99999, 0, 16, 32, 48, 64, - 80, 96, 112, 124, 127 }; +int prio_policy1[CriticalPriority+1] = { + -99999, 0, 16, 32, 48, 64, + 80, 96, 112, 124, 127, 127 }; // System parameters used internally static clock_t clock_tics_per_sec = 100; @@ -1048,15 +1050,22 @@ } // If the creator called set priority before we started, - // we need to call set priority now that we have an lwp. - // Get the priority from libthread and set the priority - // for the new Solaris lwp. + // we need to call set_native_priority now that we have an lwp. + // We used to get the priority from thr_getprio (we called + // thr_setprio way back in create_thread) and pass it to + // set_native_priority, but Solaris scales the priority + // in java_to_os_priority, so when we read it back here, + // we pass trash to set_native_priority instead of what's + // in java_to_os_priority. So we save the native priority + // in the osThread and recall it here. + if ( osthr->thread_id() != -1 ) { if ( UseThreadPriorities ) { - thr_getprio(osthr->thread_id(), &prio); + int prio = osthr->native_priority(); if (ThreadPriorityVerbose) { - tty->print_cr("Starting Thread " INTPTR_FORMAT ", LWP is " INTPTR_FORMAT ", setting priority: %d\n", - osthr->thread_id(), osthr->lwp_id(), prio ); + tty->print_cr("Starting Thread " INTPTR_FORMAT ", LWP is " + INTPTR_FORMAT ", setting priority: %d\n", + osthr->thread_id(), osthr->lwp_id(), prio); } os::set_native_priority(thread, prio); } @@ -1353,13 +1362,12 @@ // Remember that we created this thread so we can set priority on it osthread->set_vm_created(); - // Set the default thread priority otherwise use NormalPriority - - if ( UseThreadPriorities ) { - thr_setprio(tid, (DefaultThreadPriority == -1) ? + // Set the default thread priority. If using bound threads, setting + // lwp priority will be delayed until thread start. + set_native_priority(thread, + DefaultThreadPriority == -1 ? java_to_os_priority[NormPriority] : DefaultThreadPriority); - } // Initial thread state is INITIALIZED, not SUSPENDED osthread->set_state(INITIALIZED); @@ -3728,7 +3736,7 @@ } SchedInfo; -static SchedInfo tsLimits, iaLimits, rtLimits; +static SchedInfo tsLimits, iaLimits, rtLimits, fxLimits; #ifdef ASSERT static int ReadBackValidate = 1; @@ -3739,6 +3747,8 @@ static int myCur = 0; static bool priocntl_enable = false; +static const int criticalPrio = 60; // FX/60 is critical thread class/priority on T4 +static int java_MaxPriority_to_os_priority = 0; // Saved mapping // Call the version of priocntl suitable for all supported versions // of Solaris. We need to call through this wrapper so that we can @@ -3783,19 +3793,27 @@ if (os::Solaris::T2_libthread() || UseBoundThreads) { // If ThreadPriorityPolicy is 1, switch tables if (ThreadPriorityPolicy == 1) { - for (i = 0 ; i < MaxPriority+1; i++) + for (i = 0 ; i < CriticalPriority+1; i++) os::java_to_os_priority[i] = prio_policy1[i]; } + if (UseCriticalJavaThreadPriority) { + // MaxPriority always maps to the FX scheduling class and criticalPrio. + // See set_native_priority() and set_lwp_class_and_priority(). + // Save original MaxPriority mapping in case attempt to + // use critical priority fails. + java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority]; + // Set negative to distinguish from other priorities + os::java_to_os_priority[MaxPriority] = -criticalPrio; + } } // Not using Bound Threads, set to ThreadPolicy 1 else { - for ( i = 0 ; i < MaxPriority+1; i++ ) { + for ( i = 0 ; i < CriticalPriority+1; i++ ) { os::java_to_os_priority[i] = prio_policy1[i]; } return 0; } - // Get IDs for a set of well-known scheduling classes. // TODO-FIXME: GETCLINFO returns the current # of classes in the // the system. We should have a loop that iterates over the @@ -3828,24 +3846,33 @@ rtLimits.maxPrio = ((rtinfo_t*)ClassInfo.pc_clinfo)->rt_maxpri; rtLimits.minPrio = 0; + strcpy(ClassInfo.pc_clname, "FX"); + ClassInfo.pc_cid = -1; + rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); + if (rslt < 0) return errno; + assert(ClassInfo.pc_cid != -1, "cid for FX class is -1"); + fxLimits.schedPolicy = ClassInfo.pc_cid; + fxLimits.maxPrio = ((fxinfo_t*)ClassInfo.pc_clinfo)->fx_maxupri; + fxLimits.minPrio = 0; // Query our "current" scheduling class. - // This will normally be IA,TS or, rarely, RT. - memset (&ParmInfo, 0, sizeof(ParmInfo)); + // This will normally be IA, TS or, rarely, FX or RT. + memset(&ParmInfo, 0, sizeof(ParmInfo)); ParmInfo.pc_cid = PC_CLNULL; - rslt = (*priocntl_ptr) (PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo ); - if ( rslt < 0 ) return errno; + rslt = (*priocntl_ptr) (PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo); + if (rslt < 0) return errno; myClass = ParmInfo.pc_cid; // We now know our scheduling classId, get specific information - // the class. + // about the class. ClassInfo.pc_cid = myClass; ClassInfo.pc_clname[0] = 0; - rslt = (*priocntl_ptr) (PC_VERSION, (idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo ); - if ( rslt < 0 ) return errno; - - if (ThreadPriorityVerbose) - tty->print_cr ("lwp_priocntl_init: Class=%d(%s)...", myClass, ClassInfo.pc_clname); + rslt = (*priocntl_ptr) (PC_VERSION, (idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo); + if (rslt < 0) return errno; + + if (ThreadPriorityVerbose) { + tty->print_cr("lwp_priocntl_init: Class=%d(%s)...", myClass, ClassInfo.pc_clname); + } memset(&ParmInfo, 0, sizeof(pcparms_t)); ParmInfo.pc_cid = PC_CLNULL; @@ -3865,6 +3892,11 @@ myMin = tsLimits.minPrio; myMax = tsLimits.maxPrio; myMax = MIN2(myMax, (int)tsInfo->ts_uprilim); // clamp - restrict + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) { + fxparms_t *fxInfo = (fxparms_t*)ParmInfo.pc_clparms; + myMin = fxLimits.minPrio; + myMax = fxLimits.maxPrio; + myMax = MIN2(myMax, (int)fxInfo->fx_uprilim); // clamp - restrict } else { // No clue - punt if (ThreadPriorityVerbose) @@ -3872,8 +3904,9 @@ return EINVAL; // no clue, punt } - if (ThreadPriorityVerbose) - tty->print_cr ("Thread priority Range: [%d..%d]\n", myMin, myMax); + if (ThreadPriorityVerbose) { + tty->print_cr ("Thread priority Range: [%d..%d]\n", myMin, myMax); + } priocntl_enable = true; // Enable changing priorities return 0; @@ -3882,6 +3915,7 @@ #define IAPRI(x) ((iaparms_t *)((x).pc_clparms)) #define RTPRI(x) ((rtparms_t *)((x).pc_clparms)) #define TSPRI(x) ((tsparms_t *)((x).pc_clparms)) +#define FXPRI(x) ((fxparms_t *)((x).pc_clparms)) // scale_to_lwp_priority @@ -3900,13 +3934,13 @@ } -// set_lwp_priority +// set_lwp_class_and_priority // -// Set the priority of the lwp. This call should only be made -// when using bound threads (T2 threads are bound by default). +// Set the class and priority of the lwp. This call should only +// be made when using bound threads (T2 threads are bound by default). // -int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) -{ +int set_lwp_class_and_priority(int ThreadID, int lwpid, + int newPrio, int new_class, bool scale) { int rslt; int Actual, Expected, prv; pcparms_t ParmInfo; // for GET-SET @@ -3927,19 +3961,20 @@ return EINVAL; } - // If lwp hasn't started yet, just return // the _start routine will call us again. if ( lwpid <= 0 ) { if (ThreadPriorityVerbose) { - tty->print_cr ("deferring the set_lwp_priority of thread " INTPTR_FORMAT " to %d, lwpid not set", + tty->print_cr ("deferring the set_lwp_class_and_priority of thread " + INTPTR_FORMAT " to %d, lwpid not set", ThreadID, newPrio); } return 0; } if (ThreadPriorityVerbose) { - tty->print_cr ("set_lwp_priority(" INTPTR_FORMAT "@" INTPTR_FORMAT " %d) ", + tty->print_cr ("set_lwp_class_and_priority(" + INTPTR_FORMAT "@" INTPTR_FORMAT " %d) ", ThreadID, lwpid, newPrio); } @@ -3948,40 +3983,70 @@ rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo); if (rslt < 0) return errno; - if (ParmInfo.pc_cid == rtLimits.schedPolicy) { + int cur_class = ParmInfo.pc_cid; + ParmInfo.pc_cid = (id_t)new_class; + + if (new_class == rtLimits.schedPolicy) { rtparms_t *rtInfo = (rtparms_t*)ParmInfo.pc_clparms; - rtInfo->rt_pri = scale_to_lwp_priority (rtLimits.minPrio, rtLimits.maxPrio, newPrio); + rtInfo->rt_pri = scale ? scale_to_lwp_priority(rtLimits.minPrio, + rtLimits.maxPrio, newPrio) + : newPrio; rtInfo->rt_tqsecs = RT_NOCHANGE; rtInfo->rt_tqnsecs = RT_NOCHANGE; if (ThreadPriorityVerbose) { tty->print_cr("RT: %d->%d\n", newPrio, rtInfo->rt_pri); } - } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) { - iaparms_t *iaInfo = (iaparms_t*)ParmInfo.pc_clparms; - int maxClamped = MIN2(iaLimits.maxPrio, (int)iaInfo->ia_uprilim); - iaInfo->ia_upri = scale_to_lwp_priority(iaLimits.minPrio, maxClamped, newPrio); - iaInfo->ia_uprilim = IA_NOCHANGE; + } else if (new_class == iaLimits.schedPolicy) { + iaparms_t* iaInfo = (iaparms_t*)ParmInfo.pc_clparms; + int maxClamped = MIN2(iaLimits.maxPrio, + cur_class == new_class + ? (int)iaInfo->ia_uprilim : iaLimits.maxPrio); + iaInfo->ia_upri = scale ? scale_to_lwp_priority(iaLimits.minPrio, + maxClamped, newPrio) + : newPrio; + iaInfo->ia_uprilim = cur_class == new_class + ? IA_NOCHANGE : (pri_t)iaLimits.maxPrio; iaInfo->ia_mode = IA_NOCHANGE; + iaInfo->ia_nice = cur_class == new_class ? IA_NOCHANGE : NZERO; if (ThreadPriorityVerbose) { - tty->print_cr ("IA: [%d...%d] %d->%d\n", - iaLimits.minPrio, maxClamped, newPrio, iaInfo->ia_upri); + tty->print_cr("IA: [%d...%d] %d->%d\n", + iaLimits.minPrio, maxClamped, newPrio, iaInfo->ia_upri); } - } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) { - tsparms_t *tsInfo = (tsparms_t*)ParmInfo.pc_clparms; - int maxClamped = MIN2(tsLimits.maxPrio, (int)tsInfo->ts_uprilim); - prv = tsInfo->ts_upri; - tsInfo->ts_upri = scale_to_lwp_priority(tsLimits.minPrio, maxClamped, newPrio); - tsInfo->ts_uprilim = IA_NOCHANGE; + } else if (new_class == tsLimits.schedPolicy) { + tsparms_t* tsInfo = (tsparms_t*)ParmInfo.pc_clparms; + int maxClamped = MIN2(tsLimits.maxPrio, + cur_class == new_class + ? (int)tsInfo->ts_uprilim : tsLimits.maxPrio); + tsInfo->ts_upri = scale ? scale_to_lwp_priority(tsLimits.minPrio, + maxClamped, newPrio) + : newPrio; + tsInfo->ts_uprilim = cur_class == new_class + ? TS_NOCHANGE : (pri_t)tsLimits.maxPrio; if (ThreadPriorityVerbose) { - tty->print_cr ("TS: %d [%d...%d] %d->%d\n", - prv, tsLimits.minPrio, maxClamped, newPrio, tsInfo->ts_upri); + tty->print_cr("TS: [%d...%d] %d->%d\n", + tsLimits.minPrio, maxClamped, newPrio, tsInfo->ts_upri); } - if (prv == tsInfo->ts_upri) return 0; + } else if (new_class == fxLimits.schedPolicy) { + fxparms_t* fxInfo = (fxparms_t*)ParmInfo.pc_clparms; + int maxClamped = MIN2(fxLimits.maxPrio, + cur_class == new_class + ? (int)fxInfo->fx_uprilim : fxLimits.maxPrio); + fxInfo->fx_upri = scale ? scale_to_lwp_priority(fxLimits.minPrio, + maxClamped, newPrio) + : newPrio; + fxInfo->fx_uprilim = cur_class == new_class + ? FX_NOCHANGE : (pri_t)fxLimits.maxPrio; + fxInfo->fx_tqsecs = FX_NOCHANGE; + fxInfo->fx_tqnsecs = FX_NOCHANGE; + if (ThreadPriorityVerbose) { + tty->print_cr("FX: [%d...%d] %d->%d\n", + fxLimits.minPrio, maxClamped, newPrio, fxInfo->fx_upri); + } } else { - if ( ThreadPriorityVerbose ) { - tty->print_cr ("Unknown scheduling class\n"); + if (ThreadPriorityVerbose) { + tty->print_cr("Unknown new scheduling class %d\n", new_class); } - return EINVAL; // no clue, punt + return EINVAL; // no clue, punt } rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo); @@ -4016,16 +4081,20 @@ } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) { Actual = TSPRI(ReadBack)->ts_upri; Expected = TSPRI(ParmInfo)->ts_upri; + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) { + Actual = FXPRI(ReadBack)->fx_upri; + Expected = FXPRI(ParmInfo)->fx_upri; } else { - if ( ThreadPriorityVerbose ) { - tty->print_cr("set_lwp_priority: unexpected class in readback: %d\n", ParmInfo.pc_cid); + if (ThreadPriorityVerbose) { + tty->print_cr("set_lwp_class_and_priority: unexpected class in readback: %d\n", + ParmInfo.pc_cid); } } if (Actual != Expected) { - if ( ThreadPriorityVerbose ) { - tty->print_cr ("set_lwp_priority(%d %d) Class=%d: actual=%d vs expected=%d\n", - lwpid, newPrio, ReadBack.pc_cid, Actual, Expected); + if (ThreadPriorityVerbose) { + tty->print_cr ("set_lwp_class_and_priority(%d %d) Class=%d: actual=%d vs expected=%d\n", + lwpid, newPrio, ReadBack.pc_cid, Actual, Expected); } } #endif @@ -4033,8 +4102,6 @@ return 0; } - - // Solaris only gives access to 128 real priorities at a time, // so we expand Java's ten to fill this range. This would be better // if we dynamically adjusted relative priorities. @@ -4055,8 +4122,7 @@ // which do not explicitly alter their thread priorities. // - -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { -99999, // 0 Entry should never be used 0, // 1 MinPriority @@ -4071,17 +4137,51 @@ 127, // 8 127, // 9 NearMaxPriority - 127 // 10 MaxPriority + 127, // 10 MaxPriority + + -criticalPrio // 11 CriticalPriority }; - OSReturn os::set_native_priority(Thread* thread, int newpri) { + OSThread* osthread = thread->osthread(); + + // Save requested priority in case the thread hasn't been started + osthread->set_native_priority(newpri); + + // Check for critical priority request + bool fxcritical = false; + if (newpri == -criticalPrio) { + fxcritical = true; + newpri = criticalPrio; + } + assert(newpri >= MinimumPriority && newpri <= MaximumPriority, "bad priority mapping"); - if ( !UseThreadPriorities ) return OS_OK; - int status = thr_setprio(thread->osthread()->thread_id(), newpri); - if ( os::Solaris::T2_libthread() || (UseBoundThreads && thread->osthread()->is_vm_created()) ) - status |= (set_lwp_priority (thread->osthread()->thread_id(), - thread->osthread()->lwp_id(), newpri )); + if (!UseThreadPriorities) return OS_OK; + + int status = 0; + + if (!fxcritical) { + // Use thr_setprio only if we have a priority that thr_setprio understands + status = thr_setprio(thread->osthread()->thread_id(), newpri); + } + + if (os::Solaris::T2_libthread() || + (UseBoundThreads && osthread->is_vm_created())) { + int lwp_status = + set_lwp_class_and_priority(osthread->thread_id(), + osthread->lwp_id(), + newpri, + fxcritical ? fxLimits.schedPolicy : myClass, + !fxcritical); + if (lwp_status != 0 && fxcritical) { + // Try again, this time without changing the scheduling class + newpri = java_MaxPriority_to_os_priority; + lwp_status = set_lwp_class_and_priority(osthread->thread_id(), + osthread->lwp_id(), + newpri, myClass, false); + } + status |= lwp_status; + } return (status == 0) ? OS_OK : OS_ERR; } diff -r 6db63e782d3d -r de268c8a8075 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/os/windows/vm/os_windows.cpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3296,7 +3296,7 @@ // so we compress Java's ten down to seven. It would be better // if we dynamically adjusted relative priorities. -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { THREAD_PRIORITY_IDLE, // 0 Entry should never be used THREAD_PRIORITY_LOWEST, // 1 MinPriority THREAD_PRIORITY_LOWEST, // 2 @@ -3307,10 +3307,11 @@ THREAD_PRIORITY_ABOVE_NORMAL, // 7 THREAD_PRIORITY_ABOVE_NORMAL, // 8 THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority - THREAD_PRIORITY_HIGHEST // 10 MaxPriority + THREAD_PRIORITY_HIGHEST, // 10 MaxPriority + THREAD_PRIORITY_HIGHEST // 11 CriticalPriority }; -int prio_policy1[MaxPriority + 1] = { +int prio_policy1[CriticalPriority + 1] = { THREAD_PRIORITY_IDLE, // 0 Entry should never be used THREAD_PRIORITY_LOWEST, // 1 MinPriority THREAD_PRIORITY_LOWEST, // 2 @@ -3321,17 +3322,21 @@ THREAD_PRIORITY_ABOVE_NORMAL, // 7 THREAD_PRIORITY_HIGHEST, // 8 THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority - THREAD_PRIORITY_TIME_CRITICAL // 10 MaxPriority + THREAD_PRIORITY_TIME_CRITICAL, // 10 MaxPriority + THREAD_PRIORITY_TIME_CRITICAL // 11 CriticalPriority }; static int prio_init() { // If ThreadPriorityPolicy is 1, switch tables if (ThreadPriorityPolicy == 1) { int i; - for (i = 0; i < MaxPriority + 1; i++) { + for (i = 0; i < CriticalPriority + 1; i++) { os::java_to_os_priority[i] = prio_policy1[i]; } } + if (UseCriticalJavaThreadPriority) { + os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority] ; + } return 0; } diff -r 6db63e782d3d -r de268c8a8075 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -855,23 +855,23 @@ // Note that this only sets the JavaThread _priority field, which by // definition is limited to Java priorities and not OS priorities. // The os-priority is set in the CompilerThread startup code itself + java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); - // CLEANUP PRIORITIES: This -if- statement hids a bug whereby the compiler - // threads never have their OS priority set. The assumption here is to - // enable the Performance group to do flag tuning, figure out a suitable - // CompilerThreadPriority, and then remove this 'if' statement (and - // comment) and unconditionally set the priority. + + // Note that we cannot call os::set_priority because it expects Java + // priorities and we are *explicitly* using OS priorities so that it's + // possible to set the compiler thread priority higher than any Java + // thread. - // Compiler Threads should be at the highest Priority - if ( CompilerThreadPriority != -1 ) - os::set_native_priority( compiler_thread, CompilerThreadPriority ); - else - os::set_native_priority( compiler_thread, os::java_to_os_priority[NearMaxPriority]); - - // Note that I cannot call os::set_priority because it expects Java - // priorities and I am *explicitly* using OS priorities so that it's - // possible to set the compiler thread priority higher than any Java - // thread. + int native_prio = CompilerThreadPriority; + if (native_prio == -1) { + if (UseCriticalCompilerThreadPriority) { + native_prio = os::java_to_os_priority[CriticalPriority]; + } else { + native_prio = os::java_to_os_priority[NearMaxPriority]; + } + } + os::set_native_priority(compiler_thread, native_prio); java_lang_Thread::set_daemon(thread_oop()); @@ -879,6 +879,7 @@ Threads::add(compiler_thread); Thread::start(compiler_thread); } + // Let go of Threads_lock before yielding os::yield(); // make sure that the compiler thread is started early (especially helpful on SOLARIS) diff -r 6db63e782d3d -r de268c8a8075 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,10 +75,25 @@ set_name("Concurrent Mark-Sweep GC Thread"); if (os::create_thread(this, os::cgc_thread)) { - // XXX: need to set this to low priority - // unless "agressive mode" set; priority - // should be just less than that of VMThread. - os::set_priority(this, NearMaxPriority); + // An old comment here said: "Priority should be just less + // than that of VMThread". Since the VMThread runs at + // NearMaxPriority, the old comment was inaccurate, but + // changing the default priority to NearMaxPriority-1 + // could change current behavior, so the default of + // NearMaxPriority stays in place. + // + // Note that there's a possibility of the VMThread + // starving if UseCriticalCMSThreadPriority is on. + // That won't happen on Solaris for various reasons, + // but may well happen on non-Solaris platforms. + int native_prio; + if (UseCriticalCMSThreadPriority) { + native_prio = os::java_to_os_priority[CriticalPriority]; + } else { + native_prio = os::java_to_os_priority[NearMaxPriority]; + } + os::set_native_priority(this, native_prio); + if (!DisableStartThread) { os::start_thread(this); } diff -r 6db63e782d3d -r de268c8a8075 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/share/vm/runtime/globals.hpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3477,16 +3477,19 @@ " Linux this policy requires root privilege.") \ \ product(bool, ThreadPriorityVerbose, false, \ - "print priority changes") \ + "Print priority changes") \ \ product(intx, DefaultThreadPriority, -1, \ - "what native priority threads run at if not specified elsewhere (-1 means no change)") \ + "The native priority at which threads run if not elsewhere " \ + "specified (-1 means no change)") \ \ product(intx, CompilerThreadPriority, -1, \ - "what priority should compiler threads run at (-1 means no change)") \ + "The native priority at which compiler threads should run " \ + "(-1 means no change)") \ \ product(intx, VMThreadPriority, -1, \ - "what priority should VM threads run at (-1 means no change)") \ + "The native priority at which the VM thread should run " \ + "(-1 means no change)") \ \ product(bool, CompilerThreadHintNoPreempt, true, \ "(Solaris only) Give compiler threads an extra quanta") \ @@ -3505,6 +3508,15 @@ product(intx, JavaPriority9_To_OSPriority, -1, "Map Java priorities to OS priorities") \ product(intx, JavaPriority10_To_OSPriority,-1, "Map Java priorities to OS priorities") \ \ + experimental(bool, UseCriticalJavaThreadPriority, false, \ + "Java thread priority 10 maps to critical scheduling priority") \ + \ + experimental(bool, UseCriticalCompilerThreadPriority, false, \ + "Compiler thread(s) run at critical scheduling priority") \ + \ + experimental(bool, UseCriticalCMSThreadPriority, false, \ + "ConcurrentMarkSweep thread runs at critical scheduling priority")\ + \ /* compiler debugging */ \ notproduct(intx, CompileTheWorldStartAt, 1, \ "First class to consider when using +CompileTheWorld") \ @@ -3871,7 +3883,7 @@ product(bool, UseVMInterruptibleIO, false, \ "(Unstable, Solaris-specific) Thread interrupt before or with " \ "EINTR for I/O operations results in OS_INTRPT. The default value"\ - " of this flag is true for JDK 6 and earliers") + " of this flag is true for JDK 6 and earlier") /* * Macros for factoring of globals diff -r 6db63e782d3d -r de268c8a8075 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Wed Jan 25 18:58:59 2012 -0800 +++ b/src/share/vm/runtime/os.hpp Thu Jan 26 20:06:06 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,8 +73,9 @@ MinPriority = 1, // Minimum priority NormPriority = 5, // Normal (non-daemon) priority NearMaxPriority = 9, // High priority, used for VMThread - MaxPriority = 10 // Highest priority, used for WatcherThread + MaxPriority = 10, // Highest priority, used for WatcherThread // ensures that VMThread doesn't starve profiler + CriticalPriority = 11 // Critical thread priority }; // Typedef for structured exception handling support @@ -733,7 +734,7 @@ // Thread priority helpers (implemented in OS-specific part) static OSReturn set_native_priority(Thread* thread, int native_prio); static OSReturn get_native_priority(const Thread* const thread, int* priority_ptr); - static int java_to_os_priority[MaxPriority + 1]; + static int java_to_os_priority[CriticalPriority + 1]; // Hint to the underlying OS that a task switch would not be good. // Void return because it's a hint and can fail. static void hint_no_preempt();