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
squeak-dev@lists.squeakfoundation.org