<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
    <title></title>
  </head>
  <body bgcolor="#ffffff" text="#000000">
    Hi Eliot,<br>
    <br>
    The V3 code in Cuis was last updated on 2010, but that was just the
    comment. I went back in time, and this (except for the comment)
    identical version of the code is 10/5/2007 by Andreas.<br>
    <br>
    critical: mutuallyExcludedBlock            <br>
        "Evaluate mutuallyExcludedBlock only if the receiver is not
    currently in<br>
        the process of running the critical: message. If the receiver
    is, evaluate<br>
        mutuallyExcludedBlock after the other critical: message is
    finished."<br>
        | blockValue caught |<br>
        caught := false.<br>
        [<br>
            caught := true.<br>
            self wait.<br>
            blockValue := mutuallyExcludedBlock value<br>
        ] ensure: [caught ifTrue: [self signal]].<br>
        ^blockValue<br>
    <br>
    If you are interested, in Cuis, unzip /PreviousUpdates and in file
    list set this filter: *-ar.cs.st;*-ar.?.cs.st;*-ar.??.cs.st<br>
    This will show all the change sets in Cuis history directly based on
    Andreas' contributions. In this case it is
    0104-SemaCritical-ar.cs.st<br>
    <br>
    You know this stuff better than anyone, and I'm happy to follow your
    lead here, Eliot.<br>
    <br>
    Just a question. You are using primitives
    #primitiveExitCriticalSection  #primitiveEnterCriticalSection
    #primitiveTestAndSetOwnershipOfCriticalSection (185, 186, 187), that
    Cuis hasn't used so far. Are they supported by SqueakJS and the
    classic interpreter?<br>
    <br>
    Thanks,<br>
    <pre class="moz-signature" cols="72">-- 
Juan Vuletich
<a class="moz-txt-link-abbreviated" href="http://www.cuis-smalltalk.org">www.cuis-smalltalk.org</a>
<a class="moz-txt-link-freetext" href="https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev">https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev</a>
<a class="moz-txt-link-freetext" href="https://github.com/jvuletich">https://github.com/jvuletich</a>
<a class="moz-txt-link-freetext" href="https://www.linkedin.com/in/juan-vuletich-75611b3">https://www.linkedin.com/in/juan-vuletich-75611b3</a>
@JuanVuletich</pre>
    <br>
    On 7/27/2018 2:40 AM, Eliot Miranda wrote:
    <blockquote
cite="mid:CAC20JE19=p4yjAqqVU4zHcoqh7rdgh3TLpjTpE8rDrH=sZUndQ@mail.gmail.com"
      type="cite"><br>
      <div dir="ltr">Ha!
        <div class="gmail_extra"><br>
          <div class="gmail_quote">On Thu, Jul 26, 2018 at 9:31 PM,
            Eliot Miranda <span dir="ltr"><<a moz-do-not-send="true"
                href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span>
            wrote:<br>
            <blockquote class="gmail_quote" style="margin: 0px 0px 0px
              0.8ex; border-left: 1px solid rgb(204, 204, 204);
              padding-left: 1ex;">
              <div dir="ltr">Hi David, Hi Bert, Clément, Juan, Levente
                and Marcus, Hi Anyone else with strong experience in the
                VM with processes,
                <div class="gmail_extra"><br>
                  <div class="gmail_quote">On Mon, Jul 23, 2018 at 7:38
                    PM, David T. Lewis <span dir="ltr"><<a
                        moz-do-not-send="true"
                        href="mailto:lewis@mail.msen.com"
                        target="_blank">lewis@mail.msen.com</a>></span>
                    wrote:<br>
                    <blockquote class="gmail_quote" style="margin: 0px
                      0px 0px 0.8ex; border-left: 1px solid rgb(204,
                      204, 204); padding-left: 1ex;">Semaphore seems
                      like a rather basic thing that should work
                      correctly in<br>
                      any Squeak image. The tests do not pass in trunk
                      any more.<br>
                      <br>
                      Specifically, SemaphoreTest>>testSemaInCriti<wbr>calWait
                      fails in trunk, but passes<br>
                      in the earlier Squeak 4.6 / 5.0 images.<br>
                      <br>
                      Is this a real problem? Does it need to be fixed
                      for the 5.2 release?<br>
                    </blockquote>
                    <div><br>
                    </div>
                    <div>Yes.  Yes.  And it needs to be fixed in Pharo
                      too.  I know this message will strike you as
                      TL;DR, but please, especially if you're Bert,
                      Clément, Juan, Levente or Marcus, read this
                      carefully.  It's quite important.  And below I'll
                      present the Squeak code but will work with Clément
                      and Marcus to implement semantically equivalent
                      Pharo code asap.</div>
                    <div><br>
                    </div>
                    <div>And apologies in advance for the repetitious
                      nature of this message.  It is better that I am
                      precise than I am brief and anyone miss anything. 
                      This is an old problem and it will be nice if I've
                      fixed it, but I could easily have missed
                      something; this problem having been around for
                      decades.  OK...</div>
                    <div><br>
                    </div>
                    <div><br>
                    </div>
                    <div>This is an old problem which boiled down to
                      there being no way to determine by looking at a
                      process's suspendedContext whether a process is
                      either waiting on a Semaphore or Mutex or is no
                      longer waiting, but has made no progress because
                      it is at a lower priority than runnable processes
                      and so has not got a chance to run yet.</div>
                    <div><br>
                    </div>
                    <div>So in</div>
                    <div>    | s |</div>
                    <div>    s := Semaphore new.</div>
                    <div>    ...</div>
                    <div>    s wait</div>
                    <div>    ...</div>
                    <div><br>
                    </div>
                    <div>if we look at the context containing the wait
                      its pc will be the same whether the process is
                      blocked, waiting on the semaphore, or whether the
                      semaphore has been signalled but the process has
                      not been able to proceed because it is of lower
                      priority than runnable processes and so can make
                      no progress.  This caused problems for code such
                      as this:</div>
                    <div><br>
                    </div>
                    <div>Semaphore>>critical:
                      mutuallyExcludedBlock</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>self
                      wait.</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>^mutuallyExcludedBlock
                      ensure: [self signal]</div>
                    <div><br>
                    </div>
                    <div>because the ensure: won't be entered if higher
                      priority runnable processes are preventing it from
                      running.</div>
                    <div><br>
                    </div>
                    <div>And for code such as this:</div>
                    <div><br>
                    </div>
                    <div>Semaphore>>critical:
                      mutuallyExcludedBlock</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> ^[</span>self
                      wait.</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>mutuallyExcludedBlock
                      value]</div>
                    <div><span style="white-space: pre-wrap;"> </span><span
                        style="white-space: pre-wrap;"> </span>ensure:
                      [self signal]</div>
                    <div><br>
                    </div>
                    <div>because if the process is terminated when the
                      semaphore has not been signalled (i.e. the process
                      is blocked in the wait), Process>>terminate
                      will run the ensure: block anyway, resulting in
                      the Semaphore getting an extra signal.</div>
                    <div><br>
                    </div>
                    <div>This occupied Andreas and I at Qwaq, and we
                      didn't solve it.  We developed Mutex as a more
                      efficient version of Monitor, but this is also
                      subject so the same problem.  We did change the
                      definition of ensure: so that it is not a
                      suspension point, by adding
                      valueNoContextSwitch[:]</div>
                    <div><br>
                    </div>
                    <div>
                      <div>BlockClosure>>ensure: aBlock</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Evaluate
                        a termination block after evaluating the
                        receiver, regardless of</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        whether the receiver's evaluation completes. 
                        N.B.  This method is *not*</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        implemented as a primitive.  Primitive 198
                        always fails.  The VM uses prim</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> 198
                        in a context's method as the mark for an
                        ensure:/ifCurtailed: activation."</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>|
                        complete returnValue |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span><primitive:
                        198></div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>returnValue
                        := self valueNoContextSwitch.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>complete
                        ifNil:[</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>complete
                        := true.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>aBlock
                        value.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^
                        returnValue</div>
                    </div>
                    <div><br>
                    </div>
                    <div>This means that we don't have to deal with
                      suspensions here (marked with !!!)</div>
                    <div><br>
                    </div>
                    <div>I now understand how to distinguish between the
                      two cases, between blocking and not blocked but no
                      progress.  Process>>suspend answers the list
                      the Process was on when it was suspended.  If the
                      process is already suspended
                      Process>>suspend answers nil.  If the
                      process is waiting on a Semaphore or a Mutex,
                      Process>>suspend answers the Semaphore or
                      Mutex. And if the process is runnable then
                      Process>>suspend answers the process's run
                      list (a LinkedList in ProcessorScheduler's <wbr>quiescentProcessLists
                      array corresponding to the process's priority).</div>
                    <div><br>
                    </div>
                    <div>So Process>>#terminate can distinguish
                      between #wait or #primitiveEnterCriticalSection or
                      #<wbr>primitiveTestAndSetOwnershipOf<wbr>CriticalSection
                      being blocked, or being unblocked but having made
                      no progress due to too low a priority.  We do so
                      by testing the class of the result of suspending
                      the process.  If it is a LinkedList, the process
                      has past the #wait or #<wbr>primitiveEnterCriticalSection <wbr>but
                      has made no progress due to too low a priority.</div>
                    <div><br>
                    </div>
                    <div>The version of Process>>#terminate I'm
                      about to commit deals with several cases.  Let me
                      present the cases first.  There are three versions
                      of Semaphore>>#critical: to handle, and one
                      version of Mutex>>critical: and
                      Mutex>>#critical:ifLocked:.</div>
                    <div><br>
                    </div>
                    <div>The two basic versions of
                      Semaphore>>critical: are</div>
                    <div><br>
                    </div>
                    <div>V1</div>
                    <div>
                      <div>critical: mutuallyExcludedBlock</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Evaluate
                        mutuallyExcludedBlock only if the receiver is
                        not currently in</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>the
                        process of running the critical: message. If the
                        receiver is, evaluate</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>mutuallyExcludedBlock
                        after the other critical: message is finished."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span><criticalSection></div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>self
                        wait.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^mutuallyExcludedBlock
                        ensure: [self signal]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>V2</div>
                    <div>
                      <div>critical: mutuallyExcludedBlock</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Evaluate
                        mutuallyExcludedBlock only if the receiver is
                        not currently in</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>the
                        process of running the critical: message. If the
                        receiver is, evaluate</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>mutuallyExcludedBlock
                        after the other critical: message is finished."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span><criticalSection></div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^[self
                        wait.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>  
                        mutuallyExcludedBlock value]</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ensure:
                        [self signal]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>and Juan's safer version is (after I added the
                      criticalSection pragma)</div>
                    <div><br>
                    </div>
                    <div>V3</div>
                    <div>
                      <div>critical: mutuallyExcludedBlock</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Evaluate
                        mutuallyExcludedBlock only if the receiver is
                        not currently in</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>the
                        process of running the critical: message. If the
                        receiver is, evaluate</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>mutuallyExcludedBlock
                        after the other critical: message is finished."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;">
                          <criticalSection></span></div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>|
                        caught |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"We
                        need to catch eventual interruptions very
                        carefully. </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>The
                        naive approach of just doing, e.g.,:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>self
                        wait.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>aBlock
                        ensure:[self signal].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>will
                        fail if the active process gets terminated while
                        in the wait.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>However,
                        the equally naive:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[self
                        wait.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>aBlock
                        value] ensure:[self signal].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>will
                        fail too, since the active process may get
                        interrupted while</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>entering
                        the ensured block and leave the semaphore
                        signaled twice.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>To
                        avoid both problems we make use of the fact that
                        interrupts only</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>occur
                        on sends (or backward jumps) and use an
                        assignment (bytecode)</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>right
                        before we go into the wait primitive (which is
                        not a real send and</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>therefore
                        not interruptable either)."</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>caught
                        := false.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^[</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>caught
                        := true.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>self
                        wait.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>mutuallyExcludedBlock
                        value</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>]
                        ensure: [ caught ifTrue: [self signal] ]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>and the Mutex>>critical:'s are</div>
                    <div><br>
                    </div>
                    <div>
                      <div>critical: aBlock</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Evaluate
                        aBlock protected by the receiver."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span><criticalSection></div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^self
                        primitiveEnterCriticalSection</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ifTrue:
                        [aBlock value]</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ifFalse:
                        [aBlock ensure: [self
                        primitiveExitCriticalSection]]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>
                      <div>critical: aBlock ifLocked: lockedBlock</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Answer
                        the evaluation of aBlock protected by the
                        receiver.  If it is already in a critical</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        section on behalf of some other process answer
                        the evaluation of lockedBlock."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span><criticalSection></div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^self
                        primitiveTestAndSetOwnershipOf<wbr>CriticalSection</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ifNil:
                        [lockedBlock value]</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ifNotNil:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[:alreadyOwner|</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        alreadyOwner</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ifTrue:
                        [aBlock value]</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ifFalse:
                        [aBlock ensure: [self
                        primitiveExitCriticalSection]]<wbr>]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>primitiveEnterCriticalSection answers false if
                      the Mutex was unowned, and true if it was already
                      owned by the active process.  It blocks otherwise.
                       <wbr>primitiveTestAndSetOwnershipOf<wbr>CriticalSection
                      answers false if the Mutex was unowned, true if it
                      was already owned by the active process, and nil
                      if owned by some other process.<br>
                    </div>
                    <div><br>
                    </div>
                    <div>So we want Process>>#terminate to
                      correctly release the semaphores and mutexes no
                      matter where in these methods they are.  We don't
                      have to worry if the process is within the block
                      argument to a critical: itself, only if it is
                      actually within the critical: method or a block
                      within it. If it is already within the block
                      argument to critical: then
                      Process>>#terminate's unwind handling will
                      unwind things correctly.  Taking Juan's version of
                      Semaphore>>#critical: above, the key issue
                      is whether the process being terminated is blocked
                      on the wait, not blocked but still stuck at the
                      wait, or at the start of the block argument to
                      ensure:.</div>
                    <div><br>
                    </div>
                    <div>I have extracted the processing into
                      Process>><wbr>releaseCriticalSection:, so
                      now Process>>terminate reads</div>
                    <div><br>
                    </div>
                    <div>
                      <div>terminate </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Stop
                        the process that the receiver represents
                        forever.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        Unwind to execute pending ensure:/ifCurtailed:
                        blocks before terminating.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> If
                        the process is in the middle of a critical:
                        critical section, release it properly."</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>| ctxt
                        unwindBlock oldList |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>self
                        isActiveProcess ifTrue: [</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        := thisContext.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[<span
class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        := ctxt findNextUnwindContextUpTo: nil.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        isNil</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>]
                        whileFalse: [</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>(ctxt
                        tempAt: 2) ifNil:[</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        tempAt: 2 put: nil.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>unwindBlock
                        := ctxt tempAt: 1.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>thisContext
                        terminateTo: ctxt.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>unwindBlock
                        value].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>thisContext
                        terminateTo: nil.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>self
                        suspend.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>]
                        ifFalse:[</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Always
                        suspend the process first so it doesn't
                        accidentally get woken up.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> N.B.
                        If oldList is a LinkedList then the process is
                        runnable. If it is a Semaphore/Mutex et al</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> then
                        the process is blocked, and if it is nil then
                        the process is already suspended."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>oldList
                        := self suspend.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>suspendedContext
                        ifNotNil:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>["Release
                        any method marked with the
                        <criticalSection> pragma.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>  The
                        argument is whether the process is runnable."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> self
                        releaseCriticalSection: (oldList isNil or:
                        [oldList class == LinkedList]).</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"If
                        terminating a process halfways through an
                        unwind, try to complete that unwind block
                        first."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>(suspendedContext
                        findNextUnwindContextUpTo: nil) ifNotNil:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[:outer|</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>(suspendedContext
                        findContextSuchThat:[:c| c closure == (outer
                        tempAt: 1)]) ifNotNil:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[:inner|
                        "This is an unwind block currently under
                        evaluation"</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>suspendedContext
                        runUntilErrorOrReturnFrom: inner]].</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        := self popTo: suspendedContext bottomContext.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        == suspendedContext bottomContext ifFalse:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[self
                        debug: ctxt title: 'Unwind error during
                        termination'].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Set
                        the context to its endPC for the benefit of
                        isTerminated."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>ctxt
                        pc: ctxt endPC]]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>In implementing releaseCriticalSection: we need
                      to know which selector a context has just sent.
                       selectorJustSentOrSelf is implemented in Squeak
                      as</div>
                    <div><br>
                    </div>
                    <div>InstructionStream>><wbr>selectorJustSentOrSelf</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>"If this
                      instruction follows a send, answer the send's
                      selector, otherwise answer self."</div>
                    <div><br>
                    </div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>| method
                      |</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>method
                      := self method.</div>
                    <div><span
                        class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                        style="white-space: pre-wrap;"> </span>^method
                      encoderClass selectorToSendOrItselfFor: self in:
                      method at: self previousPc</div>
                    <div><br>
                    </div>
                    <div>c.f.</div>
                    <div><br>
                    </div>
                    <div>
                      <div>InstructionStream>><wbr>selectorToSendOrSelf</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"If
                        this instruction is a send, answer the selector,
                        otherwise answer self."</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>|
                        method |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>method
                        := self method.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>^method
                        encoderClass selectorToSendOrItselfFor: self in:
                        method at: pc</div>
                    </div>
                    <div><br>
                    </div>
                    <div>Now we can implement Process>>#<wbr>releaseCriticalSection:</div>
                    <div><br>
                    </div>
                    <div>
                      <div>releaseCriticalSection: runnable</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Figure
                        out if we are terminating a process that is in
                        the ensure: block of a critical section.</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> In
                        this case, if the block has made progress, pop
                        the suspendedContext so that we leave the</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        ensure: block inside the critical: without
                        signaling the semaphore/exiting the primitive
                        section,</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> since
                        presumably this has already happened.  But if it
                        hasn't made progress but is beyond the</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> wait
                        (which we can tell my the oldList being one of
                        the runnable lists, i.e. a LinkedList, not a</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        Semaphore or Mutex, et al), then the ensure:
                        block needs to be run."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>|
                        selectorJustSent |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>(suspendedContext
                        method pragmaAt: #criticalSection) ifNil:
                        [^self].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>selectorJustSent
                        := suspendedContext selectorJustSentOrSelf.</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Receiver
                        and/or argument blocks of ensure: in
                        Semaphore>>critical: or
                        Mutex>>#critical:"</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>suspendedContext
                        isClosureContext ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        sender selector == #ensure: ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[|
                        notWaitingButMadeNoProgress |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Avoid
                        running the ensure: block twice, popping it if
                        it has already been run. If runnable</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> but
                        at the wait, leave it in place. N.B. No need to
                        check if the block receiver of ensure: has</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> not
                        started to run (via suspendedContext pc =
                        suspendedContext startpc) because ensure:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> uses
                        valueNoContextSwitch, and so there is no
                        suspension point before the wait."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        notWaitingButMadeNoProgress :=</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>runnable</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>and:
                        [selectorJustSent == #wait</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>and:
                        [suspendedContext sender selectorJustSentOrSelf
                        == #valueNoContextSwitch]].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        notWaitingButMadeNoProgress ifFalse:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        := suspendedContext home]].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        ^self].</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Either
                        Semaphore>>critical: or
                        Mutex>>#critical:.  Is the process still
                        blocked?  If so, nothing further to do."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>runnable
                        ifFalse: [^self].</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"If
                        still at the wait the ensure: block has not been
                        activated, so signal to restore."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>selectorJustSent
                        == #wait ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        receiver signal].</div>
                      <div><br>
                      </div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"If
                        still at the lock primitive and the lock
                        primitive just acquired ownership (indicated by
                        it answering false)</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> then
                        the ensure block has not been activated, so
                        explicitly primitiveExitCriticalSection to
                        unlock."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>(selectorJustSent
                        == #primitiveEnterCriticalSection</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> or:
                        [selectorJustSent == #<wbr>primitiveTestAndSetOwnershipOf<wbr>CriticalSection])
                        ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[(suspendedContext
                        stackPtr > 0</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>  and:
                        [suspendedContext top == false]) ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        receiver primitiveExitCriticalSection]]</div>
                    </div>
                    <div><br>
                    </div>
                    <div><br>
                    </div>
                    <div>Let's go through it line by line.  First,
                      runnable is an argument, determined in
                      Process>>#terminate.  One could invoke it
                      with</div>
                    <div><br>
                    </div>
                    <div>    self releaseCriticalSection: oldList class
                      == LinkedList<br>
                    </div>
                    <div><br>
                    </div>
                    <div>but this means that an already suspended
                      process is assumed to be not runnable, which makes
                      it tricky to debug the Process>>#terminate
                      method.  One has to assign to oldList while
                      stepping though the method.  I've chosen safety,
                      assuming that the process is still runnable if
                      suspend answers nil, its simply being debugged.</div>
                    <div><br>
                    </div>
                    <div>Then we're only interested in
                      <criticalSection> marked methods se we
                      return if there's no such pragma.</div>
                    <div><br>
                    </div>
                    <div>Then we deal with blocks in these methods.  One
                      issue here is to avoid running the ensure: block
                      twice if it is already being evaluated.  The other
                      is to run it if it is stalled and has yet to be
                      run.</div>
                    <div><br>
                    </div>
                    <div>So if</div>
                    <div><br>
                    </div>
                    <div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>suspendedContext
                        isClosureContext ifTrue:</div>
                    </div>
                    <div><br>
                    </div>
                    <div>we're in the ensure: receiver or argument
                      blocks in any <criticalSection> marked
                      method, i.e. Semaphore>>critical: and
                      Mutex>>critical:[ifLocked:].  If wait was
                      just sent then we're in the ensure: receiver block
                      of Semaphore>>critical: (V2 & V3 above)
                      and the issue is whether the process is blocked or
                      is unblocked and has made no progress. If blocked
                      then nothing needs to be done; the ensure: block
                      is discarded and the stack cut back to the
                      critical: activation.  If progress has been made
                      then nothing needs to be done (in fact we can't be
                      in this state; the ensure: receiver will have
                      started evaluating the critical: block argument). 
                      If unblocked, but no progress has been made, do
                      /not/ discard the unwind block and it will be run
                      in Process>>#terminate when this method
                      returns.  Hence...</div>
                    <div><br>
                    </div>
                    <div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        sender selector == #ensure: ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[|
                        notWaitingButMadeNoProgress |</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Avoid
                        running the ensure: block twice, popping it if
                        it has already been run. If runnable</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> but
                        at the wait, leave it in place. N.B. No need to
                        check if the block receiver of ensure: has</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> not
                        started to run (via suspendedContext pc =
                        suspendedContext startpc) because ensure:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> uses
                        valueNoContextSwitch, and so there is no
                        suspension point before the wait."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        notWaitingButMadeNoProgress :=</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>runnable</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>and:
                        [selectorJustSent == #wait</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>and:
                        [suspendedContext sender selectorJustSentOrSelf
                        == #valueNoContextSwitch]].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        notWaitingButMadeNoProgress ifFalse:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        := suspendedContext home]].</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>
                        ^self].</div>
                    </div>
                    <div><br>
                    </div>
                    <div>Now we're left with the simpler version of
                      Semaphore>>critical: (V1 above) and the two
                      Mutex methods Mutex>>#critical:[ifLocked:]. 
                      Here the only state we have to worry about is that
                      the process is unblocked but has made no
                      progress.  If not runnable the process is still
                      blocked and we can simply return.</div>
                    <div><br>
                    </div>
                    <div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"Either
                        Semaphore>>critical: or
                        Mutex>>#critical:.  Is the process still
                        blocked?  If so, nothing further to do."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>runnable
                        ifFalse: [^self].</div>
                      <div><br>
                      </div>
                    </div>
                    <div>If #wait was just sent the process is in
                      Semaphore>>#critical: and, because ensure:
                      has not been sent we signal explicitly to restore
                      the signal count:</div>
                    <div><br>
                    </div>
                    <div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"If
                        still at the wait the ensure: block has not been
                        activated, so signal to restore."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>selectorJustSent
                        == #wait ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        receiver signal].</div>
                    </div>
                    <div><br>
                    </div>
                    <div>If either of primitiveEnterCriticalSection or
                      primitiveTestAndSetOwnershipOf<wbr>CriticalSection
                      have just been sent then either the Mutex is
                      already owned, in which case the ensure block is
                      elsewhere in the colder part of the stack, or has
                      just been owned, and because ensure: has not been
                      sent we unlock explicitly to release the Mutex:</div>
                    <div><br>
                    </div>
                    <div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>"If
                        still at the lock primitive and the lock
                        primitive just acquired ownership (indicated by
                        it answering false)</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> then
                        the ensure block has not been activated, so
                        explicitly primitiveExitCriticalSection to
                        unlock."</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>(selectorJustSent
                        == #primitiveEnterCriticalSection</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span> or:
                        [selectorJustSent == #<wbr>primitiveTestAndSetOwnershipOf<wbr>CriticalSection])
                        ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[(suspendedContext
                        stackPtr > 0</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>  and:
                        [suspendedContext top == false]) ifTrue:</div>
                      <div><span
                          class="gmail-m_6592452582788869196gmail-Apple-tab-span"
                          style="white-space: pre-wrap;"> </span>[suspendedContext
                        receiver primitiveExitCriticalSection]]</div>
                    </div>
                    <div><br>
                    </div>
                    <div>So Pharoers can you read and say whether you
                      think this is sane or not?  If so, then we can
                      kibbutz to write the Pharo version.</div>
                    <div><br>
                    </div>
                    <div>Squeakers can you review Kernel-eem.1183
                      & Kernel-eem.1184 in the inbox? 
                      Kernel-eem.1183 includes the fix as described
                      above.  Kernel-eem.1184 reverts
                      Semaphore>>#critical: to V1 above.</div>
                    <div><br>
                    </div>
                    <div><br>
                    </div>
                    <div>P.S. Looking at V1 above it seems to me that
                      there is an issue if the process is preempted in
                      ensure: before sending valueNoContextSwitch:. 
                      I'll try and write a test that advances a process
                      to that precise point.  If that test fails I think
                      we have to use V2 or V3, and V2 is clearly
                      preferable.</div>
                  </div>
                </div>
              </div>
            </blockquote>
            <div><br>
            </div>
            <div>Lovely.  I added the test (testSemaCriticalWaitInEnsure
              & testMutexCriticalBlockedInEnsure) and it is V1 that
              works and V2 that does not.  I think it best not to try
              and be too clever and fix terminate and/or
              releaseCriticalSection: for this case.  We can simply
              stick with V1 for now.</div>
          </div>
          <br>
          <div class="gmail_signature">
            <div dir="ltr">
              <div><span style="font-size: small; border-collapse:
                  separate;">
                  <div>_,,,^..^,,,_<br>
                  </div>
                  <div>best, Eliot</div>
                </span></div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>