[Cuis-dev] #terminate and #suspend update
Jaromir Matas
mail at jaromir.net
Sat Aug 27 03:12:24 PDT 2022
Hi Juan,
> There is one problem left. #isTerminated will always answer false if #suspend primitive failed and old primitive 88 fallback method is called. I just pushed to github update #5458 to address this. Please check it carefully. Maybe you prefer a different solution, I'll be happy to review and integrate it.
Oops, I forgot to mention the backward compatibility consideration but you caught it :) (meaning: to be able to run new images with older VMs, not only older images with the new VM). Squeak decided to maintain only its ability to run older images with the new VM - so no change in #isTerminated in Squeak; however I agree with you that "fixing" #isTerminated is worth the effort provided the fix is pretty easy.
I'm enclosing my original suggestion for #isTerminated; I think the semantics is very similar to your version (checking whether the remaining context chain has anything useful left) except one thing: Your version allows a process with its suspended context's pc = nil to be considered not terminated. My understanding was: if a process's suspended context's pc is nil, it implies the process would be considered terminated. Is this right or would you define 'being terminated' differently?
Check this example:
ctx _ [] asContextWithSender: [] asContext.
p _ Process forContext: ctx priority: 40.
ctx pc: nil.
p isTerminated. "answers false in your version and true in mine"
I already noticed a while ago my previous version of #isTerminated failed to catch pc = nil in a process's suspended context and evaluate the process as 'terminated'. I wonder now what definition of 'terminated' state is actually 'the right one'.
Another question: in the example above - how do you look at the bytecodes of ctx? In Squeak the Explorer shows the bytecodes right away but in Cuis I have to open an extra inspector for 'method' and look at 'allBytecodes', right?
In Squeak the process p answers true to #isTerminated even without nilling its pc, which is expected because each of the two contexts consists only of a single instruction, a return. But in Cuis I'm not sure how come the answer is false; I suspect I've got confused by the different implementation of Context / ContextPart in Squeak/Cuis. Here's what I mean:
ctx _ [] asContextWithSender: [] asContext.
p _ Process forContext: ctx priority: 40.
p isTerminated. "answers false in Cuis and true in Squeak because ctx atEnd differs"
... while this works the same in both:
ctx _ [1] asContextWithSender: [] asContext.
p _ Process forContext: ctx priority: 40.
p isTerminated. "answers false in both Cuis and Squeak because ctx is not atEnd"
Thank you for your advice.
Best regards,
Jaromir
--
Jaromír Matas
mail at jaromir.net
From: Juan Vuletich<mailto:juan at cuis.st>
Sent: Wednesday, August 17, 2022 18:29
To: Discussion of Cuis Smalltalk<mailto:cuis-dev at lists.cuis.st>
Cc: Jaromir Matas<mailto:mail at jaromir.net>
Subject: Re: [Cuis-dev] #terminate and #suspend update
Hi Jaromir,
One important note at the end.
On 8/16/2022 4:46 PM, Jaromir Matas via Cuis-dev wrote:
Hi Juan,
I'm enclosing an update of #terminate and a revised version of #suspend.
Thanks!
There are two main reasons for this update:
(1) Currently the process that sends #terminate won't wait for the process being terminated to finish its termination if the process being terminated e.g. inserts a delay in an unwind block (see #testTerminateWithDelayInUnwind). To fix this deficiency I've engaged a semaphore to synchronize the two processes. In addition, I've added a bit more powerful guard (see #unwindAndStop:) to make sure a process is correctly terminated even in case of multiple concurrent termination attempts, and a few minor fixes for edge cases. This updated approach passed all Squeak’s and Pharo’s tests :) I'll be sending more tests later after I'll adapt my Squeak versions; apologies. (Changed methods: #terminate, #unwindTo:, #runUntilReturnFrom:; added methods: #suspendAndReleaseCriticalSection, #unwindAndStop:)
Nice. Please don't forget to update us too with those tests!
(2) Eliot implemented a revised process suspend semantics in primitive 578. The original suspend semantics (in primitive 88) is flawed and allows a process waiting on a semaphore (or mutex in Squeak) to leave the semaphore even without receiving a signal: the original suspend primitive 88 simply removes the process from the semaphore. The new suspend primitive 578 backs up the process's pc by "one instruction", i.e. to the send that placed the process in the semaphore queue; it means that when the process resumes it reenters the wait state. Check #testSuspendAndResume. (Changed methods: #suspend, #signalException:, #signalWaitingProcess; added methods: #suspendAndUnblock:, #processSuspensionUnblocks)
I was somewhat aware of this, but unable to take any action, never enough time. Thanks for bringing this to Cuis too. This is important.
Both "fixes" can be implemented independently but for simplicity I'm sending them both in one package; should you decide to implement just fix at a time I can separate them.
I reviewed them to the best of my knowledge (it is less than yours in many details). Both are @ GitHub now.
While the #terminate fix is just improving the current behavior (and most likely not breaking any existing code) the #suspend fix may be a bit different story:
Considerations:
i) there may be some existing external code (ab)using the flawed behavior of primitive 88 -> for this scenario the old behavior has been retained in #suspendAndUnblock method. It may be useful but must be used with caution.
It will only be used as a fallback for older VMs. New behavior is correct. Old wasn't.
ii) there are a few methods even in the core taking advantage of the old behavior: Process >> #signalException: and DelayWaitTimeout >> #signalWaitingProcess - check the fixed code. (Cuis has also Process >> #signal but I'm not sure what its purpose is compared to #signalException: - please advise)
Had to dig history. #signalException: and #signal: both came from Squeak and were essentially unchanged since 2007 and 2003. And #signal: is obsolete and unused. Just removed it.
iii) in the new release VM (3185) there are in fact two new suspend primitives: #578 and #568; the only difference is the return value: #568 returns the list the suspended process was previously waiting at (the same return semantics as primitive #88) while #578 returns nil if the process's pc was backed up; after a debate with Eliot and Nicolas, Squeak uses 578 but it's no problem to use 568 instead.
I have no elements to argue in that discussion. If the three of you agreed on #578, that's enough for me.
iv) #testAtomicSuspend uses #suspendPrimitivelyOrFail - I'd suggest changing the primitive suspend to 578 and modify the test but I'm not sure how you decide to proceed; maybe test both primitives?
Changed it to just test the new one. Had to assert answer is nil, not the list, as we're using #578 and not #568. Please review updates #5455 (yours), #5456 (test helper), #5457 (cleanup) and #testAtomicSuspend. I added the changes using your initials, as this is all yours. Just check that I didn't mess anything.
v) Eliot has also added to Squeak a new method #processSuspensionUnblocks accessing vmParameterAt: 65 which indicates whether the VM provides the new suspend primitives. I'm just mentioning it FYI and enclosing the code for your consideration (with Eliot's authorship).
May be of use. Thanks. Didn't remove it from the changeset as pushed to the repo.
Juan, please let me know what you think and whether you plan to use the new #suspend. Thanks again for implementing the UI fixes - without them the new #terminate would freeze the UI for many innocent examples :) (...because #terminate operates inside the ensure argument block and now *waits* there until the process being terminated finishes its termination and that would indeed freeze the UI in case of an unwind error).
If you spot any issue or inconsistency please let me know; I'll be away for a few days but back for the weekend.
As already commented, I already integrated it all. Thanks!
Best regards,
Jaromir
--
Jaromír Matas
mail at jaromir.net<mailto:mail at jaromir.net>
There is one problem left. #isTerminated will always answer false if #suspend primitive failed and old primitive 88 fallback method is called. I just pushed to github update #5458 to address this. Please check it carefully. Maybe you prefer a different solution, I'll be happy to review and integrate it. Had to add calls to #processSuspensionUnblocks so they won't fail in older VMs too.
Thanks,
--
Juan Vuletich
cuis.st
github.com/jvuletich
researchgate.net/profile/Juan-Vuletich
independent.academia.edu/JuanVuletich
patents.justia.com/inventor/juan-manuel-vuletich
linkedin.com/in/juan-vuletich-75611b3
twitter.com/JuanVuletich
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20220827/14cfc57a/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 5461-CuisCore-JaromirMatas-2022Aug26-18h17m-jar.isTerminated.cs.st
Type: application/octet-stream
Size: 646 bytes
Desc: 5461-CuisCore-JaromirMatas-2022Aug26-18h17m-jar.isTerminated.cs.st
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20220827/14cfc57a/attachment-0001.obj>
More information about the Cuis-dev
mailing list