130fdc8d8SChris Lattner //===-- PThreadMutex.h ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner //
930fdc8d8SChris Lattner //  Created by Greg Clayton on 6/16/07.
1030fdc8d8SChris Lattner //
1130fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
1230fdc8d8SChris Lattner 
13cdc514e4SJonas Devlieghere #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_PTHREADMUTEX_H
14cdc514e4SJonas Devlieghere #define LLDB_TOOLS_DEBUGSERVER_SOURCE_PTHREADMUTEX_H
1530fdc8d8SChris Lattner 
16*76e47d48SRaphael Isemann #include <cassert>
17*76e47d48SRaphael Isemann #include <cstdint>
18b9c1b51eSKate Stone #include <pthread.h>
1930fdc8d8SChris Lattner 
2030fdc8d8SChris Lattner //#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1
2130fdc8d8SChris Lattner 
2230fdc8d8SChris Lattner #if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
23b9c1b51eSKate Stone #define PTHREAD_MUTEX_LOCKER(var, mutex)                                       \
24b9c1b51eSKate Stone   PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__)
2530fdc8d8SChris Lattner 
2630fdc8d8SChris Lattner #else
2730fdc8d8SChris Lattner #define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex)
2830fdc8d8SChris Lattner #endif
2930fdc8d8SChris Lattner 
30b9c1b51eSKate Stone class PThreadMutex {
3130fdc8d8SChris Lattner public:
32b9c1b51eSKate Stone   class Locker {
3330fdc8d8SChris Lattner   public:
3430fdc8d8SChris Lattner #if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
3530fdc8d8SChris Lattner 
3630fdc8d8SChris Lattner     Locker(PThreadMutex &m, const char *function, const char *file, int line);
3730fdc8d8SChris Lattner     Locker(PThreadMutex *m, const char *function, const char *file, int line);
38b9c1b51eSKate Stone     Locker(pthread_mutex_t *mutex, const char *function, const char *file,
39b9c1b51eSKate Stone            int line);
4030fdc8d8SChris Lattner     ~Locker();
4130fdc8d8SChris Lattner     void Lock();
4230fdc8d8SChris Lattner     void Unlock();
4330fdc8d8SChris Lattner 
4430fdc8d8SChris Lattner #else
45b9c1b51eSKate Stone     Locker(PThreadMutex &m) : m_pMutex(m.Mutex()) { Lock(); }
4630fdc8d8SChris Lattner 
47b9c1b51eSKate Stone     Locker(PThreadMutex *m) : m_pMutex(m ? m->Mutex() : NULL) { Lock(); }
4830fdc8d8SChris Lattner 
49b9c1b51eSKate Stone     Locker(pthread_mutex_t *mutex) : m_pMutex(mutex) { Lock(); }
5030fdc8d8SChris Lattner 
51b9c1b51eSKate Stone     void Lock() {
5230fdc8d8SChris Lattner       if (m_pMutex)
5330fdc8d8SChris Lattner         ::pthread_mutex_lock(m_pMutex);
5430fdc8d8SChris Lattner     }
5530fdc8d8SChris Lattner 
56b9c1b51eSKate Stone     void Unlock() {
5730fdc8d8SChris Lattner       if (m_pMutex)
5830fdc8d8SChris Lattner         ::pthread_mutex_unlock(m_pMutex);
5930fdc8d8SChris Lattner     }
6030fdc8d8SChris Lattner 
61b9c1b51eSKate Stone     ~Locker() { Unlock(); }
6230fdc8d8SChris Lattner 
6330fdc8d8SChris Lattner #endif
6430fdc8d8SChris Lattner 
6530fdc8d8SChris Lattner     // unlock any the current mutex and lock the new one if it is valid
66b9c1b51eSKate Stone     void Reset(pthread_mutex_t *pMutex = NULL) {
6730fdc8d8SChris Lattner       Unlock();
6830fdc8d8SChris Lattner       m_pMutex = pMutex;
6930fdc8d8SChris Lattner       Lock();
7030fdc8d8SChris Lattner     }
7130fdc8d8SChris Lattner     pthread_mutex_t *m_pMutex;
7230fdc8d8SChris Lattner #if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
7330fdc8d8SChris Lattner     const char *m_function;
7430fdc8d8SChris Lattner     const char *m_file;
7530fdc8d8SChris Lattner     int m_line;
7630fdc8d8SChris Lattner     uint64_t m_lock_time;
7730fdc8d8SChris Lattner #endif
7830fdc8d8SChris Lattner   };
7930fdc8d8SChris Lattner 
PThreadMutex()80b9c1b51eSKate Stone   PThreadMutex() {
8130fdc8d8SChris Lattner     int err;
82b9c1b51eSKate Stone     err = ::pthread_mutex_init(&m_mutex, NULL);
83b9c1b51eSKate Stone     assert(err == 0);
8430fdc8d8SChris Lattner   }
8530fdc8d8SChris Lattner 
PThreadMutex(int type)86b9c1b51eSKate Stone   PThreadMutex(int type) {
8730fdc8d8SChris Lattner     int err;
8830fdc8d8SChris Lattner     ::pthread_mutexattr_t attr;
89b9c1b51eSKate Stone     err = ::pthread_mutexattr_init(&attr);
90b9c1b51eSKate Stone     assert(err == 0);
91b9c1b51eSKate Stone     err = ::pthread_mutexattr_settype(&attr, type);
92b9c1b51eSKate Stone     assert(err == 0);
93b9c1b51eSKate Stone     err = ::pthread_mutex_init(&m_mutex, &attr);
94b9c1b51eSKate Stone     assert(err == 0);
95b9c1b51eSKate Stone     err = ::pthread_mutexattr_destroy(&attr);
96b9c1b51eSKate Stone     assert(err == 0);
9730fdc8d8SChris Lattner   }
9830fdc8d8SChris Lattner 
~PThreadMutex()99b9c1b51eSKate Stone   ~PThreadMutex() {
10030fdc8d8SChris Lattner     int err;
10130fdc8d8SChris Lattner     err = ::pthread_mutex_destroy(&m_mutex);
102b9c1b51eSKate Stone     if (err != 0) {
10330fdc8d8SChris Lattner       err = Unlock();
10430fdc8d8SChris Lattner       if (err == 0)
10530fdc8d8SChris Lattner         ::pthread_mutex_destroy(&m_mutex);
10630fdc8d8SChris Lattner     }
10730fdc8d8SChris Lattner   }
10830fdc8d8SChris Lattner 
Mutex()109b9c1b51eSKate Stone   pthread_mutex_t *Mutex() { return &m_mutex; }
11030fdc8d8SChris Lattner 
Lock()111b9c1b51eSKate Stone   int Lock() { return ::pthread_mutex_lock(&m_mutex); }
11230fdc8d8SChris Lattner 
Unlock()113b9c1b51eSKate Stone   int Unlock() { return ::pthread_mutex_unlock(&m_mutex); }
11430fdc8d8SChris Lattner 
11530fdc8d8SChris Lattner protected:
11630fdc8d8SChris Lattner   pthread_mutex_t m_mutex;
11730fdc8d8SChris Lattner };
11830fdc8d8SChris Lattner 
11930fdc8d8SChris Lattner #endif
120