[squeak-dev] The Trunk: Kernel-eem.999.mcz
Levente Uzonyi
leves at caesar.elte.hu
Sat Feb 20 02:29:31 UTC 2016
On Fri, 19 Feb 2016, commits at source.squeak.org wrote:
> 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)]!
The list variable seems unnecessary. myList should do it, because its
value will be pushed onto the stack before it could be changed.
>
> 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)]!
Same as above.
>
> 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]]]!
I find it hard to decode what this method does with all that boolean
magic. IMHO early returns would make it a lot easier to understand what it
actually does:
myList ifNotNil: [ ^false ].
suspendedContext ifNil: [ ^false ].
suspendedContext isBottomContext ifFalse: [ ^true ].
suspendedContext closure ifNotNil: [ :closure |
^suspendContext pc < closure endPC ].
^suspendedContext methodClass ~~ Process
or: [ suspendedContext selector ~~ #terminate ]
> - "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]]]!
Just like above.
> - 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']]]!
I guess you know already. :)
Levente
>
>
>
More information about the Squeak-dev
mailing list
|