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, &param)) {
+        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, &param)) {
+            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, &param);
+        if (!result) {
+            param.sched_priority = defaultPriority(policy) + priority;
+            return pthread_setschedparam((pthread_t)thread, policy, &param);
+        } 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.