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