19 #include <ndb_global.h>
25 static FILE * statout = 0;
28 NdbMutex* NdbMutex_Create()
30 return NdbMutex_CreateWithName(0);
33 NdbMutex* NdbMutex_CreateWithName(
const char *
name)
38 pNdbMutex = (NdbMutex*)NdbMem_Allocate(
sizeof(NdbMutex));
40 if (pNdbMutex == NULL)
43 result = NdbMutex_InitWithName(pNdbMutex, name);
48 NdbMem_Free(pNdbMutex);
52 int NdbMutex_Init(NdbMutex* pNdbMutex)
54 return NdbMutex_InitWithName(pNdbMutex, 0);
57 int NdbMutex_InitWithName(NdbMutex* pNdbMutex,
const char * name)
61 DBUG_ENTER(
"NdbMutex_Init");
64 bzero(pNdbMutex,
sizeof(NdbMutex));
65 pNdbMutex->min_lock_wait_time_ns = ~(Uint64)0;
66 pNdbMutex->min_hold_time_ns = ~(Uint64)0;
67 p = &pNdbMutex->mutex;
70 snprintf(pNdbMutex->name,
sizeof(pNdbMutex->name),
"%p",
75 snprintf(pNdbMutex->name,
sizeof(pNdbMutex->name),
"%p:%s",
78 if (getenv(
"NDB_MUTEX_STAT") != 0)
87 #if defined(VM_TRACE) && \
88 defined(HAVE_PTHREAD_MUTEXATTR_INIT) && \
89 defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE)
92 pthread_mutexattr_t t;
93 pthread_mutexattr_init(&t);
94 pthread_mutexattr_settype(&t, PTHREAD_MUTEX_ERRORCHECK);
95 result = pthread_mutex_init(p, &t);
97 pthread_mutexattr_destroy(&t);
100 result = pthread_mutex_init(p, 0);
105 int NdbMutex_Destroy(NdbMutex* p_mutex)
112 #ifdef NDB_MUTEX_STAT
113 result = pthread_mutex_destroy(&p_mutex->mutex);
115 result = pthread_mutex_destroy(p_mutex);
118 NdbMem_Free(p_mutex);
123 #ifdef NDB_MUTEX_STAT
130 clock_gettime(CLOCK_MONOTONIC, &ts);
131 return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
136 dumpstat(NdbMutex* p)
142 " lock [ cnt: %u con: %u wait: [ min: %llu avg: %llu max: %llu ] ]"
143 " trylock [ ok: %u nok: %u ]"
144 " hold: [ min: %llu avg: %llu max: %llu ]\n",
147 p->cnt_lock_contention,
148 p->min_lock_wait_time_ns,
149 p->cnt_lock_contention ?
150 p->sum_lock_wait_time_ns / p->cnt_lock_contention : 0,
151 p->max_lock_wait_time_ns,
155 (p->cnt_lock + p->cnt_trylock_ok) ?
156 p->sum_hold_time_ns / (p->cnt_lock + p->cnt_trylock_ok) : 0,
157 p->max_hold_time_ns);
160 p->cnt_lock_contention = 0;
161 p->cnt_trylock_ok = 0;
162 p->cnt_trylock_nok = 0;
163 p->min_lock_wait_time_ns = ~(Uint64)0;
164 p->sum_lock_wait_time_ns = 0;
165 p->max_lock_wait_time_ns = 0;
166 p->min_hold_time_ns = ~(Uint64)0;
167 p->sum_hold_time_ns = 0;
168 p->max_hold_time_ns = 0;
173 int NdbMutex_Lock(NdbMutex* p_mutex)
180 #ifdef NDB_MUTEX_STAT
183 if ((result = pthread_mutex_trylock(&p_mutex->mutex)) == 0)
189 Uint64 start = now();
190 assert(result == EBUSY);
191 result = pthread_mutex_lock(&p_mutex->mutex);
193 p_mutex->cnt_lock_contention++;
194 Uint64 t = (stop - start);
195 p_mutex->sum_lock_wait_time_ns += t;
196 if (t < p_mutex->min_lock_wait_time_ns)
197 p_mutex->min_lock_wait_time_ns = t;
198 if (t > p_mutex->max_lock_wait_time_ns)
199 p_mutex->max_lock_wait_time_ns = t;
202 p_mutex->lock_start_time_ns = stop;
205 result = pthread_mutex_lock(p_mutex);
213 int NdbMutex_Unlock(NdbMutex* p_mutex)
220 #ifdef NDB_MUTEX_STAT
222 Uint64 stop = now() - p_mutex->lock_start_time_ns;
223 p_mutex->sum_hold_time_ns += stop;
224 if (stop < p_mutex->min_hold_time_ns)
225 p_mutex->min_hold_time_ns = stop;
226 if (stop > p_mutex->max_hold_time_ns)
227 p_mutex->max_hold_time_ns = stop;
228 result = pthread_mutex_unlock(&p_mutex->mutex);
229 if (((p_mutex->sum_hold_time_ns + p_mutex->sum_lock_wait_time_ns)
230 >= 3*1000000000ULL) ||
231 p_mutex->cnt_lock >= 16384 ||
232 p_mutex->cnt_trylock_ok >= 16384)
238 result = pthread_mutex_unlock(p_mutex);
246 int NdbMutex_Trylock(NdbMutex* p_mutex)
253 #ifdef NDB_MUTEX_STAT
254 result = pthread_mutex_trylock(&p_mutex->mutex);
257 p_mutex->cnt_trylock_ok++;
258 p_mutex->lock_start_time_ns = now();
262 __sync_fetch_and_add(&p_mutex->cnt_trylock_nok, 1);
265 result = pthread_mutex_trylock(p_mutex);
267 assert(result == 0 || result == EBUSY);