Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-07-09 19:24:38


On Jul 9, 2004, at 6:54 PM, Glen Knowles wrote:

> From: Howard Hinnant [mailto:hinnant_at_[hidden]]
>> On Jul 9, 2004, at 4:11 PM, Peter Dimov wrote:
>>>> rw_mutex m;
>>>>
>>>> void invitation_for_deadlock()
>>>> {
>>>> read_lock r(m);
>>>> // ok to read
>>>> upgradable_read_lock ur(m);
>>>> r.unlock();
>>>> write_lock w(ur);
>>>> // ok to write
>>>> }
>>>>
>>>> It took me awhile to spot the deadlock in the above code. Does
>>>> anyone else see the above code as scary? (scary as in looks ok but
> isn't).
>>>> Or is the deadlock obvious to everyone else (and thus not scary)?
>>>
>>> Not scary, IMO, even if not obvious, because it always deadlocks, as
>>> soon as you attempt the "idiom". You can't miss it.
>>
>> I'm not following "always deadlocks". If only one thread enters, at
>> what point does it deadlock (assuming no other thread playing with m)?
>> Experimentally running through this on my prototype implementation
>> with a single thread isn't deadlocking. But perhaps my prototype is
> buggy?
>
> It only deadlocks under a race, but I'm not sure it's scary. It's
> something
> I'm use to seeing in the presents of r/w locks.

If r/w locks regularly encourage deadlocks, I am not anxious to further
pursue them. I'm not convinced of that however (and hope I won't be).
I'm seeking a system which makes it easy to avoid deadlocks, race
conditions, and leaked locks. Admittedly any system can be abused.
But a good system will naturally reduce accidental abuse, while not
necessarily preventing intentional abuse.

> I don't know where you left off, are you implementing single
> upgradeable or
> multiple upgradeables? If only one upgradeable can exist in the system
> at a
> time then, what would deadlock, will result in a failure to create a
> second
> upgradable lock, IIUC.

Single upgradable.

> You can always manufacture ways to deadlock, I'd still vote for just
> hanging
> a try/timed_promote() on all read locks. Unless perhaps there's
> overhead in
> upgradable_read_lock that isn't required in read_lock?

There's not overhead in the lock, but in the rw_mutex to support both
read/write and upgradable_read. But hanging a try_promote on multiple
upgradable read locks really makes me nervous. Doing so (imho) makes
deadlock significantly more likely (see my post with
lock_both/transfer_lock example).

Fwiw, here's what I'm seeing that is scaring me:

rw_mutex m;

void invitation_for_deadlock()
{
// 1
     read_lock r(m);
     // ok to read
// 2
     upgradable_read_lock ur(m);
// 3
     r.unlock();
// 4
     write_lock w(ur);
// 5
     // ok to write
}

Thread A Thread B
    1
    2
    3
    4
                        1
                        2

A holds ur.
B holds r.
A waits for B to unlock r so it can unlock ur and lock w.
B waits for A to unlock ur so it can lock ur.

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk