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
38 enum MutexAction
39 {
40 eMutexActionInitialized,
41 eMutexActionDestroyed,
42 eMutexActionAssertInitialized
43 };
44
45 static bool
error_check_mutex(pthread_mutex_t * m,MutexAction action)46 error_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
91 using 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 //----------------------------------------------------------------------
Locker()100 Mutex::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 //----------------------------------------------------------------------
Locker(Mutex & m)111 Mutex::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 //----------------------------------------------------------------------
Locker(Mutex * m)123 Mutex::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 //----------------------------------------------------------------------
~Locker()135 Mutex::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 //----------------------------------------------------------------------
144 void
Lock(Mutex & mutex)145 Mutex::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
157 void
Unlock()158 Mutex::Locker::Unlock ()
159 {
160 if (m_mutex_ptr)
161 {
162 m_mutex_ptr->Unlock ();
163 m_mutex_ptr = NULL;
164 }
165 }
166
167 bool
TryLock(Mutex & mutex,const char * failure_message)168 Mutex::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 //----------------------------------------------------------------------
Mutex()189 Mutex::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 //----------------------------------------------------------------------
Mutex(Mutex::Type type)206 Mutex::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 //----------------------------------------------------------------------
~Mutex()243 Mutex::~Mutex()
244 {
245 #if ENABLE_MUTEX_ERROR_CHECKING
246 int err = ::pthread_mutex_destroy (&m_mutex);
247 assert(err == 0);
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 #else
257 ::pthread_mutex_destroy (&m_mutex);
258 #endif
259 }
260
261 //----------------------------------------------------------------------
262 // Locks the mutex owned by this object, if the mutex is already
263 // locked, the calling thread will block until the mutex becomes
264 // available.
265 //
266 // RETURNS
267 // The error code from the pthread_mutex_lock() function call.
268 //----------------------------------------------------------------------
269 int
Lock()270 Mutex::Lock()
271 {
272 DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_lock (%p)...\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex);
273
274 #if ENABLE_MUTEX_ERROR_CHECKING
275 error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
276 #endif
277
278 int err = ::pthread_mutex_lock (&m_mutex);
279
280
281 #if ENABLE_MUTEX_ERROR_CHECKING
282 if (err)
283 {
284 Host::SetCrashDescriptionWithFormat ("%s error: pthread_mutex_lock(%p) => err = %i (%s)", __PRETTY_FUNCTION__, &m_mutex, err, strerror(err));
285 assert(err == 0);
286 }
287 #endif
288 DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_lock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
289 return err;
290 }
291
292 //----------------------------------------------------------------------
293 // Attempts to lock the mutex owned by this object without blocking.
294 // If the mutex is already locked, TryLock() will not block waiting
295 // for the mutex, but will return an error condition.
296 //
297 // RETURNS
298 // The error code from the pthread_mutex_trylock() function call.
299 //----------------------------------------------------------------------
300 int
TryLock(const char * failure_message)301 Mutex::TryLock(const char *failure_message)
302 {
303 #if ENABLE_MUTEX_ERROR_CHECKING
304 error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
305 #endif
306
307 int err = ::pthread_mutex_trylock (&m_mutex);
308 DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_trylock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
309 return err;
310 }
311
312 //----------------------------------------------------------------------
313 // If the current thread holds the lock on the owned mutex, then
314 // Unlock() will unlock the mutex. Calling Unlock() on this object
315 // that the calling thread does not hold will result in undefined
316 // behavior.
317 //
318 // RETURNS
319 // The error code from the pthread_mutex_unlock() function call.
320 //----------------------------------------------------------------------
321 int
Unlock()322 Mutex::Unlock()
323 {
324 #if ENABLE_MUTEX_ERROR_CHECKING
325 error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
326 #endif
327
328 int err = ::pthread_mutex_unlock (&m_mutex);
329
330 #if ENABLE_MUTEX_ERROR_CHECKING
331 if (err)
332 {
333 Host::SetCrashDescriptionWithFormat ("%s error: pthread_mutex_unlock(%p) => err = %i (%s)", __PRETTY_FUNCTION__, &m_mutex, err, strerror(err));
334 assert(err == 0);
335 }
336 #endif
337 DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_unlock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
338 return err;
339 }
340
341 #endif
342
343 //----------------------------------------------------------------------
344 // Mutex get accessor.
345 //----------------------------------------------------------------------
346 lldb::mutex_t *
GetMutex()347 Mutex::GetMutex()
348 {
349 return &m_mutex;
350 }
351
352 #ifdef LLDB_CONFIGURATION_DEBUG
353 int
Unlock()354 TrackingMutex::Unlock ()
355 {
356 if (!m_failure_message.empty())
357 Host::SetCrashDescriptionWithFormat ("Unlocking lock (on thread %p) that thread: %p failed to get: %s",
358 pthread_self(),
359 m_thread_that_tried,
360 m_failure_message.c_str());
361 assert (m_failure_message.empty());
362 return Mutex::Unlock();
363 }
364
365 int
Lock()366 LoggingMutex::Lock ()
367 {
368 printf("locking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
369 int x = Mutex::Lock();
370 m_locked = true;
371 printf("%d\n",x);
372 return x;
373 }
374
375 int
Unlock()376 LoggingMutex::Unlock ()
377 {
378 printf("unlocking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
379 int x = Mutex::Unlock();
380 m_locked = false;
381 printf("%d\n",x);
382 return x;
383 }
384
385 int
TryLock(const char * failure_message)386 LoggingMutex::TryLock (const char *failure_message)
387 {
388 printf("trylocking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
389 int x = Mutex::TryLock(failure_message);
390 if (x == 0)
391 m_locked = true;
392 printf("%d\n",x);
393 return x;
394 }
395
396 #endif
397
398
399