Kaffe thread scheduling bug

William Chesters kaffe@kaffe.org
Tue, 29 Apr 1997 18:21:21 +0200


Following up on the reasons why IFC doesn't work under Kaffe/BISS AWT,
I came up with the test program listed below.

Results:

java YieldTest n n
java YieldTest n y
java YieldTest y n
java YieldTest y y
    all three threads run; once a second it prints "a/b/c"

kaffe YieldTest n n
    all three threads run; once a second it prints "a/b/c"

kaffe YieldTest n y
kaffe YieldTest y n
kaffe YieldTest y y
    as soon as a thread yields, it stops; prints "a/b/c"
    once, then nothing

From a quick look at kaffe/kaffevm/thread.c, it seems that
`setPriorityThread' moves the thread to the back of the scheduling queue
(within its priority level), whereas `yieldThread' implicitly assumes
that the yielding thread is at the front of the queue.  Line 326

	threadQhead[TCTX(currentThread)->priority] = currentThread->next;

will set the queue head to null if the thread has called setPriority,
and all the threads at this priority level will be ignored in future
scheduling rounds.

(please forgive me if I've got the diagnosis wrong---I verified that
the queue head is indeed getting nulled out but I can't claim to
understand the mechansism in depth ...)

By the way, even if I stop the IFC code calling setPriority, it still
comes to a grinding halt when it gets to a wait()---probably a
different problem.



public class YieldTest extends Thread {
  private static boolean setPriorityPreYield;
  private static boolean setPriorityPostYield;

  private String diagName;
  private long last = 0;

  public YieldTest(String diagName) {
    this.diagName = diagName;
  }

  public void run() {
    for (;;) {
      long now = System.currentTimeMillis();
      if (now - last > 1000) {
	System.out.println(diagName);
	last = now;
      }

      if (setPriorityPreYield)
	setPriority(getPriority());

      yield();

      if (setPriorityPostYield)
	setPriority(getPriority());
    }
  }

  public static void main(String[] args) {
    setPriorityPreYield = args[0].equals("y");
    setPriorityPostYield = args[1].equals("y");

    new YieldTest("a").start();
    new YieldTest("b").start();
    new YieldTest("c").start();
  }
}