Hi!
With Guille and Pablo this morning we found what is the problem and apparently fixed it. The problem is that there is a process in priority 10 that takes the delay lock (accessProtect semaphore) and go to sleep. Then the #benchFor: launches another process in priority 79 that tries to take the delay lock but, since it's taken by the other process, it goes to sleep. But the UI process is in priority 40 so it will always have priority over the one that has the lock. Consequence: the process in priority 10 has the delay lock and will never be awaken until the UI process gets suspended.��
More in detail, the following method makes the assumption that once the delay process finishes the handling of the delay to schedule, it will return to same process. But that is not true if there is another process with more priority.
schedule: aDelay
| scheduled |
scheduled := false.
aDelay schedulerBeingWaitedOn ifTrue: [^self error: 'This Delay has already been scheduled.'].
accessProtect critical: [
scheduledDelay := aDelay.
timingSemaphore signal. "#handleTimerEvent: sets scheduledDelay:=nil"
scheduled := (scheduledDelay == nil).
].
^scheduled.
Our solution is to run the critical section in a higher priority to ensure that always comes back to the same process to release the delay lock.
schedule: aDelay
| scheduled |
scheduled := false.
aDelay schedulerBeingWaitedOn
ifTrue: [ ^ self error: 'This Delay has already been scheduled.' ].
[ accessProtect
critical:
[ scheduledDelay := aDelay.
timingSemaphore signal. "#handleTimerEvent: sets scheduledDelay:=nil"
scheduled := scheduledDelay == nil ].
^ scheduled ] valueAt: Processor timingPriority - 1
Also, to not have interference with the benchmarking process we reduce the priority of the process used in benchFor:
benchFor: duration
"Run me for duration and return a BenchmarkResult"
"[ 100 factorial ] benchFor: 2 seconds"
| count run started |
count := 0.
run := true.
[ duration wait. run := false ] forkAt: Processor timingPriority - 2.
started := Time millisecondClockValue.
[ run ] whileTrue: [ self value. count := count + 1 ].
^ BenchmarkResult new��
iterations: count;��
elapsedTime: (Time millisecondsSince: started) milliSeconds;��
yourself
We will create an entry in fogbugz and submit the change.
Regards,
Martin, Guille and Pablo