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