1 /*
2    Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef NDB_MUTEX_H
26 #define NDB_MUTEX_H
27 
28 #include <ndb_global.h>
29 #include <thr_mutex.h>
30 
31 #ifdef	__cplusplus
32 extern "C" {
33 #endif
34 
35 #if !defined NDB_MUTEX_STAT && !defined NDB_MUTEX_DEADLOCK_DETECTOR
36 typedef native_mutex_t NdbMutex;
37 #else
38 typedef struct {
39   native_mutex_t mutex;
40 #ifdef NDB_MUTEX_STAT
41   unsigned cnt_lock;
42   unsigned cnt_lock_contention;
43   unsigned cnt_trylock_ok;
44   unsigned cnt_trylock_nok;
45   unsigned long long min_lock_wait_time_ns;
46   unsigned long long sum_lock_wait_time_ns;
47   unsigned long long max_lock_wait_time_ns;
48   unsigned long long min_hold_time_ns;
49   unsigned long long sum_hold_time_ns;
50   unsigned long long max_hold_time_ns;
51   unsigned long long lock_start_time_ns;
52   char name[32];
53 #endif
54 #ifdef NDB_MUTEX_DEADLOCK_DETECTOR
55   struct ndb_mutex_state * m_mutex_state;
56 #endif
57 } NdbMutex;
58 #endif
59 
60 /**
61  * Create a mutex
62  *  - the allocated mutex should be released by calling
63  *    NdbMutex_Destroy
64  *
65  * returnvalue: pointer to the mutex structure
66  */
67 NdbMutex* NdbMutex_Create(void);
68 NdbMutex* NdbMutex_CreateWithName(const char * name);
69 
70 /**
71  * Initialize a mutex created with file-storage or on the stack
72  *
73  * * p_mutex: pointer to the mutex structure
74  * * returnvalue: 0 = succeeded, -1 = failed
75  */
76 int NdbMutex_Init(NdbMutex* p_mutex);
77 int NdbMutex_InitWithName(NdbMutex* p_mutex, const char * name);
78 
79 /**
80  * Destroy a mutex
81  *
82  * * p_mutex: pointer to the mutex structure
83  * * returnvalue: 0 = succeeded, -1 = failed
84  */
85 int NdbMutex_Destroy(NdbMutex* p_mutex);
86 int NdbMutex_Deinit(NdbMutex* p_mutex);
87 
88 /**
89  * Lock a mutex
90  *
91  * * p_mutex: pointer to the mutex structure
92  * * returnvalue: 0 = succeeded, -1 = failed
93  */
94 int NdbMutex_Lock(NdbMutex* p_mutex);
95 
96 /**
97  * Unlock a mutex
98  *
99  * * p_mutex: pointer to the mutex structure
100  * * returnvalue: 0 = succeeded, -1 = failed
101  */
102 int NdbMutex_Unlock(NdbMutex* p_mutex);
103 
104 /**
105  * Try to lock a mutex
106  *
107  * * p_mutex: pointer to the mutex structure
108  * * returnvalue: 0 = succeeded, -1 = failed
109  */
110 int NdbMutex_Trylock(NdbMutex* p_mutex);
111 
112 #ifdef	__cplusplus
113 }
114 #endif
115 
116 #ifdef __cplusplus
117 class NdbLockable {
118   friend class Guard;
119   friend class Guard2;
120 public:
NdbLockable()121   NdbLockable() { m_mutex = NdbMutex_Create(); }
~NdbLockable()122   ~NdbLockable() { NdbMutex_Destroy(m_mutex); }
123 
lock()124   void lock() { NdbMutex_Lock(m_mutex); }
unlock()125   void unlock(){ NdbMutex_Unlock(m_mutex);}
tryLock()126   bool tryLock(){ return NdbMutex_Trylock(m_mutex) == 0;}
127 
getMutex()128   NdbMutex* getMutex() {return m_mutex;};
129 
130 protected:
131   NdbMutex * m_mutex;
132 };
133 
134 class Guard {
135 public:
Guard(NdbMutex * mtx)136   Guard(NdbMutex *mtx) : m_mtx(mtx) { NdbMutex_Lock(m_mtx); };
Guard(NdbLockable & l)137   Guard(NdbLockable & l) : m_mtx(l.m_mutex) { NdbMutex_Lock(m_mtx); };
~Guard()138   ~Guard() { NdbMutex_Unlock(m_mtx); };
139 private:
140   NdbMutex *m_mtx;
141 };
142 
143 class Guard2
144 {
145 public:
Guard2(NdbMutex * mtx)146   Guard2(NdbMutex *mtx) : m_mtx(mtx) { if (m_mtx) NdbMutex_Lock(m_mtx);};
Guard2(NdbLockable & l)147   Guard2(NdbLockable & l) : m_mtx(l.m_mutex) { if(m_mtx)NdbMutex_Lock(m_mtx);};
~Guard2()148   ~Guard2() { if (m_mtx) NdbMutex_Unlock(m_mtx); };
149 private:
150   NdbMutex *m_mtx;
151 };
152 
153 #endif
154 
155 #endif
156