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
error_check_mutex(pthread_mutex_t * m,MutexAction action)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 //----------------------------------------------------------------------
Locker()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 //----------------------------------------------------------------------
Locker(Mutex & m)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 //----------------------------------------------------------------------
Locker(Mutex * m)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 //----------------------------------------------------------------------
~Locker()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
Lock(Mutex & mutex)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
Unlock()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
TryLock(Mutex & mutex,const char * failure_message)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 //----------------------------------------------------------------------
Mutex()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 //----------------------------------------------------------------------
Mutex(Mutex::Type type)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 //----------------------------------------------------------------------
~Mutex()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 *
GetMutex()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
Lock()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
TryLock(const char * failure_message)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
Unlock()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
Unlock()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
Lock()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
Unlock()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
TryLock(const char * failure_message)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