Re: mutex problems on Windows



On Tue, 7 Jul 2009 12:19:27 +0300
Dov Grobgeld <dov grobgeld gmail com> wrote:
> Hi Richard,
> 
> As far as I understand from your pseudo code you are doing the same
> mistake as I did in my first effort, namely to lock the same mutex
> twice in the same thread, and to expect that the second invocation
> will block until another thread releases the mutex. You do this in 3
> and in 6. Indeed I, like you, found out that this works under Linux,
> but Tor pointed out that the documentation states that this is
> undefined behaviour, and indeed it does not work under Windows.
> That's why I used the GCond instead.
> 
> Regards,
> Dov
> 
> 2009/7/7 richard boaz <ivor boaz gmail com>
> 
> > Hi Dov,
> >
> > I have solved this in a diferent way that does seem to be a bit
> > easier, and is a little more like your first algorithm.  (indeed,
> > your second solution does seem a bit convoluted.)
> >
> > First, different from your mutex, I'm using a static mutex that is
> > referenced everywhere.  And, my program is not one of a GUI and a
> > worker thread, but between the main program and multiple worker
> > threads, though the general idea is the same.
> >
> > The general algorithm is:
> >
> >    1. main thread (M) does program setup
> >    2. M then calls routine (TM) directly to set up the worker
> > threads (i.e, TM is NOT a separate thread from M)
> >    3. TM immediately locks the static mutex
> >    4. TM then creates as many threads (T*n*) as there are CPU's
> > available 5. TM returns control to M
> >    6. M: upon return from TM, immediately calls
> > g_static_mutex_lock(), blocking flow since this has already been
> > locked in step 3. 7. T*n*: all threads do their work until
> > complete.  Once complete, each thread calls a common thread finish
> > routine (TF) that keeps track of when all threads have completed.
> >    8. TF: Once all threads are complete, static mutex locked in
> > step 3 is unlocked.
> >    9. M: block from step 6 can now continue
[snip]
> > richard

Richard's approach can be made to work on unix-like OSes (ie those where
the underlying threading is pthreads) because it respects mutex
ownership of a locked mutex and the result of double locking a
non-recursive mutex is defined in pthreads if you choose
PTHREAD_MUTEX_NORMAL as the mutex type, as deadlocking is mandatory in
that case, but not otherwise (this is from the POSIX standard):

"PTHREAD_MUTEX_NORMAL: This type of mutex does not detect deadlock. A
thread attempting to relock this mutex without first unlocking it shall
deadlock. Attempting to unlock a mutex locked by a different thread
results in undefined behavior. Attempting to unlock an unlocked mutex
results in undefined behavior.

PTHREAD_MUTEX_ERRORCHECK This type of mutex provides error checking. A
thread attempting to relock this mutex without first unlocking it shall
return with an error. A thread attempting to unlock a mutex which
another thread has locked shall return with an error. A thread
attempting to unlock an unlocked mutex shall return with an error.
PTHREAD_MUTEX_RECURSIVE A thread attempting to relock this mutex
without first unlocking it shall succeed in locking the mutex. The
relocking deadlock which can occur with mutexes of type

PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple
locks of this mutex shall require the same number of unlocks to release
the mutex before another thread can acquire the mutex. A thread
attempting to unlock a mutex which another thread has locked shall
return with an error. A thread attempting to unlock an unlocked mutex
shall return with an error.

PTHREAD_MUTEX_DEFAULT Attempting to recursively lock a mutex of this
type results in undefined behavior. Attempting to unlock a mutex of
this type which was not locked by the calling thread results in
undefined behavior. Attempting to unlock a mutex of this type which is
not locked results in undefined behavior."

However, GThreads most likely uses PTHREAD_MUTEX_DEFAULT in which case
the fact that it works is a matter of luck (although all
implementations I have seen do in fact deadlock with
PTHREAD_MUTEX_DEFAULT). Dov's implementation also suffered from the
problem of a non-owning thread unlocking the mutex, which is undefined
behaviour for all mutex types.

Altogether, it would be better to use either POSIX semaphores (for
which Dov's approach would be fine as semaphores are not owned) but
which are not found in GThreads, or condition variables, which are.

Chris



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]