JDK-6512687 : Bug #4813310 (Linux thread priority support) marked as Closed, fixed but is not.
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux
  • CPU: x86
  • Submitted: 2007-01-12
  • Updated: 2011-02-16
  • Resolved: 2007-01-30
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.16-2-686 #1 Sat Jul 15 21:59:21 UTC 2006 i686 GNU/Linux (Debian)

A DESCRIPTION OF THE PROBLEM :
Bug report 4813310 indicates that thread priority support has been added to the Hotspot JVM when run as root under linux, so long as the -XX:ThreadPriorityPolicy=1 option is supplied. This is not true.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Source code below is compiled, and run as root with

java -XX:ThreadPriorityPolicy=1 ThreadTester

as advised in bug #4813310.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Once the high priority thread is started, the Thread.yield() statement should have no effect, as the high priority thread remains runnable for the duration of its life.  The low priority thread should only be able to complete once the high priority thread has completed output.

This behaviour is observed on Windows but not Linux.
ACTUAL -
On Linux, the output from the two threads are interleaved, so Thread.yield() is not behaving as described in the API documentation.

Even if the Thread.yield() command is removed, then the low priority thread is still able to periodically interrupt the high priority thread.

The impact on us is that time-critical IO responses are being delayed by garbage collection and other housekeeping processes, causing our application to break.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class ThreadTester implements Runnable {

        int priority;

        public void run() {
                Thread.currentThread().setPriority(priority);
                for(int i=0; i<50000; i++) {
                        System.out.println(priority+" "+i);
//Optionally yield
                        Thread.yield();
                }
                System.out.println(priority+" done.");
        }

        public static void main(String[] args) {
                ThreadTester low=new ThreadTester();
                low.priority=Thread.MIN_PRIORITY;

                ThreadTester high=new ThreadTester();
                high.priority=Thread.MAX_PRIORITY;

                Thread tlow=new Thread(low);
                Thread thigh=new Thread(high);

                System.out.println("Executing Low");

                tlow.start();

                System.out.println("Sleeping");

                try {
                        Thread.sleep(20);
                } catch (InterruptedException ie) {

                }

                System.out.println("Executing high");
                thigh.start();
        }
}

---------- END SOURCE ----------

Comments
EVALUATION CR 4813310 requested that Java thread priorities map to OS thread/process priorities on linux. This was done to the extent possible while using the SCHED_OTHER scheduling policy. Hence 4813310 was fixed. To clarify, the "fix" for 4813310 was to adjust the "niceness" of the kernel thread that is presumed to be bound to the Java thread by calling setpriority(). This does not provide strict priority preemptive scheduling as it is still done within the SCHED_OTHER scheduling policy by default. This means that lower "priority" threads will gradually increase in priority (priority ageing) as each timeslice elapses. Hence all threads will get a chance to run as was observed. The Windows priorty scheduling model behaves somewhat differently and more in line with the submitters expectations. Note that Thread.yield itself is not specified to be priority-based. It's specification/documentation simply states: "Causes the currently executing thread object to temporarily pause and allow other threads to execute." Hence the observed behaviour is totally allowable and there is no bug in Thread.yield. In contrast OS "yield" operations are often defined in terms of priority (eg. placing the current thread at the tail of the queue for its priority level), such as the linux sched_yield method which is actually used for Thread.yield on linux. However sched_yield's behaviour is defined in terms of the static priority of the thread (really process) and that value is always zero under SCHED_OTHER, so regardless of the nice level, sched_yield will relinquish the processor if another thread is ready. So again this is what was observed with the Thread.yield present. The Hotspot VM will currently not work reliably under strict priority preemptive scheduling (as reported in 4813310) - for that you need a real-time Java implementation such as Sun's Java Real-Time System (Java RTS): http://java.sun.com/javase/technologies/realtime.jsp Given the need to apparently preempt GC and other "housekeeping" tasks I would most definitely refer the submitter to the Java RTS product as this is the kind of role it is designed for. In a normal VM GC will preempt all threads, at least part of the time, regardless of their priority (even if strict priority was used, because GC requires that mutator threads "suspend" until the GC completes - which is achieved in Hotspot using the safepoint mechanism (Java 5 and above).
30-01-2007