Acquiring multiple locks

nicolas cellier ncellier at ifrance.com
Tue Jun 27 00:33:58 UTC 2006


Hi Andreas,

Why using a primitive ? Because you are sure that processes are mutually 
excluded ?

In this case, why not using a GlobalMutex to get similar protection

Of course MutexSet cannot work due to deadlock... but this LockSet might:

Object subclass: #LockSet
    instanceVariableNames: 'array'
    classVariableNames: 'GlobalMutex'
    poolDictionaries: ''
    category: 'Kernel-Processes'

LockSet>>initialize
    array := Array new

LockSet>>withAll: locks
    array := locks

LockSet>>mutex
    "a global mutex with lazy initialization"
    GlobalMutex ifNil: [GlobalMutex := Mutex new].
    GlobalMutex

LockSet>>critical: aBlock
    "evaluate aBlock if we can acquire all locks"
    | indexFailed |
    [indexFailed := self mutex critical: 
        [(1 to: array size) detect: [:i | (array at: iLock)
            acquireNoWait = false] ifNone:
                [aBlock value.
               1 to: array size do: [:i | (array at: i) signal].
                0]]].
    indexFailed = 0] whileFalse:
        [(1 to: indexFailed -1) do: [:i | (array at: i) signal].
 (array at: indexFailed) wait; signal].

Semaphore>>acquireNoWait
    | waitingProcess wakeupProcess ok |
    waitingProcess := Processor activeProcess.
    ok := true.
    wakeupProcess :=
        [Processor yield.
        ok := false.
        self resumeProcess: waitingProcess] fork.
    self wait.
    wakeupProcess terminate.
    ^ok

You can replace wait by acquireLock, signal by releaseLock and acquireNoWait 
by acquireLockNoWait and replace Semaphore with your own Lock class...

I did not try it cause it's late but maybe you will.

Nicolas


Le Mardi 27 Juin 2006 00:12, Andreas Raab a écrit :
> Hi Folks -
>
> I have an interesting little problem that can be trivially solved with
> help from the VM but that I'm curious if there is a way of doing it from
> Squeak directly. Here is the problem:
>
> Given a set of N locks (semaphores), how can multiple processes acquire
> subsets of those locks without deadlocking? E.g., it's fairly obvious
> that if one process attempts to acquire lock A and B and another one
> lock B and A that this leads to deadlock in a hurry. What's in
> particular problematic for my use case is that I don't know which
> semaphores are part of said set of locks and that I can't establish a
> total order to make sure that lock A always gets acquired before lock B.
>
> What I've been contemplating is to add a primitive which does the
> following: It attempts to acquire all the locks given as argument and if
> one of them cannot be acquired it immediately releases all the locks
> acquired so far and leaves the process suspended on the "failing" lock.
> The return value will indicate whether all the locks were acquired and
> therefore one can write a loop like here to acquire all of the locks:
>
>    [self primitiveAcquireAll: locks] whileFalse.
>
> In other words, if all the locks can be acquired the code just marches
> through. If it fails to acquire a lock the process will stay suspended
> until that particular lock is released and then retry to acquire the locks.
>
> Is it possible to do that without a VM change?
>
> Cheers,
>    - Andreas




More information about the Squeak-dev mailing list