Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-eem.999.mcz
==================== Summary ====================
Name: Kernel-eem.999 Author: eem Time: 18 February 2016, 11:03:09.008076 pm UUID: 30222068-755f-4637-bbbb-6f775291e746 Ancestors: Kernel-bf.998
Fix isSuspended (my last commit was a regression; I had confused isSuspended with isBlocked). Comment all the isFoo testing methods in process. Add isBlocked. Modify Process>>terminate to set the pc of the context of a process that is not auto-terminated to its endPC so that isTerminated and isSuspended can distinguish between processes either terminated or suspended.
=============== Diff against Kernel-bf.998 ===============
Item was added: + ----- Method: Process>>isBlocked (in category 'testing') ----- + isBlocked + "A process is blocked if it is waiting on some list (i.e. a Semaphore), other than the runnable process lists." + | myPriority | + "Grab my prioirty now. Even though evaluation is strictly right-to-left, accessing Processor could involve a send." + myPriority := priority. + ^myList + ifNil: [false] + ifNotNil: [:list| list ~~ (Processor waitingProcessesAt: myPriority)]!
Item was added: + ----- Method: Process>>isRunnable (in category 'testing') ----- + isRunnable + "A process is runnable if it is the active process or is on one of the runnable process lists." + | myPriority | + "Grab my prioirty now. Even though evaluation is strictly right-to-left, accessing Processor could involve a send." + myPriority := priority. + ^myList + ifNil: [^self == Processor activeProcess] + ifNotNil: [:list| list == (Processor waitingProcessesAt: myPriority)]!
Item was changed: ----- Method: Process>>isSuspended (in category 'testing') ----- isSuspended + "A process is suspended if it has been suspended with the suspend primitive. + It is distinguishable from the active process and a terminated process by + having a non-nil suspendedContext that is either not the bottom context + or has not reached its endPC." + ^nil == myList + and: [nil ~~ suspendedContext + and: [suspendedContext isBottomContext + ifTrue: [suspendedContext closure + ifNil: [suspendedContext methodClass ~~ Process + or: [suspendedContext selector ~~ #terminate]] + ifNotNil: [suspendedContext pc < suspendedContext closure endPC]] + ifFalse: [true]]]! - "A process is suspended if it is waiting on some list, other than the runnable process lists." - | myPriority | - "Grab my prioirty now. Even though evaluation is strictly right-to-left, accessing Processor could involve a send." - myPriority := priority. - ^myList - ifNil: [false] - ifNotNil: [:list| list ~~ (Processor waitingProcessesAt: myPriority)]!
Item was changed: ----- Method: Process>>isTerminated (in category 'testing') ----- isTerminated + "Answer if the receiver is terminated, or at least terminating." - self isActiveProcess ifTrue: [^ false]. ^suspendedContext isNil or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. + If so, and the pc is at the endPC, the block has already sent and returned - If so, and the pc is greater than the startpc, the block has alrteady sent and returned from value and there is nothing more to do." suspendedContext isBottomContext + and: [suspendedContext closure + ifNil: [suspendedContext methodClass == Process + and: [suspendedContext selector == #terminate]] + ifNotNil: [suspendedContext pc >= suspendedContext closure endPC]]]! - and: [suspendedContext pc > suspendedContext startpc]]!
Item was changed: ----- Method: Process>>terminate (in category 'changing process state') ----- terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
| ctxt unwindBlock oldList | self isActiveProcess ifTrue: [ ctxt := thisContext. [ ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ (ctxt tempAt: 2) ifNil:[ ctxt tempAt: 2 put: nil. unwindBlock := ctxt tempAt: 1. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. self suspend. ] ifFalse:[ "Always suspend the process first so it doesn't accidentally get woken up" oldList := self suspend. suspendedContext ifNotNil:[ "Figure out if we are terminating a process that is in the ensure: block of a critical section. In this case, if the block has made progress, pop the suspendedContext so that we leave the ensure: block inside the critical: without signaling the semaphore/exiting the primitive section, since presumably this has already happened." (suspendedContext isClosureContext and: [(suspendedContext method pragmaAt: #criticalSection) notNil and: [suspendedContext startpc > suspendedContext closure startpc]]) ifTrue: [suspendedContext := suspendedContext home].
"If we are terminating a process halfways through an unwind, try to complete that unwind block first." (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: [:outer| (suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil: [:inner| "This is an unwind block currently under evaluation" suspendedContext runUntilErrorOrReturnFrom: inner]].
ctxt := self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: + [self debug: ctxt title: 'Unwind error during termination']. + "Set the context to its endPC for the benefit of isTerminated." + ctxt pc: ctxt endPC]]! - [self debug: ctxt title: 'Unwind error during termination']]]!
packages@lists.squeakfoundation.org