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']]]! |
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 > > > |
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 > > |
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 >> >> > > |
Free forum by Nabble | Edit this page |