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 36enum MutexAction 37{ 38 eMutexActionInitialized, 39 eMutexActionDestroyed, 40 eMutexActionAssertInitialized 41}; 42 43static bool 44error_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 89using 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//---------------------------------------------------------------------- 98Mutex::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//---------------------------------------------------------------------- 109Mutex::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//---------------------------------------------------------------------- 121Mutex::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//---------------------------------------------------------------------- 133Mutex::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//---------------------------------------------------------------------- 142void 143Mutex::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 155void 156Mutex::Locker::Unlock () 157{ 158 if (m_mutex_ptr) 159 { 160 m_mutex_ptr->Unlock (); 161 m_mutex_ptr = NULL; 162 } 163} 164 165bool 166Mutex::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//---------------------------------------------------------------------- 185Mutex::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//---------------------------------------------------------------------- 202Mutex::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//---------------------------------------------------------------------- 239Mutex::~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//---------------------------------------------------------------------- 258pthread_mutex_t * 259Mutex::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//---------------------------------------------------------------------- 272int 273Mutex::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//---------------------------------------------------------------------- 303int 304Mutex::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//---------------------------------------------------------------------- 324int 325Mutex::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 345int 346TrackingMutex::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 357int 358LoggingMutex::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 367int 368LoggingMutex::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 377int 378LoggingMutex::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