|
Boost : |
From: Mariusz Kedzierawski (m.kedzierawski_at_[hidden])
Date: 2006-09-28 12:40:28
Hi
I think there is a problem in implementation of function: void
condition_impl::notify_one() (with BOOST_HAS_MPTASKS beeing defined -
apple version) in file condition.cpp
There is no mutex release before leaving that function in one place:
(The same problem is in fuction notify_all)
//------[ BEGIN ]------------------------------------
void condition_impl::notify_one()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
++m_waiting;
--m_blocked;
/************************************************/
/************************************************/
There is no MPExitCriticalRegion(m_mutex) here !
/************************************************/
/************************************************/
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = 1;
--m_blocked;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
/************************************************/
/************************************************/
Solution could be putting "}" here instead of after ongoing while
(signals) {...}
/************************************************/
/************************************************/
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
//------[ END ]------------------------------------
Second problem is in file condition.hpp
//------[ BEGIN ]------------------------------------
template <typename M>
void do_wait(M& mutex)
{
/...
m_impl.enter_wait();
//...
lock_ops::unlock(mutex, state);
/************************************************/
/************************************************/
Unlocking mutex and hanging on semaphore should be atomic operation
and here it is not (notification can be lost here (becouse of
switching between threads) and thread can than wait for it forever).
/************************************************/
/************************************************/
m_impl.do_wait();
//...
lock_ops::lock(mutex, state);
//...
}
//------[ END ]------------------------------------
Please correct me if I am wrong :)
-- Mariusz Kedzierawski M(dot)Kedzierawski_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk