﻿'From Squeak6.0beta of 18 May 2022 [latest update: #21760] on 19 May 2022 at 7:06:47 pm'!

!DelayWaitTimeout methodsFor: 'signaling' stamp: 'jar 5/19/2022 12:38'!
signalWaitingProcess
	"Release the given process from the semaphore it is waiting on.
	This method relies on running at highest priority so that it cannot be preempted
	by the process being released."
	beingWaitedOn := false.
	"Release the process but only if it is still waiting on its original list"
	process suspendingList == delaySemaphore ifTrue:[
		expired := true.
		process suspendAndUnblock; resume.
	].
! !


!Process methodsFor: 'changing process state' stamp: 'jar 5/19/2022 14:57'!
suspend
	"eem 1/3/2022 10:38:
	 Primitive. Suspend the receiver, aProcess, such that it can be executed again
	 by sending #resume. If the given process is not the active process, take it off
	 its corresponding list. If the list was not its run queue assume it was on some
	 condition variable (Semaphore, Mutex) and back up its pc to the send that
	 invoked the wait state the process entered.  Hence when the process resumes
	 it will reenter the wait state. Answer the list the receiver was previously on iff
	 it was not active and not blocked, otherwise answer nil."

	<primitive: 578 error: ec>
	"This is fallback code for VMs which only support the old primitiveSuspend 88.
	 Note: in this case some tests may fail and some methods assuming the revised
	 suspend semantics described above may not work entirely as expected (e.g.
	 Context >> #releaseCriticalSection or Process >> #signalException)."
	 ^self suspendAndUnblock! !

!Process methodsFor: 'changing process state' stamp: 'jar 5/19/2022 13:00'!
suspendAndUnblock
	"ar 12/7/2007 17:10:
	 Primitive. Stop the process that the receiver represents in such a way 
	 that it can be restarted at a later time (by sending the receiver the 
	 message resume). If the receiver represents the activeProcess, suspend it. 
	 Otherwise remove the receiver from the list of waiting processes.
	 The return value of this method is the list the receiver was previously on (if any)."

	<primitive: 88 error: ec>
	"ar 12/7/2007 17:10:
	 This is fallback code for VMs which only support the old primitiveSuspend which 
	 would not accept processes that are waiting to be run."
	 ^myList ifNotNil: "this allows us to use suspend multiple times"
		[:oldList|
		 myList := nil.
		 oldList remove: self ifAbsent: [].
		 oldList]! !

!Process methodsFor: 'signaling' stamp: 'eem 1/1/2022 17:43'!
signalException: anException
	"Signal an exception in the receiver process...if the receiver is currently
	suspended, the exception will get signaled when the receiver is resumed.  If 
	the receiver is blocked on a Semaphore, it will be immediately re-awakened
	and the exception will be signaled; if the exception is resumed, then the receiver
	will return to a blocked state unless the blocking Semaphore has excess signals"

	"If we are the active process, go ahead and signal the exception"
	 self isActiveProcess ifTrue: [^anException signal].

	"Suspend myself first to ensure that I won't run away
	 in the midst of the following modifications."
	 self suspend.
	 suspendedContext := Context
								sender: suspendedContext
								receiver: anException
								method: (anException class lookupSelector: #signal)
								arguments: #().
	 ^self resume! !

!Process methodsFor: '*KernelTests-Processes' stamp: 'jar 5/18/2022 19:33'!
suspendPrimitivelyOrFail
	"Test support. Execute primitive 578, or fail."

	<primitive: 578>
	^self primitiveFailed! !


!ProcessTest methodsFor: 'tests' stamp: 'jar 5/19/2022 19:06'!
testAtomicSuspend
	"Test atomic suspend of foreign processes"

	| list p |
	p := [semaphore wait] fork.
	Processor yield.
	list := p suspendPrimitivelyOrFail.
	self assert: list == nil.
! !

