[squeak-dev] The Trunk: Kernel-eem.999.mcz

Levente Uzonyi leves at caesar.elte.hu
Sat Feb 20 03:20:26 UTC 2016


Hi Eliot,

On Fri, 19 Feb 2016, Eliot Miranda wrote:

> Hi Levente,
>
>> On Feb 19, 2016, at 6:29 PM, Levente Uzonyi <leves at caesar.elte.hu> wrote:
>>
>>> 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.
>
> I'm being a bit over cautious here but I'm imagining that it's possible that deteferencing the global Processor might involve a send.  For example in the VW system global a are sent #value and with namespaces that might bind to a real method and hence be an interrupt point.
>

I mean in case of

 	myList ifNil: [ ^false ]
 	^myList ~~ (Processor waitingProcessesAt: myPriority)

The second line will work because the value of myList is on the left side 
of #~~, so it will have been pushed onto the stack when Processor will be 
dereferenced.

Levente

>>
>>>
>>> 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.
>
> Ditto :)
>>
>>>
>>> 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