[squeak-dev] The Inbox: Kernel-jar.1377.mcz
commits at source.squeak.org
commits at source.squeak.org
Wed Mar 3 22:06:50 UTC 2021
A new version of Kernel was added to project The Inbox:
http://source.squeak.org/inbox/Kernel-jar.1377.mcz
==================== Summary ====================
Name: Kernel-jar.1377
Author: jar
Time: 3 March 2021, 11:06:44.192499 pm
UUID: b99e562a-887b-7e4e-9c11-6818ca1acaeb
Ancestors: Kernel-nice.1376
Fix inconsistent bahavior in #isTerminated and #isSuspended
=============== Diff against Kernel-nice.1376 ===============
Item was changed:
----- Method: Process>>isSuspended (in category 'testing') -----
isSuspended
+ "A process is suspended if it has non-nil suspendedContext (e.g. new or
+ previously suspended with the suspend primitive) and is not terminated or
+ waiting in a scheduler or a semaphore queue (i.e. is not runnable or blocked)."
+
+ ^myList isNil
+ and: [suspendedContext notNil]
+ and: [self isTerminated not]!
- "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]]]!
Item was changed:
----- Method: Process>>isTerminated (in category 'testing') -----
isTerminated
+ "Answer if the receiver is terminated, or at least terminating, i.e. if one
+ of the following conditions is satisfied:
+ (1) the receiver is a defunct process (suspendedContext = nil or pc = nil)
+ (2) we catch the active process termination by adding a first temporary
+ in Process>>terminate called terminationStatus and having Process>>
+ terminate assign #terminated to it when termination is essentially complete
+ (3) the suspendedContext is the bottomContext and the pc is at the endPC"
+
+ self isActiveProcess ifTrue: [^false].
- "Answer if the receiver is terminated, or at least terminating."
- self isActiveProcess ifTrue: [^ false].
^suspendedContext isNil
+ or: [suspendedContext isDead]
+ or: [suspendedContext methodClass == Process
+ and: [suspendedContext selector == #terminate]
+ and: [(suspendedContext tempAt: 1) == #terminated]]
+ or: [suspendedContext isBottomContext and: [suspendedContext atEnd]]!
- 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
- 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]]]!
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.
If the process is in the middle of a critical: critical section, release it properly."
+ | terminationStatus ctxt unwindBlock oldList |
- | ctxt unwindBlock oldList |
self isActiveProcess ifTrue:
[ctxt := thisContext.
[ctxt := ctxt findNextUnwindContextUpTo: nil.
ctxt ~~ nil] whileTrue:
[(ctxt tempAt: 2) ifNil:
["N.B. Unlike Context>>unwindTo: we do not set complete (tempAt: 2) to true."
unwindBlock := ctxt tempAt: 1.
thisContext terminateTo: ctxt.
unwindBlock value]].
thisContext terminateTo: nil.
+ terminationStatus := #terminated.
self suspend.
"If the process is resumed this will provoke a cannotReturn: error.
Would self debug: thisContext title: 'Resuming a terminated process' be better?"
^self].
"Always suspend the process first so it doesn't accidentally get woken up.
N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al
then the process is blocked, and if it is nil then the process is already suspended."
oldList := self suspend.
suspendedContext ifNotNil:
["Release any method marked with the <criticalSection> pragma.
The argument is whether the process is runnable."
self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]).
"If 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]!
More information about the Squeak-dev
mailing list
|