Re: How to check if a mutex is still locked?



On Sep 11, 11:07 pm, jonnie <jsav...@xxxxxxxxx> wrote:

Let us keep Szabolcs happy and provide a satisfactory alternative to
the isLocked/unLock duo.

You would rather make me happy if you guys could afford to keep to the
simple basic rules of multiprogramming:

1. Shared resource should only be handled inside critical regions

2. Outside of the critical region you should not take any action based
on the status of the shared resource

Simple, isn't it?

It all comes from the fundamental fact that in a multiprogramming
environment the "once false, always false" does not hold for shared
resources. So we either have to adapt to it, on the one hand, or we
have to change the circumstances to keep to the "once false, always
false" when we need it (hence the critical region).

Now let us suppose for the moment that the shared resource is the
particular mutex mentioned in the initial message. Furthermore, let us
suppose that the mutex can be unlocked by any thread other than the
owner and a query is provided whether it is locked. Then, you must
introduce a super mutex and handle your mutex under the protection of
the super mutex only. In pseudo code, it would be something like this:

class crazy_mutex_handling

private: the_super_mutex
private: the_mutex // i.e. the shared resource

check_and_unlock_by_others:
lock the_super_mutex
if not locked
unlock the_mutex
unlock the_super_mutex

The consequence is that locking and unlocking must be done under the
protection of the wrapper mutex as well:

unlock_by_owner:
lock the_super_mutex
unlock the_mutex
unlock the_super_mutex

lock:
lock the_super_mutex
lock the_mutex
unlock the_super_mutex

Ooops! Locking cannot be simple like that. Already the second thread
would drive the system into a deadlock if the first one has not
released the crazy mutex yet. So, in case the internal mutex is
locked, the new thread must be delayed by other means. Let us
introduce a semaphore for the middle term scheduling:

private: the_sema

The locking is changed like this:

lock:
lock the_super_mutex
if locked
unlock the_super_mutex
wait the_sema
lock the_super_mutex
lock the_mutex
unlock the_super_mutex

But then, the semaphore must be handled in the unlocking methods as
well:

unlock_by_owner:
lock the_super_mutex
unlock the_mutex
signal the_sema
unlock the_super_mutex

check_and_unlock_by_others:
lock the_super_mutex
if not locked
unlock the_mutex
signal the_sema
unlock the_super_mutex

Actually, you can see that the mutex does not effectively work now
since the scheduling is taken over by the semaphore. The shared
resource (the_mutex) can be replaced by a single boolean variable
resulting in the class:

class crazy_mutex

private: the_super_mutex
private: the_sema
private: mocked_mutex_locked = false // i.e. the shared resource

lock:
lock the_super_mutex
if mocked_mutex_locked
unlock the_super_mutex
wait the_sema
lock the_super_mutex
mocked_mutex_locked = true
unlock the_super_mutex

unlock_by_owner:
lock the_super_mutex
mocked_mutex_locked = false
signal the_sema
unlock the_super_mutex

check_and_unlock_by_others:
lock the_super_mutex
if not mocked_mutex_locked
mocked_mutex_locked = false
signal the_sema
unlock the_super_mutex

Now, what we finally have is a monitor data structure built from mutex
and semaphore.

You can use an object of the class crazy mutex for that special
requirement, though, the `check and unlock by others´ method is still
strange in a multiprogramming environment. On the one hand, by default
you unlock a mutex if you have locked it before. You do not have to
check this (just see the use of the super mutex above). On the other
hand, it is still an action on a non-deterministic status if another
thread tries to unlock a mutex, i.e. if it takes an action on a
momentary status of the shared resource.

Finally, let me note that the mutex serves for short term scheduling
only. If the need ever arises in your program to check and unlock any
mutex it means in the first place that most likely you misuse the
mutex.

Best Regards,
Szabolcs

.



Relevant Pages

  • Re: A scoped lock/unlock implementation in C++.
    ... mutex_locker wrapping the same mutex, more than one thread won't share ... But beyond that it will still work with thread local mutex_locker instances, since no two threads can have a nonzero lock count anyway. ... When entering a locked region, if the last entry is negative, you know ... In case of unlocks even the unlock count is insignificant. ...
    (comp.programming.threads)
  • Pthreads: how to insure mutex is unlocked when a thread dies.
    ... Anyway, I was planning to have this thread lock a mutex when it starts, ... unlock it when it's done, e.g., when the application notifies it to ... I'm concerned that if the thread dies before the application notifies ...
    (comp.programming.threads)
  • Re: A scoped lock/unlock implementation in C++.
    ... namely a guarantee that a scoped_unlock *will* unlock the mutex lock ... You may protect the mutex::lock and unlock functions and declare the ... lock function and a locked flag. ...
    (comp.programming.threads)
  • Re: double-checked locking in C
    ... Except that threads may never lock the mutex. ... guarantee they'll ever see the initialization. ... you don't call 'lock' or 'unlock' if the initialization ...
    (comp.programming.threads)
  • Re: semantics of pthread locks
    ... but why must a shared resource be tested prior to ... > until a shared counter reaches a certain value: why must it test for the ...
    (comp.os.linux.development.system)