The Trunk: Kernel-eem.999.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Kernel-eem.999.mcz

commits-2
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']]]!


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Kernel-eem.999.mcz

Levente Uzonyi
On Fri, 19 Feb 2016, [hidden email] 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

>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Kernel-eem.999.mcz

Eliot Miranda-2
Hi Levente,

> On Feb 19, 2016, at 6:29 PM, Levente Uzonyi <[hidden email]> wrote:
>
>> On Fri, 19 Feb 2016, [hidden email] 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.

>
>>
>> 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
>
>

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Kernel-eem.999.mcz

Levente Uzonyi
Hi Eliot,

On Fri, 19 Feb 2016, Eliot Miranda wrote:

> Hi Levente,
>
>> On Feb 19, 2016, at 6:29 PM, Levente Uzonyi <[hidden email]> wrote:
>>
>>> On Fri, 19 Feb 2016, [hidden email] 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
>>
>>
>
>