Home | History | Annotate | Download | only in common
      1 //===-- Mutex.cpp -----------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Host/Mutex.h"
     11 #include "lldb/Host/Host.h"
     12 
     13 #include <string.h>
     14 #include <stdio.h>
     15 #include <unistd.h>
     16 
     17 #if 0
     18 // This logging is way too verbose to enable even for a log channel.
     19 // This logging can be enabled by changing the "#if 0", but should be
     20 // reverted prior to checking in.
     21 #include <cstdio>
     22 #define DEBUG_LOG(fmt, ...) printf(fmt, ## __VA_ARGS__)
     23 #else
     24 #define DEBUG_LOG(fmt, ...)
     25 #endif
     26 
     27 // Enable extra mutex error checking
     28 #ifdef LLDB_CONFIGURATION_DEBUG
     29 #define ENABLE_MUTEX_ERROR_CHECKING 1
     30 #include <inttypes.h>
     31 #endif
     32 
     33 #if ENABLE_MUTEX_ERROR_CHECKING
     34 #include <set>
     35 
     36 enum MutexAction
     37 {
     38     eMutexActionInitialized,
     39     eMutexActionDestroyed,
     40     eMutexActionAssertInitialized
     41 };
     42 
     43 static bool
     44 error_check_mutex (pthread_mutex_t *m, MutexAction action)
     45 {
     46     typedef std::set<pthread_mutex_t *> mutex_set;
     47     static pthread_mutex_t g_mutex_set_mutex = PTHREAD_MUTEX_INITIALIZER;
     48     static mutex_set g_initialized_mutex_set;
     49     static mutex_set g_destroyed_mutex_set;
     50 
     51     bool success = true;
     52     int err;
     53     // Manually call lock so we don't to any of this error checking
     54     err = ::pthread_mutex_lock (&g_mutex_set_mutex);
     55     assert(err == 0);
     56     switch (action)
     57     {
     58         case eMutexActionInitialized:
     59             // Make sure this isn't already in our initialized mutex set...
     60             assert (g_initialized_mutex_set.find(m) == g_initialized_mutex_set.end());
     61             // Remove this from the destroyed set in case it was ever in there
     62             g_destroyed_mutex_set.erase(m);
     63             // Add the mutex to the initialized set
     64             g_initialized_mutex_set.insert(m);
     65             break;
     66 
     67         case eMutexActionDestroyed:
     68             // Make sure this isn't already in our destroyed mutex set...
     69             assert (g_destroyed_mutex_set.find(m) == g_destroyed_mutex_set.end());
     70             // Remove this from the initialized so we can put it into the destroyed set
     71             g_initialized_mutex_set.erase(m);
     72             // Add the mutex to the destroyed set
     73             g_destroyed_mutex_set.insert(m);
     74             break;
     75         case eMutexActionAssertInitialized:
     76             // This function will return true if "m" is in the initialized mutex set
     77             success = g_initialized_mutex_set.find(m) != g_initialized_mutex_set.end();
     78             assert (success);
     79             break;
     80     }
     81     // Manually call unlock so we don't to any of this error checking
     82     err = ::pthread_mutex_unlock (&g_mutex_set_mutex);
     83     assert(err == 0);
     84     return success;
     85 }
     86 
     87 #endif
     88 
     89 using namespace lldb_private;
     90 
     91 //----------------------------------------------------------------------
     92 // Default constructor.
     93 //
     94 // This will create a scoped mutex locking object that doesn't have
     95 // a mutex to lock. One will need to be provided using the Reset()
     96 // method.
     97 //----------------------------------------------------------------------
     98 Mutex::Locker::Locker () :
     99     m_mutex_ptr(NULL)
    100 {
    101 }
    102 
    103 //----------------------------------------------------------------------
    104 // Constructor with a Mutex object.
    105 //
    106 // This will create a scoped mutex locking object that extracts the
    107 // mutex owned by "m" and locks it.
    108 //----------------------------------------------------------------------
    109 Mutex::Locker::Locker (Mutex& m) :
    110     m_mutex_ptr(NULL)
    111 {
    112     Lock (m);
    113 }
    114 
    115 //----------------------------------------------------------------------
    116 // Constructor with a Mutex object pointer.
    117 //
    118 // This will create a scoped mutex locking object that extracts the
    119 // mutex owned by "m" and locks it.
    120 //----------------------------------------------------------------------
    121 Mutex::Locker::Locker (Mutex* m) :
    122     m_mutex_ptr(NULL)
    123 {
    124     if (m)
    125         Lock (m);
    126 }
    127 
    128 //----------------------------------------------------------------------
    129 // Destructor
    130 //
    131 // Unlocks any owned mutex object (if it is valid).
    132 //----------------------------------------------------------------------
    133 Mutex::Locker::~Locker ()
    134 {
    135     Unlock();
    136 }
    137 
    138 //----------------------------------------------------------------------
    139 // Unlock the current mutex in this object (if this owns a valid
    140 // mutex) and lock the new "mutex" object if it is non-NULL.
    141 //----------------------------------------------------------------------
    142 void
    143 Mutex::Locker::Lock (Mutex &mutex)
    144 {
    145     // We already have this mutex locked or both are NULL...
    146     if (m_mutex_ptr == &mutex)
    147         return;
    148 
    149     Unlock ();
    150 
    151     m_mutex_ptr = &mutex;
    152     m_mutex_ptr->Lock();
    153 }
    154 
    155 void
    156 Mutex::Locker::Unlock ()
    157 {
    158     if (m_mutex_ptr)
    159     {
    160         m_mutex_ptr->Unlock ();
    161         m_mutex_ptr = NULL;
    162     }
    163 }
    164 
    165 bool
    166 Mutex::Locker::TryLock (Mutex &mutex, const char *failure_message)
    167 {
    168     // We already have this mutex locked!
    169     if (m_mutex_ptr == &mutex)
    170         return true;
    171 
    172     Unlock ();
    173 
    174     if (mutex.TryLock(failure_message) == 0)
    175         m_mutex_ptr = &mutex;
    176 
    177     return m_mutex_ptr != NULL;
    178 }
    179 
    180 //----------------------------------------------------------------------
    181 // Default constructor.
    182 //
    183 // Creates a pthread mutex with no attributes.
    184 //----------------------------------------------------------------------
    185 Mutex::Mutex () :
    186     m_mutex()
    187 {
    188     int err;
    189     err = ::pthread_mutex_init (&m_mutex, NULL);
    190 #if ENABLE_MUTEX_ERROR_CHECKING
    191     if (err == 0)
    192         error_check_mutex (&m_mutex, eMutexActionInitialized);
    193 #endif
    194     assert(err == 0);
    195 }
    196 
    197 //----------------------------------------------------------------------
    198 // Default constructor.
    199 //
    200 // Creates a pthread mutex with "type" as the mutex type.
    201 //----------------------------------------------------------------------
    202 Mutex::Mutex (Mutex::Type type) :
    203     m_mutex()
    204 {
    205     int err;
    206     ::pthread_mutexattr_t attr;
    207     err = ::pthread_mutexattr_init (&attr);
    208     assert(err == 0);
    209     switch (type)
    210     {
    211     case eMutexTypeNormal:
    212 #if ENABLE_MUTEX_ERROR_CHECKING
    213         err = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK);
    214 #else
    215         err = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL);
    216 #endif
    217         break;
    218 
    219     case eMutexTypeRecursive:
    220         err = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
    221         break;
    222     }
    223     assert(err == 0);
    224     err = ::pthread_mutex_init (&m_mutex, &attr);
    225 #if ENABLE_MUTEX_ERROR_CHECKING
    226     if (err == 0)
    227         error_check_mutex (&m_mutex, eMutexActionInitialized);
    228 #endif
    229     assert(err == 0);
    230     err = ::pthread_mutexattr_destroy (&attr);
    231     assert(err == 0);
    232 }
    233 
    234 //----------------------------------------------------------------------
    235 // Destructor.
    236 //
    237 // Destroys the mutex owned by this object.
    238 //----------------------------------------------------------------------
    239 Mutex::~Mutex()
    240 {
    241     int err = ::pthread_mutex_destroy (&m_mutex);
    242     assert(err == 0);
    243 #if ENABLE_MUTEX_ERROR_CHECKING
    244     if (err == 0)
    245         error_check_mutex (&m_mutex, eMutexActionDestroyed);
    246     else
    247     {
    248         Host::SetCrashDescriptionWithFormat ("%s error: pthread_mutex_destroy() => err = %i (%s)", __PRETTY_FUNCTION__, err, strerror(err));
    249         assert(err == 0);
    250     }
    251     memset (&m_mutex, '\xba', sizeof(m_mutex));
    252 #endif
    253 }
    254 
    255 //----------------------------------------------------------------------
    256 // Mutex get accessor.
    257 //----------------------------------------------------------------------
    258 pthread_mutex_t *
    259 Mutex::GetMutex()
    260 {
    261     return &m_mutex;
    262 }
    263 
    264 //----------------------------------------------------------------------
    265 // Locks the mutex owned by this object, if the mutex is already
    266 // locked, the calling thread will block until the mutex becomes
    267 // available.
    268 //
    269 // RETURNS
    270 //  The error code from the pthread_mutex_lock() function call.
    271 //----------------------------------------------------------------------
    272 int
    273 Mutex::Lock()
    274 {
    275     DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_lock (%p)...\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex);
    276 
    277 #if ENABLE_MUTEX_ERROR_CHECKING
    278     error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
    279 #endif
    280 
    281     int err = ::pthread_mutex_lock (&m_mutex);
    282 
    283 
    284 #if ENABLE_MUTEX_ERROR_CHECKING
    285     if (err)
    286     {
    287         Host::SetCrashDescriptionWithFormat ("%s error: pthread_mutex_lock(%p) => err = %i (%s)", __PRETTY_FUNCTION__, &m_mutex, err, strerror(err));
    288         assert(err == 0);
    289     }
    290 #endif
    291     DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_lock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
    292     return err;
    293 }
    294 
    295 //----------------------------------------------------------------------
    296 // Attempts to lock the mutex owned by this object without blocking.
    297 // If the mutex is already locked, TryLock() will not block waiting
    298 // for the mutex, but will return an error condition.
    299 //
    300 // RETURNS
    301 //  The error code from the pthread_mutex_trylock() function call.
    302 //----------------------------------------------------------------------
    303 int
    304 Mutex::TryLock(const char *failure_message)
    305 {
    306 #if ENABLE_MUTEX_ERROR_CHECKING
    307     error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
    308 #endif
    309 
    310     int err = ::pthread_mutex_trylock (&m_mutex);
    311     DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_trylock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
    312     return err;
    313 }
    314 
    315 //----------------------------------------------------------------------
    316 // If the current thread holds the lock on the owned mutex, then
    317 // Unlock() will unlock the mutex. Calling Unlock() on this object
    318 // that the calling thread does not hold will result in undefined
    319 // behavior.
    320 //
    321 // RETURNS
    322 //  The error code from the pthread_mutex_unlock() function call.
    323 //----------------------------------------------------------------------
    324 int
    325 Mutex::Unlock()
    326 {
    327 #if ENABLE_MUTEX_ERROR_CHECKING
    328     error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
    329 #endif
    330 
    331     int err = ::pthread_mutex_unlock (&m_mutex);
    332 
    333 #if ENABLE_MUTEX_ERROR_CHECKING
    334     if (err)
    335     {
    336         Host::SetCrashDescriptionWithFormat ("%s error: pthread_mutex_unlock(%p) => err = %i (%s)", __PRETTY_FUNCTION__, &m_mutex, err, strerror(err));
    337         assert(err == 0);
    338     }
    339 #endif
    340     DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_unlock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
    341     return err;
    342 }
    343 
    344 #ifdef LLDB_CONFIGURATION_DEBUG
    345 int
    346 TrackingMutex::Unlock ()
    347 {
    348     if (!m_failure_message.empty())
    349         Host::SetCrashDescriptionWithFormat ("Unlocking lock (on thread %p) that thread: %p failed to get: %s",
    350                                              pthread_self(),
    351                                              m_thread_that_tried,
    352                                              m_failure_message.c_str());
    353     assert (m_failure_message.empty());
    354     return Mutex::Unlock();
    355 }
    356 
    357 int
    358 LoggingMutex::Lock ()
    359 {
    360     printf("locking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
    361     int x = Mutex::Lock();
    362     m_locked = true;
    363     printf("%d\n",x);
    364     return x;
    365 }
    366 
    367 int
    368 LoggingMutex::Unlock ()
    369 {
    370     printf("unlocking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
    371     int x = Mutex::Unlock();
    372     m_locked = false;
    373     printf("%d\n",x);
    374     return x;
    375 }
    376 
    377 int
    378 LoggingMutex::TryLock (const char *failure_message)
    379 {
    380     printf("trylocking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
    381     int x = Mutex::TryLock(failure_message);
    382     if (x == 0)
    383         m_locked = true;
    384     printf("%d\n",x);
    385     return x;
    386 }
    387 
    388 #endif
    389 
    390 
    391