[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