Re: [rvm-research] Implementation of setPriority/getPriority for RVMThread (RVM-750)
Carl Ritson <[email protected]>
| Newsgroups | gmane.comp.java.jikes.rvm.devel |
|---|---|
| Message-ID | <CAKDym5O_=_iZUF4os+3vX95fxC-O9t=PB=YX8gs4pk1LfhaMtw@mail.gmail.com> |
Hi, >> Would you like me to fix this and the above, and provide new patches? > > Please do so. I don't have access to an OS X machine, so it would be > great if you could check that pre-commit test run passes on your OS X > machine. Please find an updated version of the diff for this change. This passes checkstyle, makes the change to setPriority that was suggested and adds some basic tracing controlled by a new 'tracePriority' constant (same scheme as traceAcct). I've also run the pre-commit tests on OS X, all of which pass. Let me know if you'd like a copy of the test output. Kind regards, Carl ------------------------------------------------------------------------------ Get 100% visibility into Java/.NET code with AppDynamics Lite! It's a free troubleshooting tool designed for production. Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk _______________________________________________ Jikesrvm-researchers mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers
thread-priority-fixed.r10655.diff
(application/octet-stream, 8.5 KB)
diff -r 6ea4feda95a5 rvm/src/org/jikesrvm/VM.java
--- a/rvm/src/org/jikesrvm/VM.java Mon Jul 22 19:47:09 2013 +0200
+++ b/rvm/src/org/jikesrvm/VM.java Mon Aug 12 18:08:16 2013 +0100
@@ -160,6 +160,7 @@
//
sysCall.sysSetupHardwareTrapHandler();
RVMThread.getCurrentThread().pthread_id = sysCall.sysGetThreadId();
+ RVMThread.getCurrentThread().priority_handle = sysCall.sysGetThreadPriorityHandle();
RVMThread.availableProcessors = SysCall.sysCall.sysNumProcessors();
// Set up buffer locks used by Thread for logging and status dumping.
diff -r 6ea4feda95a5 rvm/src/org/jikesrvm/runtime/BootRecord.java
--- a/rvm/src/org/jikesrvm/runtime/BootRecord.java Mon Jul 22 19:47:09 2013 +0200
+++ b/rvm/src/org/jikesrvm/runtime/BootRecord.java Mon Aug 12 18:08:16 2013 +0100
@@ -262,6 +262,9 @@
public Address sysSetupHardwareTrapHandlerIP;
public Address sysStashVMThreadIP;
public Address sysThreadTerminateIP;
+ public Address sysGetThreadPriorityHandleIP;
+ public Address sysGetThreadPriorityIP;
+ public Address sysSetThreadPriorityIP;
// monitors
public Address sysMonitorCreateIP;
diff -r 6ea4feda95a5 rvm/src/org/jikesrvm/runtime/SysCall.java
--- a/rvm/src/org/jikesrvm/runtime/SysCall.java Mon Jul 22 19:47:09 2013 +0200
+++ b/rvm/src/org/jikesrvm/runtime/SysCall.java Mon Aug 12 18:08:16 2013 +0100
@@ -190,6 +190,15 @@
public abstract Word sysGetThreadId();
@SysCallTemplate
+ public abstract Word sysGetThreadPriorityHandle();
+
+ @SysCallTemplate
+ public abstract int sysGetThreadPriority(Word thread, Word handle);
+
+ @SysCallTemplate
+ public abstract int sysSetThreadPriority(Word thread, Word handle, int priority);
+
+ @SysCallTemplate
public abstract void sysSetupHardwareTrapHandler();
// This implies that the RVMThread is somehow pinned, or else the
diff -r 6ea4feda95a5 rvm/src/org/jikesrvm/scheduler/RVMThread.java
--- a/rvm/src/org/jikesrvm/scheduler/RVMThread.java Mon Jul 22 19:47:09 2013 +0200
+++ b/rvm/src/org/jikesrvm/scheduler/RVMThread.java Mon Aug 12 18:08:16 2013 +0100
@@ -180,6 +180,9 @@
/** Trace adjustments to stack size */
private static final boolean traceAdjustments = false;
+ /** Trace thread priority */
+ private static final boolean tracePriority = false;
+
/** Never kill threads. Useful for testing bugs related to interaction of
thread death with for example MMTk. For production, this should never
be set to true. */
@@ -1025,6 +1028,12 @@
public Word pthread_id;
/**
+ * Thread priority handle. Used when manipulating the threads priority.
+ * This may be different from pthread_id.
+ */
+ public Word priority_handle;
+
+ /**
* Scratch area for use for gpr <=> fpr transfers by PPC baseline compiler.
* Used to transfer x87 to SSE registers on IA32
*/
@@ -2590,6 +2599,14 @@
* get pthread_id from the operating system and store into RVMThread field
*/
currentThread.pthread_id = sysCall.sysGetThreadId();
+ currentThread.priority_handle = sysCall.sysGetThreadPriorityHandle();
+
+ /*
+ * set thread priority to match stored value
+ */
+ sysCall.sysSetThreadPriority(currentThread.pthread_id,
+ currentThread.priority_handle, currentThread.priority - Thread.NORM_PRIORITY);
+
currentThread.enableYieldpoints();
sysCall.sysStashVMThread(currentThread);
if (traceAcct) {
@@ -4471,6 +4488,13 @@
* @see java.lang.Thread#getPriority()
*/
public int getPriority() {
+ if (isAlive()) {
+ // compute current priority
+ priority = sysCall.sysGetThreadPriority(pthread_id, priority_handle) + Thread.NORM_PRIORITY;
+ }
+ if (tracePriority) {
+ VM.sysWriteln("Thread #", getThreadSlot(), " get priority returning: ", priority);
+ }
return priority;
}
@@ -4481,8 +4505,25 @@
* @see java.lang.Thread#getPriority()
*/
public void setPriority(int priority) {
- this.priority = priority;
- // @TODO this should be calling a syscall
+ if (isAlive()) {
+ int result = sysCall.sysSetThreadPriority(pthread_id, priority_handle, priority - Thread.NORM_PRIORITY);
+ if (result == 0) {
+ this.priority = priority;
+ if (tracePriority) {
+ VM.sysWriteln("Thread #", getThreadSlot(), " set priority: ", priority);
+ }
+ } else {
+ // setting priority failed
+ if (tracePriority) {
+ VM.sysWriteln("Thread #", getThreadSlot(), " failed to set priority: ", priority, ", result: ", result);
+ }
+ }
+ } else {
+ if (tracePriority) {
+ VM.sysWriteln("Thread #", getThreadSlot(), " set priority: ", priority, " while not running");
+ }
+ this.priority = priority;
+ }
}
/**
diff -r 6ea4feda95a5 tools/bootImageRunner/sys.C
--- a/tools/bootImageRunner/sys.C Mon Jul 22 19:47:09 2013 +0200
+++ b/tools/bootImageRunner/sys.C Mon Aug 12 18:08:16 2013 +0100
@@ -34,6 +34,11 @@
extern "C" int sched_yield(void);
#endif
+// Enable syscall on Linux / glibc
+#ifdef RVM_FOR_LINUX
+#define _GNU_SOURCE
+#endif
+
#include <stdio.h>
#include <stdlib.h> // getenv() and others
#include <unistd.h>
@@ -71,6 +76,7 @@
#include <sys/ioctl.h>
#ifdef RVM_FOR_LINUX
#include <asm/ioctls.h>
+#include <sys/syscall.h>
#endif
# include <sched.h>
@@ -1248,6 +1254,104 @@
#endif
}
+// Determine if a given thread can use pthread_setschedparam to
+// configure its priority, this is based on the current priority
+// of the thread.
+//
+// The result will be true on all systems other than Linux where
+// pthread_setschedparam cannot be used with SCHED_OTHER policy.
+//
+static int hasPthreadPriority(Word thread_id)
+{
+ struct sched_param param;
+ int policy;
+ if (!pthread_getschedparam((pthread_t)thread_id, &policy, ¶m)) {
+ int min = sched_get_priority_min(policy);
+ int max = sched_get_priority_max(policy);
+ if (min || max) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Return a handle which can be used to manipulate a threads priority
+// on Linux this will be the kernel thread_id, on other systems the
+// standard thread id.
+extern "C" Word
+sysGetThreadPriorityHandle()
+{
+ // gettid() syscall is Linux specific, detect its syscall number macro
+ #ifdef SYS_gettid
+ pid_t tid = (pid_t) syscall(SYS_gettid);
+ if (tid != -1)
+ return (Word) tid;
+ #endif /* SYS_gettid */
+ return (Word) getThreadId();
+}
+
+// Compute the default (or middle) priority for a given policy.
+static int defaultPriority(int policy)
+{
+ int min = sched_get_priority_min(policy);
+ int max = sched_get_priority_max(policy);
+ return min + ((max - min) / 2);
+}
+
+// Get the thread priority as an offset from the default.
+extern "C" int
+sysGetThreadPriority(Word thread, Word handle)
+{
+ // use pthread priority mechanisms where possible
+ if (hasPthreadPriority(thread)) {
+ struct sched_param param;
+ int policy;
+ if (!pthread_getschedparam((pthread_t)thread, &policy, ¶m)) {
+ return param.sched_priority - defaultPriority(policy);
+ }
+ } else if (thread != handle) {
+ // fallback to setpriority if handle is valid
+ // i.e. handle is tid from gettid()
+ int result;
+ errno = 0; // as result can be legally be -1
+ result = getpriority(PRIO_PROCESS, (int) handle);
+ if (errno == 0) {
+ // default priority is 0, low number -> high priority
+ return -result;
+ }
+
+ }
+ return 0;
+}
+
+// Set the thread priority as an offset from the default.
+extern "C" int
+sysSetThreadPriority(Word thread, Word handle, int priority)
+{
+ // fast path
+ if (sysGetThreadPriority(thread, handle) == priority)
+ return 0;
+
+ // use pthread priority mechanisms where possible
+ if (hasPthreadPriority(thread)) {
+ struct sched_param param;
+ int policy;
+ int result = pthread_getschedparam((pthread_t)thread, &policy, ¶m);
+ if (!result) {
+ param.sched_priority = defaultPriority(policy) + priority;
+ return pthread_setschedparam((pthread_t)thread, policy, ¶m);
+ } else {
+ return result;
+ }
+ } else if (thread != handle) {
+ // fallback to setpriority if handle is valid
+ // i.e. handle is tid from gettid()
+ // default priority is 0, low number -> high priority
+ return setpriority(PRIO_PROCESS, (int) handle, -priority);
+ }
+ return -1;
+}
+
////////////// Pthread mutex and condition functions /////////////
#ifndef RVM_FOR_HARMONY