Allow recursive fc::mutexes

This commit is contained in:
Eric Frias 2014-10-12 17:28:41 -04:00
parent 4e83427df0
commit b63e6a8b81
2 changed files with 27 additions and 19 deletions

View file

@ -102,6 +102,7 @@ namespace fc {
private: private:
fc::spin_yield_lock m_blist_lock; fc::spin_yield_lock m_blist_lock;
fc::context* m_blist; fc::context* m_blist;
unsigned recursive_lock_count;
}; };
} // namespace fc } // namespace fc

View file

@ -7,8 +7,10 @@
namespace fc { namespace fc {
mutex::mutex() mutex::mutex() :
:m_blist(0){} m_blist(0),
recursive_lock_count(0)
{}
mutex::~mutex() { mutex::~mutex() {
if( m_blist ) if( m_blist )
@ -134,6 +136,8 @@ namespace fc {
{ {
// nobody else owns the mutex, so we get it; add our context as the last and only element on the mutex's list // nobody else owns the mutex, so we get it; add our context as the last and only element on the mutex's list
m_blist = current_context; m_blist = current_context;
assert(recursive_lock_count == 0);
recursive_lock_count = 1;
assert(!current_context->next_blocked_mutex); assert(!current_context->next_blocked_mutex);
return; return;
} }
@ -141,18 +145,14 @@ namespace fc {
// allow recusive locks // allow recusive locks
fc::context* dummy_context_to_unblock = 0; fc::context* dummy_context_to_unblock = 0;
if ( get_tail( m_blist, dummy_context_to_unblock ) == current_context ) { if ( get_tail( m_blist, dummy_context_to_unblock ) == current_context ) {
// if we already have the lock (meaning we're on the tail of the list) then assert(recursive_lock_count > 0);
// we shouldn't be trying to grab the lock again ++recursive_lock_count;
assert(false);
// EMF: I think recursive locks are currently broken -- we need to
// keep track of how many times this mutex has been locked by the
// current context. Unlocking should decrement this count and unblock
// the next context only if the count drops to zero
return; return;
} }
// add ourselves to the head of the list // add ourselves to the head of the list
current_context->next_blocked_mutex = m_blist; current_context->next_blocked_mutex = m_blist;
m_blist = current_context; m_blist = current_context;
++recursive_lock_count;
#if 0 #if 0
int cnt = 0; int cnt = 0;
@ -185,17 +185,24 @@ namespace fc {
} }
} }
void mutex::unlock() { void mutex::unlock()
{
fc::context* context_to_unblock = 0; fc::context* context_to_unblock = 0;
{ fc::unique_lock<fc::spin_yield_lock> lock(m_blist_lock);
get_tail(m_blist, context_to_unblock); fc::unique_lock<fc::spin_yield_lock> lock(m_blist_lock);
if( context_to_unblock ) { assert(recursive_lock_count > 0);
context_to_unblock->next_blocked_mutex = 0; --recursive_lock_count;
context_to_unblock->ctx_thread->my->unblock( context_to_unblock ); if (recursive_lock_count != 0)
} else { return;
m_blist = 0;
} get_tail(m_blist, context_to_unblock);
if( context_to_unblock )
{
context_to_unblock->next_blocked_mutex = 0;
context_to_unblock->ctx_thread->my->unblock( context_to_unblock );
} }
else
m_blist = 0;
} }
} // fc } // fc