]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Host / common / Mutex.cpp
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
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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
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
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
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
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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
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 *
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
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
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
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
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
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
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
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