--- a/Semaphore.st Tue Oct 28 21:40:03 2003 +0100
+++ b/Semaphore.st Tue Oct 28 22:12:54 2003 +0100
@@ -335,7 +335,7 @@
].
^ true
].
- (waitingProcesses identityIndexOf:process) == 0 ifTrue:[
+ (waitingProcesses isNil or:[(waitingProcesses includesIdentical:process) not]) ifTrue:[
self addWaitingProcess:process.
].
^ false
@@ -344,11 +344,14 @@
"Modified: 10.1.1997 / 21:42:18 / cg"
!
-unregisterProcess:process
+unregisterProcess:aProcess
"interface for SemaphoreSet.
- Unregister our process from the Semaphore"
+ Unregister our process from the Semaphore.
+ ATTENTION: this must be invoked with OperatingSystem-interrupts-blocked."
- waitingProcesses removeIdentical:process ifAbsent:[].
+ waitingProcesses notNil ifTrue:[
+ self removeWaitingProcess:aProcess
+ ].
"Created: 14.12.1995 / 10:31:50 / stefan"
"Modified: 1.2.1997 / 12:11:22 / cg"
@@ -381,14 +384,23 @@
addWaitingProcess:aProcess
"add aProcess to the list of waiting processes.
- Sort, so that higher priority process are resumed first.
- Processes having the same priority are ordered first-come-first-serve.
+ all processes are ordered first-come-first-serve.
NOTE: must be called with blocked interrupts"
"for now"
- waitingProcesses add:aProcess.
+ waitingProcesses isNil ifTrue:[
+ waitingProcesses := Array with:aProcess
+ ] ifFalse:[
+ waitingProcesses class == Array ifTrue:[
+ waitingProcesses := OrderedCollection withAll:waitingProcesses.
+ ].
+ waitingProcesses add:aProcess.
+ ].
+"/ "Sort, so that higher priority process are resumed first.
+"/ Processes having the same priority are ordered first-come-first-serve."
+"/
"/ |priority insertIndex|
"/
"/ (waitingProcesses size == 0
@@ -399,6 +411,45 @@
"/
"/ insertIndex := waitingProcesses findFirst:[:process| process priority < priority].
"/ waitingProcesses add:aProcess beforeIndex:insertIndex.
+!
+
+removeFirstWaitingProcess
+ "remove the first waiting process from the list of waiting processes
+ and return it; Nil if there is none.
+
+ NOTE: must be called with blocked interrupts"
+
+ |nWaiting p|
+
+ nWaiting := waitingProcesses size.
+ nWaiting == 0 ifTrue:[^ nil].
+
+ nWaiting == 1 ifTrue:[
+ p := waitingProcesses at:1.
+ waitingProcesses := nil.
+ ^ p.
+ ].
+ ^ waitingProcesses removeFirst.
+!
+
+removeWaitingProcess:aProcess
+ "remove aProcess from the list of waiting processes
+ NO action if it is not in the list.
+
+ NOTE: must be called with blocked interrupts"
+
+ |nWaiting|
+
+ nWaiting := waitingProcesses size.
+ nWaiting == 0 ifTrue:[^ self].
+
+ nWaiting == 1 ifTrue:[
+ (waitingProcesses at:1) == aProcess ifTrue:[
+ waitingProcesses := nil.
+ ].
+ ^ self.
+ ].
+ waitingProcesses removeIdentical:aProcess ifAbsent:[].
! !
!Semaphore methodsFor:'private-accessing'!
@@ -416,7 +467,7 @@
"set the count of the semaphore;
thats the number of possible waits, without blocking"
- waitingProcesses := OrderedCollection new:2.
+ waitingProcesses := nil.
count := n
"Modified: 17.2.1997 / 11:36:40 / cg"
@@ -454,7 +505,7 @@
waitingProcesses
"return the processes waiting on the receiver"
- ^ waitingProcesses
+ ^ waitingProcesses ? #()
"Created: 18.7.1996 / 20:53:33 / cg"
!
@@ -473,7 +524,7 @@
isEmpty
"ST80 compatibility - return true if there are no waiters"
- ^ waitingProcesses isEmpty
+ ^ waitingProcesses size == 0
"Created: / 3.5.1996 / 18:06:27 / cg"
"Modified: / 18.6.1998 / 16:07:38 / cg"
@@ -491,7 +542,36 @@
"evaluate aBlock as a critical region; the receiver must be
created using Semaphore>>forMutualExclusion"
- |retVal gotSema|
+ |retVal gotSema wasBlocked|
+
+ "/ inlined common case - ugly kludge but helpful
+ wasBlocked := OperatingSystem blockInterrupts.
+ count > 0 ifTrue:[
+ count := count - 1.
+ count == 0 ifTrue:[
+ lastOwnerID := Processor activeProcessId.
+ ].
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+
+ retVal := aBlock ifCurtailed:[ self signal ].
+
+ OperatingSystem blockInterrupts.
+ [
+ |p|
+
+ count := count + 1.
+ waitingProcesses notNil ifTrue:[
+ p := self removeFirstWaitingProcess.
+ p notNil ifTrue:[
+ Processor resume:p.
+ ].
+ ].
+ ] ensure:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ].
+ ^ retVal.
+ ].
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
[
gotSema := self wait.
@@ -549,9 +629,11 @@
|p|
count := count + 1.
- p := waitingProcesses removeFirstIfAbsent:nil.
- p notNil ifTrue:[
- Processor resume:p.
+ waitingProcesses notNil ifTrue:[
+ p := self removeFirstWaitingProcess.
+ p notNil ifTrue:[
+ Processor resume:p.
+ ].
].
] ensure:[
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
@@ -570,14 +652,16 @@
waitingProcesses notEmpty ifTrue:[
wasBlocked := OperatingSystem blockInterrupts.
[
+ |nWaiting|
+
"/ first, make them all runnable, but do not schedule
"/ (in case one has higher prio and goes into a wait
"/ immediately again.)
- [waitingProcesses notEmpty] whileTrue:[
+ [(nWaiting := waitingProcesses size) > 0] whileTrue:[
|p|
- p := waitingProcesses removeFirst.
+ p := self removeFirstWaitingProcess.
count := count + 1.
Processor makeRunnable:p.
].
@@ -600,10 +684,10 @@
|wasBlocked|
- waitingProcesses notEmpty ifTrue:[
+ (waitingProcesses size > 0) ifTrue:[
wasBlocked := OperatingSystem blockInterrupts.
[
- waitingProcesses notEmpty ifTrue:[
+ (waitingProcesses size > 0) ifTrue:[
self signal
].
] ensure:[
@@ -624,12 +708,16 @@
wasBlocked := OperatingSystem blockInterrupts.
"/ check again - now interrupts are blocked.
[
+ |p|
+
count <= 0 ifTrue:[
count := count + 1.
- count == 1 ifTrue:[ |p|
- p := waitingProcesses removeFirstIfAbsent:nil.
- p notNil ifTrue:[
- Processor resume:p.
+ count == 1 ifTrue:[
+ waitingProcesses notNil ifTrue:[
+ p := self removeFirstWaitingProcess.
+ p notNil ifTrue:[
+ Processor resume:p.
+ ].
].
].
].
@@ -666,14 +754,14 @@
[
activeProcess suspendWithState:#wait
] ifCurtailed:[
- waitingProcesses removeIdentical:activeProcess ifAbsent:[].
+ self removeWaitingProcess:activeProcess.
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
count <= 0 ifTrue:[
"/ care for someone manually resuming me (i.e. semaphore still not avail)...
"/ being multiple times on waitingProcesses
- waitingProcesses removeIdentical:activeProcess ifAbsent:[].
+ self removeWaitingProcess:activeProcess.
]
].
].
@@ -716,13 +804,13 @@
[
activeProcess suspendWithState:#wait
] ifCurtailed:[
- waitingProcesses removeIdentical:activeProcess ifAbsent:[].
+ self removeWaitingProcess:activeProcess.
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
count <= 0 ifTrue:[
"/ care for someone manually resuming me (i.e. semaphore still not avail)...
"/ being multiple times on waitingProcesses
- waitingProcesses removeIdentical:activeProcess ifAbsent:[].
+ self removeWaitingProcess:activeProcess.
]
].
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
@@ -803,11 +891,11 @@
] ifCurtailed:[
Processor removeTimedBlock:unblock.
unblock := nil.
- waitingProcesses removeIdentical:activeProcess ifAbsent:[].
+ self removeWaitingProcess:activeProcess.
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
- waitingProcesses removeIdentical:activeProcess ifAbsent:[].
+ self removeWaitingProcess:activeProcess.
timeoutOccured ifTrue:[
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
unblock := nil.
@@ -835,5 +923,5 @@
!Semaphore class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.69 2003-05-07 14:11:01 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.70 2003-10-28 21:12:54 cg Exp $'
! !