Process >> priority: behavior grossly incorrect, Transcript losing output

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Process >> priority: behavior grossly incorrect, Transcript losing output

Jaromir Matas
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

^[^ Jaromir