[Vm-dev] Where to get Monitor implementation based on primitives?

Ben Coman btc at openinworld.com
Sat Feb 6 03:56:57 UTC 2016


On Fri, Jan 8, 2016 at 9:39 PM, Ben Coman <btc at openinworld.com> wrote:
>
> btw, Looking at the following...
>   CriticalSection>>critical: aBlock
>       ^self primitiveEnterCriticalSection
>           ifTrue: [aBlock value]
>           ifFalse: [aBlock ensure: [self primitiveExitCriticalSection]]
>
> without intimate VM knowledge but seeing Eliot recently say
> "invocations of methods with primitives [...] are not suspension
> points, unless their primitives fail" -- I'm paranoid that since
> #ensure: primitive 198 always fail, there might be some some small
> window for a race where a process might be terminated before
> #primitiveExitCriticalSection can be executed. I'll take a refutation
> of this to improve the method comment.
>
> The following instils more confidence...
>
>   CriticalSection2>>critical: aBlock
>       | reEntered |
>       reEntered := false.
>       [ reEntered := self primitiveEnterCriticalSection.
>          aBlock value ] ensure:
>          [ reEntered ifFalse: [ self primitiveExitCriticalSection] ]

Having spent more time considering this, I found I was off track here.
If a process waiting at #primitiveEnterCriticalSection is terminated,
then #primitiveExitCriticalSection is erroneously executed.

And it will be the same problem with the proposal for Case17373 based
on OwnedLock>>acquire

  Mutex>>critical: aBlock
      |  lockAcquiredNotHere |
     <lockAt: #lock tracksStateAt: 1>
     lockAcquiredNotHere := true.
     ^[
           lockAcquiredNotHere := false.
           lockAcquiredNotHere := lock acquire.
           aBlock value
       ] ensure: [lockAcquiredNotHere ifFalse: [lock release]].

So now I believe the original #critical: proposed by Eliot is optimal.
* If #primitiveEnterCriticalSection is terminated while waiting, then
the #ifFalse: is never executed.
* When #primitiveEnterCriticalSection returns, the inlined
#ifTrue:ifFalse cant be interrupted.
* #ensure is a primitive which can't be interrupted.  By the time it
has done its usual "fail", which I raised concern over, actually it
has already done its job to make sure #primitiveExitCriticalSection is
executed.


More information about the Vm-dev mailing list