Click to See Complete Forum and Search --> : Linux Mutex Problem-Could anyone help


Kohinoor24
September 17th, 2002, 11:01 AM
I have a multithreaded application running under Linux.
When Iam Debugging I have another problem ,Iam getting a Deadlock

I have implemented the LinuxMutex class as follows:

LinMutex::LinMutex()
{
pthread_mutex_init(&m_hMutex,(pthread_mutexattr_t*)NULL);

}
void LinMutex::AcquireLock()
{
pthread_mutex_lock(&m_hMutex);
}

void LinMutex::ReleaseLock()
{
pthread_mutex_unlock(&m_hMutex);
}

LinMutex::~LinMutex()
{
pthread_mutex_destroy(&m_hMutex);

}

Is it alright.I heard from a colleuge,that If a thread which already owns a Mutex,Try to access,it again there will be a deadlock under Linux.

In windows,I have implemented the lock() as follows to remove the DeadLock as said in Msdn:
// from Msdn
The thread that owns a mutex can specify the same mutex in repeated wait function calls without blocking its execution. Typically, you would not wait repeatedly for the same mutex, but this mechanism prevents a thread from deadlocking itself while waiting for a mutex that it already owns. However, to release its ownership, the thread must call ReleaseMutex once for each time that the mutex satisfied a wait.

void WinMutex::AcquireLock()
{
while (WaitForSingleObject(m_hMutex,1000L)!= WAIT_OBJECT_0);
}


What should I do to remove the Deadlock.What should be done in The AcquireLock() of LinMutex.
Could anyone help me on this regard.....

cup
September 17th, 2002, 12:28 PM
pthread_mutex_lock will block the thread until it acquires the lock. If the thread already has the mutex, obtaining it again will cause deadlock.

Try this. It used to work on Solaris and HPUX.

In LinMutex, add the variables

pthread_t mSelfish;
int mLocks;

LinMutex::LinMutex()
{
pthread_mutex_init(&m_hMutex,(pthread_mutexattr_t*)NULL);
mSelfish = 0;
mLocks = 0;
}
void LinMutex::AcquireLock()
{
if (mSelfish == pthread_self ())
{
mLocks++;
}
else
{
pthread_mutex_lock(&m_hMutex);
mSelfish = pthread_self ();
mLocks = 1;
}
}

void LinMutex::ReleaseLock()
{
if (mSelfish == pthread_self ())
{
if (--mLocks == 0)
{
mSelfish = 0;
pthread_mutex_unlock(&m_hMutex);
}
}
}

This assumes that the number of acquires == the number of releases. If it doesn't, you still get deadlocked. The way I prefer to code it is to use the out-of-scope destructor technique. There may be some fancy name for this technique that I've been using for the last 9 years.

class LockIt
{
static pthread_mutex_t mMutex;
static bool mUnknown;
static pthread_t mSelfish;
static int mCount;
public:
Lockit ()
{
if (mUnknown)
{
mUnknown = false;
pthread_mutex_init ((&mMutex,(pthread_mutexattr_t*)NULL);
mSelfish = 0;
mCount = 0;
}
if (mSelfish != pthread_self ())
{
pthread_mutex_lock(&mMutex);
mSelfish = pthread_self ();
}
mCount++;
}
~Lockit ()
{
mCount--;
if (mCount == 0)
{
pthread_mutex_unlock (&mMutex);
}
}
};
// Static declarations
pthread_mutex_t Lockit::mMutex;
bool Lockit::mUnknown = true;
pthread_t Lockit::mSelf = 0;
int Lockit::mCount = 0;

// Simple routine using the mutex lock
void Critical ()
{
Lockit sema;

// do whatever

// Natural destructor when sema goes out of scope so you
// don't even have to delete it.
}

It is just so much neater not having to worry about unlocking.

Kohinoor24
September 19th, 2002, 01:34 AM
Hi,
Thank you very Much for that piece of code & for ur valuable suggestion.It was really helpful for me.Thanks a lot.
I will send u personal messages when ever I have some problems in Linux ,if u dont mind :)

dimm_coder
September 20th, 2002, 01:31 AM
It's also most easy way for U.
Linux support some kind of mutexes.
The mutex kind determines what happens if a thread attempts to lock a mutex it already owns with pthread_mutex_lock.

There are next kinds:
PTHREAD_MUTEX_FAST_NP - fast mutex ( it's by default ) this mutex deadlock your thread if it try to lock mutex it already owns.
PTHREAD_MUTEX_RECURSIVE_NP - recursive mutex
this mutex has internal counter of locks and it
don't deadlock the thread. thread_mutex_lock
simply return OK status if you try to lock mutex it already owns.
PTHREAD_MUTEX_ERRORCHECK_NP - else like PTHREAD_MUTEX_RECURSIVE_NP but return error status.

so you mast write:

pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

or use

pthread_mutexattr_init() and pthread_mutexattr_setkind_np functions to set PTHREAD_MUTEX_RECURSIVE_NP kind for mutex.