xref: /NextBSD/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp (revision 287e3b14e9552995def1802ec9c5034f4adf28ec)
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