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

Denis Kudriashov dionisiydk at gmail.com
Mon Jan 11 12:59:08 UTC 2016


Hello.
I publish slice 17373
<https://pharo.fogbugz.com/f/cases/17373/Mutex-should-be-based-on-VM-primitives-and-implement-critical-methods-from-Semaphore>
.

I introduce LockOwnership class which implements VM primitives as:
- acquire
- tryAcquire
- release
(It comment saves copyright from CriticalSection)

Mutext uses it as ownership instance variable to implement critical methods
correctly:
- critical:
- critical:ifLocked:
- critical:ifError:
- critical:ifCurtailed:

For the integration process old Mutex instance variables are not removed. So
loading this code should not broke current Mutex instances. But when we
integrate it Mutex will have only variable ownership.

If you look critical implementation you will understand why I not like
semantic of primitives. it should be inverted in future. #acquire should
return true when ownership is acquired right now.

Process>>terminate now detects waiting on LockOwnership and ask it to
handle wait termination.Then LockOwnership inject right value into lock
state variable. Such variables should be marked with special pragma
    <lockAt: #ownershipVariableName tracksStateAt: 1> "index of local
variable"
Method can contain mulpible pragmas to reference all ownerships in method.
ReadWriteLock for example needs this.

2016-01-11 13:30 GMT+01:00 Henrik Johansen <henrik.s.johansen at veloxit.no>:

>
>
> On 08 Jan 2016, at 4:25 , Ben Coman <btc at openInWorld.com
> <btc at openinworld.com>> wrote:
>
>
> On Fri, Jan 8, 2016 at 9:39 PM, Ben Coman <btc at openinworld.com> wrote:
>
> On Fri, Jan 8, 2016 at 5:42 PM, stephane ducasse
> <stephane.ducasse at gmail.com> wrote:
>
>
> I have a (stupid) question.
> Is the code running without the primitives?
> Are the code below the primitives correct?
> I asked that because we can have 100 eyes and brains on the smalltalk
> level and far less on the VM primitive level.
>
>
> Because:
> 1. Concurrency bugs can be subtle and the *exact* conditions can be
> hard to reproduce for debugging.  For example, the solution to a
> couple of problems with Delay [1] [2] were solved by moving away from
> Semaphore>>critical: to use signalling.
>
> 2. The in-image atomicity of determining whether a signal was actually
> consumed or not during process suspension/termination is awkward.  Its
> seems hard to *really* know for sure it right (but I haven't looked in
> depth into Denis' latest proposals.)
>
> 3. The existing in-image implementation of Semaphore>>critical messes
> around in  Process>>terminate in a *special* way that is not easy for
> those 100 eyes to understand. For example, I personally am not
> comfortable with understanding how the special Semaphore handling in
> Process>>terminate works, but I can easily follow how
> primitiveEnterCriticalSection just looking at the code [3].
>
>
> Points 2 & 3 might possibly be addressed by having new
> primitiveWaitReturned
> *always* return true, so if the process is terminated while waiting,
> the assignment to signalConsumed doesn't occur...
>
>  critical: mutuallyExcludedBlock
>    signalConsumed := false.
>    [
>        signalConsumed := self primitiveWaitReturned.
>        blockValue := mutuallyExcludedBlock value
>    ] ensure: [ signalConsumed ifTrue: [self signal] ].
>    ^blockValue
>
> where primitiveWait (https://git.io/vuDjd) is copied
> and (just guessing) the marked line added...
>
>  primitiveWaitReturned
>      | sema excessSignals activeProc inInterpreter |
>      sema := self stackTop. "rcvr"
> "==>>" self pop: argumentCount + 1 thenPush: objectMemory trueObject.
> "<<=="
>     excessSignals := self fetchInteger: ExcessSignalsIndex ofObject: sema.
>      excessSignals > 0
>          ifTrue:
>            [self storeInteger: ExcessSignalsIndex
>                        ofObject: sema
>                        withValue: excessSignals - 1]
>          ifFalse:
>            inInterpreter := instructionPointer >= objectMemory
> startOfMemory.
>            activeProc := self activeProcess.
>            self addLastLink: activeProc toList: sema.
>            self transferTo: self wakeHighestPriority from: CSWait.
>            self
> forProcessPrimitiveReturnToExecutivePostContextSwitch: inInterpreter]
>
> which I guess could be added quickly if Esteban could compile the
> latest pharo-spur-vm ;)
>
> cheers -ben
>
>
> Won't work, there's no guarantee thread has actually ran and
> signalConsumed been assigned the primitive result after Semaphore resumed
> the waiting thread, before  a higher priority thread runs and terminates
> it. (which is exactly the case handled by special code in #terminate)
>
> Cheers,
> Henry
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20160111/f8590b8c/attachment-0001.htm


More information about the Vm-dev mailing list