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

Denis Kudriashov dionisiydk at gmail.com
Mon Jan 11 14:54:12 UTC 2016


I write it such way:

primitiveEnterCriticalSectionOnBehalfOf: activeProcess
[owningProcess ifNil:
[owningProcess := activeProcess.
^false].
 owningProcess = activeProcess ifTrue:
[^true].
 self addLast: Processor activeProcess.
activeProcess suspend] valueUnpreemptively

primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: activeProcess
[owningProcess ifNil:
[owningProcess := activeProcess.
^false].
 owningProcess = activeProcess ifTrue: [^true].
 ^nil] valueUnpreemptively

2016-01-11 14:58 GMT+01:00 Denis Kudriashov <dionisiydk at gmail.com>:

> Eliot I found that there are no methods for simulation code (if it right
> name for it). So stepping over new primitives failed (which is infinite
> recursion for Pharo case)
>
> Context>>doPrimitive: primitiveIndex method: meth receiver: aReceiver
> args: arguments
> ...
> "Mutex>>primitiveEnterCriticalSection
> Mutex>>primitiveTestAndSetOwnershipOfCriticalSection"
> (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue:
> [| active effective |
> active := Processor activeProcess.
> effective := active effectiveProcess.
> "active == effective"
> value := primitiveIndex = 186
> ifTrue: [aReceiver *primitiveEnterCriticalSectionOnBehalfOf*: effective]
> ifFalse: [aReceiver
> *primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf*: effective].
> ^(self isPrimFailToken: value)
> ifTrue: [value]
> ifFalse: [self push: value]].
>
> How this methods should be implemented?
>
> 2016-01-11 13:59 GMT+01:00 Denis Kudriashov <dionisiydk at gmail.com>:
>
>> 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/84fbc26b/attachment-0001.htm


More information about the Vm-dev mailing list