--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jan 25 18:58:59 2012 -0800
+++ b/hotspot/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 <sys/rtpriocntl.h>
# include <sys/tspriocntl.h>
# include <sys/iapriocntl.h>
+# include <sys/fxpriocntl.h>
# include <sys/loadavg.h>
# include <string.h>
# include <stdio.h>
@@ -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;
}