If a process runs alone at its original priority and bumps it higher temporarily, setting it back and yieling will not schedule processes above its original priority. Only if there are other processes running on that original (lower) priority.

This seems to be an older optimization in primitiveYield.

Here is an example:

| flag p1 p2 |
flag := Semaphore new.
p1 := [
	Processor activeProcess priority: 80.
	Transcript showln: 'P1 started!'.
	flag signal. "activate p2"
	Processor activeProcess priority: 45.
	Processor yield. "fails to schedule p2"
	Transcript showln: 'P1 finished!'.] newProcess.
p1 priority: 45.

p2 := [ 
	Transcript showln: 'P2 started!'.
	flag wait.
	Transcript showln: 'P2 finished!'.
	] newProcess.
p2 priority: 50.

p2 resume.
p1 resume.

Expected transcript output:

P2 started!
P1 started!
P2 finished!
P1 finished!

However, we get:

P2 started!
P1 started!
P1 finished!
P2 finished!

It is only circumstantial that P2 finishes at all because the Timer Interrupt Scheduler (80) will be signaled eventually and then trigger P2 (50) finally. But P1 (45) has finished by then. This is not fair.

We can show that it works as expected once another process works on the original priority (45):

| flag p1 p2 p3 |
flag := Semaphore new.
p1 := [
	p3 resume.
	Processor activeProcess priority: 80.
	Transcript showln: 'P1 started!'.
	flag signal. "activate p2"
	Processor activeProcess priority: 45.
	Processor yield. "fails to schedule p2"
	Transcript showln: 'P1 finished!'.] newProcess.
p1 priority: 45.

p3 := [
	Transcript showln: 'P3 started!'.
	Transcript showln: 'P3 finished!'.
	] newProcess.
p3 priority: 45.

p2 := [ 
	Transcript showln: 'P2 started!'.
	flag wait.
	Transcript showln: 'P2 finished!'.
	] newProcess.
p2 priority: 50.

p2 resume.
p1 resume.

The output is as expected:

P2 started!
P1 started!
P2 finished!
P3 started!
P3 finished!
P1 finished!

By skipping the P3 output, we get the expected order for P1 and P2:

P2 started!
P1 started!
P2 finished!
P1 finished!

The optimization in primitiveYield reads:

(self isEmptyList: processList) ifTrue: [^nil].

And so wakeHighestPriority will not be called in time. But I think we should support temporal priority bumping this way.


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <OpenSmalltalk/opensmalltalk-vm/issues/677@github.com>