[squeak-dev] Process >> priority: behavior grossly incorrect, Transcript losing output

Jaromir m at jaromir.net
Sat Feb 6 08:37:56 UTC 2021


In the following example higher priority process keeps waiting in the
ProcessorScheduler queue until lower priority process suspends!

Transcript flush; cr.
*Processor activeProcess priority: 42.
[ Transcript nextPut: $A ] forkAt: 41.
Processor activeProcess priority: 40.*
Transcript nextPut: $B; flush.
1000 factorial.
Transcript nextPut: $C; flush.
1000 factorial.
Transcript nextPut: $D; flush.
10 milliSeconds wait.   "suspends the active process"
Transcript nextPut: $E; flush.

Answers:

BCDAE
BCDAE
BCDE     "here A even lost!"
BCDAE
BCDAE
BCDAE
BCDAE
BCDAE


Increasing the lenght of computation by doing 20000 factorial shows
interrupts work and suspend the rogue process:

BCDAE
BACDE
BCADE
BCDE     "A lost again"
BACDE
BCDAE
BCDAE


Reason: the #priority: method won't make sure the active process doesn't
jump over a scheduled process when lowering it's priority - as a result the
active process will continue running until it suspends and won't let the
higher priority process a chance to run.

priority: anInteger 
	"Set the receiver's priority to anInteger."
	(anInteger >= Processor lowestPriority and:[anInteger <= Processor
highestPriority])
		ifTrue: [priority := anInteger]
		ifFalse: [self error: 'Invalid priority: ', anInteger printString]


Proposed solution:

priority: anInteger 
	"Set the receiver's priority to anInteger."
	(anInteger >= Processor lowestPriority and:[anInteger <= Processor
highestPriority])
		ifTrue: [
			priority := anInteger.
			*(self isActiveProcess and: [anInteger < Processor nextReadyProcess
priority])
				ifTrue: [ [self resume] fork. self suspend ] ]*
		ifFalse: [self error: 'Invalid priority: ', anInteger printString]

The problem with this solution is the #nextReadyProcess may get interrupted
in the middle which may make it's answer usless. So I guess either this
whole method should run as a primitive or in the interim, always force the
active process suspend momentarily to let ProcessorScheduler do the job:

priority: anInteger 
	"Set the receiver's priority to anInteger."
	(anInteger >= Processor lowestPriority and:[anInteger <= Processor
highestPriority])
		ifTrue: [
			priority := anInteger.
			*self isActiveProcess ifTrue: [ [self resume] fork. self suspend ] ]*
		ifFalse: [self error: 'Invalid priority: ', anInteger printString]


Impact: at least two methods use this type of priority switching:
#valueUnpreemptively and #valueAt: and their behavior is impacted the same
way.

Transcript flush; cr.
*[
[ Transcript nextPut: $A ] forkAt: 41.
] valueUnpreemptively.*
Transcript nextPut: $B; flush.
20000 factorial.
Transcript nextPut: $C; flush.
20000 factorial.
Transcript nextPut: $D; flush.
10 milliSeconds wait.
Transcript nextPut: $E; flush.

Answers again:

BCDAE
BCDAE
BCDE
BCADE
BCDAE
BCADE
BCDAE
BCDE
BCDAE
BACDE


On top of that Transcript loses some output intermittently - I'm not sure if
it's related or a separate issue.

Image
-----
C:\Users\mail\Squeak\Squeak6.0alpha-20182-64bit-superFRESH\Squeak6.0alpha-20182-64bit.image
Squeak6.0alpha latest update: #20182
with all default settings including:
Smalltalk vm processPreemptionYields = false
TranscriptStream forceUpdate = true

Related discussion:
http://forum.world.st/The-Inbox-Compiler-mt-456-mcz-td5126723.html



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html


More information about the Squeak-dev mailing list