1
by brian
clean slate |
1 |
/******************************************************
|
2 |
The interface to the operating system
|
|
3 |
synchronization primitives.
|
|
4 |
||
5 |
(c) 1995 Innobase Oy
|
|
6 |
||
7 |
Created 9/6/1995 Heikki Tuuri
|
|
8 |
*******************************************************/
|
|
9 |
||
10 |
#include "os0sync.h" |
|
11 |
#ifdef UNIV_NONINL
|
|
12 |
#include "os0sync.ic" |
|
13 |
#endif
|
|
14 |
||
15 |
#ifdef __WIN__
|
|
16 |
#include <windows.h> |
|
17 |
#endif
|
|
18 |
||
19 |
#include "ut0mem.h" |
|
20 |
#include "srv0start.h" |
|
21 |
||
22 |
/* Type definition for an operating system mutex struct */
|
|
23 |
struct os_mutex_struct{ |
|
24 |
void* handle; /* OS handle to mutex */ |
|
25 |
ulint count; /* we use this counter to check |
|
26 |
that the same thread does not
|
|
27 |
recursively lock the mutex: we
|
|
28 |
do not assume that the OS mutex
|
|
29 |
supports recursive locking, though
|
|
30 |
NT seems to do that */
|
|
31 |
UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list; |
|
32 |
/* list of all 'slow' OS mutexes created */
|
|
33 |
};
|
|
34 |
||
35 |
/* Mutex protecting counts and the lists of OS mutexes and events */
|
|
36 |
os_mutex_t os_sync_mutex; |
|
37 |
ibool os_sync_mutex_inited = FALSE; |
|
38 |
||
39 |
/* This is incremented by 1 in os_thread_create and decremented by 1 in
|
|
40 |
os_thread_exit */
|
|
41 |
ulint os_thread_count = 0; |
|
42 |
||
43 |
/* The list of all events created */
|
|
44 |
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list; |
|
45 |
||
46 |
/* The list of all OS 'slow' mutexes */
|
|
47 |
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list; |
|
48 |
||
49 |
ulint os_event_count = 0; |
|
50 |
ulint os_mutex_count = 0; |
|
51 |
ulint os_fast_mutex_count = 0; |
|
52 |
||
53 |
||
54 |
/*************************************************************
|
|
55 |
Initializes global event and OS 'slow' mutex lists. */
|
|
56 |
||
57 |
void
|
|
58 |
os_sync_init(void) |
|
59 |
/*==============*/
|
|
60 |
{
|
|
61 |
UT_LIST_INIT(os_event_list); |
|
62 |
UT_LIST_INIT(os_mutex_list); |
|
63 |
||
64 |
os_sync_mutex = os_mutex_create(NULL); |
|
65 |
||
66 |
os_sync_mutex_inited = TRUE; |
|
67 |
}
|
|
68 |
||
69 |
/*************************************************************
|
|
70 |
Frees created events and OS 'slow' mutexes. */
|
|
71 |
||
72 |
void
|
|
73 |
os_sync_free(void) |
|
74 |
/*==============*/
|
|
75 |
{
|
|
76 |
os_event_t event; |
|
77 |
os_mutex_t mutex; |
|
78 |
||
79 |
event = UT_LIST_GET_FIRST(os_event_list); |
|
80 |
||
81 |
while (event) { |
|
82 |
||
83 |
os_event_free(event); |
|
84 |
||
85 |
event = UT_LIST_GET_FIRST(os_event_list); |
|
86 |
}
|
|
87 |
||
88 |
mutex = UT_LIST_GET_FIRST(os_mutex_list); |
|
89 |
||
90 |
while (mutex) { |
|
91 |
if (mutex == os_sync_mutex) { |
|
92 |
/* Set the flag to FALSE so that we do not try to
|
|
93 |
reserve os_sync_mutex any more in remaining freeing
|
|
94 |
operations in shutdown */
|
|
95 |
os_sync_mutex_inited = FALSE; |
|
96 |
}
|
|
97 |
||
98 |
os_mutex_free(mutex); |
|
99 |
||
100 |
mutex = UT_LIST_GET_FIRST(os_mutex_list); |
|
101 |
}
|
|
102 |
}
|
|
103 |
||
104 |
/*************************************************************
|
|
105 |
Creates an event semaphore, i.e., a semaphore which may just have two
|
|
106 |
states: signaled and nonsignaled. The created event is manual reset: it
|
|
107 |
must be reset explicitly by calling sync_os_reset_event. */
|
|
108 |
||
109 |
os_event_t
|
|
110 |
os_event_create( |
|
111 |
/*============*/
|
|
112 |
/* out: the event handle */
|
|
113 |
const char* name) /* in: the name of the event, if NULL |
|
114 |
the event is created without a name */
|
|
115 |
{
|
|
116 |
#ifdef __WIN__
|
|
117 |
os_event_t event; |
|
118 |
||
119 |
event = ut_malloc(sizeof(struct os_event_struct)); |
|
120 |
||
121 |
event->handle = CreateEvent(NULL, /* No security attributes */ |
|
122 |
TRUE, /* Manual reset */ |
|
123 |
FALSE, /* Initial state nonsignaled */ |
|
124 |
(LPCTSTR) name); |
|
125 |
if (!event->handle) { |
|
126 |
fprintf(stderr, |
|
127 |
"InnoDB: Could not create a Windows event semaphore;"
|
|
128 |
" Windows error %lu\n", |
|
129 |
(ulong) GetLastError()); |
|
130 |
}
|
|
131 |
#else /* Unix */ |
|
132 |
os_event_t event; |
|
133 |
||
134 |
UT_NOT_USED(name); |
|
135 |
||
136 |
event = ut_malloc(sizeof(struct os_event_struct)); |
|
137 |
||
138 |
os_fast_mutex_init(&(event->os_mutex)); |
|
139 |
||
140 |
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
|
|
141 |
ut_a(0 == pthread_cond_init(&(event->cond_var), |
|
142 |
pthread_condattr_default)); |
|
143 |
#else
|
|
144 |
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL)); |
|
145 |
#endif
|
|
146 |
event->is_set = FALSE; |
|
147 |
event->signal_count = 0; |
|
148 |
#endif /* __WIN__ */ |
|
149 |
||
150 |
/* Put to the list of events */
|
|
151 |
os_mutex_enter(os_sync_mutex); |
|
152 |
||
153 |
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); |
|
154 |
||
155 |
os_event_count++; |
|
156 |
||
157 |
os_mutex_exit(os_sync_mutex); |
|
158 |
||
159 |
return(event); |
|
160 |
}
|
|
161 |
||
162 |
#ifdef __WIN__
|
|
163 |
/*************************************************************
|
|
164 |
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
|
165 |
reset when a single thread is released. Works only in Windows. */
|
|
166 |
||
167 |
os_event_t
|
|
168 |
os_event_create_auto( |
|
169 |
/*=================*/
|
|
170 |
/* out: the event handle */
|
|
171 |
const char* name) /* in: the name of the event, if NULL |
|
172 |
the event is created without a name */
|
|
173 |
{
|
|
174 |
os_event_t event; |
|
175 |
||
176 |
event = ut_malloc(sizeof(struct os_event_struct)); |
|
177 |
||
178 |
event->handle = CreateEvent(NULL, /* No security attributes */ |
|
179 |
FALSE, /* Auto-reset */ |
|
180 |
FALSE, /* Initial state nonsignaled */ |
|
181 |
(LPCTSTR) name); |
|
182 |
||
183 |
if (!event->handle) { |
|
184 |
fprintf(stderr, |
|
185 |
"InnoDB: Could not create a Windows auto"
|
|
186 |
" event semaphore; Windows error %lu\n", |
|
187 |
(ulong) GetLastError()); |
|
188 |
}
|
|
189 |
||
190 |
/* Put to the list of events */
|
|
191 |
os_mutex_enter(os_sync_mutex); |
|
192 |
||
193 |
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); |
|
194 |
||
195 |
os_event_count++; |
|
196 |
||
197 |
os_mutex_exit(os_sync_mutex); |
|
198 |
||
199 |
return(event); |
|
200 |
}
|
|
201 |
#endif
|
|
202 |
||
203 |
/**************************************************************
|
|
204 |
Sets an event semaphore to the signaled state: lets waiting threads
|
|
205 |
proceed. */
|
|
206 |
||
207 |
void
|
|
208 |
os_event_set( |
|
209 |
/*=========*/
|
|
210 |
os_event_t event) /* in: event to set */ |
|
211 |
{
|
|
212 |
#ifdef __WIN__
|
|
213 |
ut_a(event); |
|
214 |
ut_a(SetEvent(event->handle)); |
|
215 |
#else
|
|
216 |
ut_a(event); |
|
217 |
||
218 |
os_fast_mutex_lock(&(event->os_mutex)); |
|
219 |
||
220 |
if (event->is_set) { |
|
221 |
/* Do nothing */
|
|
222 |
} else { |
|
223 |
event->is_set = TRUE; |
|
224 |
event->signal_count += 1; |
|
225 |
ut_a(0 == pthread_cond_broadcast(&(event->cond_var))); |
|
226 |
}
|
|
227 |
||
228 |
os_fast_mutex_unlock(&(event->os_mutex)); |
|
229 |
#endif
|
|
230 |
}
|
|
231 |
||
232 |
/**************************************************************
|
|
233 |
Resets an event semaphore to the nonsignaled state. Waiting threads will
|
|
234 |
stop to wait for the event. */
|
|
235 |
||
236 |
void
|
|
237 |
os_event_reset( |
|
238 |
/*===========*/
|
|
239 |
os_event_t event) /* in: event to reset */ |
|
240 |
{
|
|
241 |
#ifdef __WIN__
|
|
242 |
ut_a(event); |
|
243 |
||
244 |
ut_a(ResetEvent(event->handle)); |
|
245 |
#else
|
|
246 |
ut_a(event); |
|
247 |
||
248 |
os_fast_mutex_lock(&(event->os_mutex)); |
|
249 |
||
250 |
if (!event->is_set) { |
|
251 |
/* Do nothing */
|
|
252 |
} else { |
|
253 |
event->is_set = FALSE; |
|
254 |
}
|
|
255 |
||
256 |
os_fast_mutex_unlock(&(event->os_mutex)); |
|
257 |
#endif
|
|
258 |
}
|
|
259 |
||
260 |
/**************************************************************
|
|
261 |
Frees an event object. */
|
|
262 |
||
263 |
void
|
|
264 |
os_event_free( |
|
265 |
/*==========*/
|
|
266 |
os_event_t event) /* in: event to free */ |
|
267 |
||
268 |
{
|
|
269 |
#ifdef __WIN__
|
|
270 |
ut_a(event); |
|
271 |
||
272 |
ut_a(CloseHandle(event->handle)); |
|
273 |
#else
|
|
274 |
ut_a(event); |
|
275 |
||
276 |
os_fast_mutex_free(&(event->os_mutex)); |
|
277 |
ut_a(0 == pthread_cond_destroy(&(event->cond_var))); |
|
278 |
#endif
|
|
279 |
/* Remove from the list of events */
|
|
280 |
||
281 |
os_mutex_enter(os_sync_mutex); |
|
282 |
||
283 |
UT_LIST_REMOVE(os_event_list, os_event_list, event); |
|
284 |
||
285 |
os_event_count--; |
|
286 |
||
287 |
os_mutex_exit(os_sync_mutex); |
|
288 |
||
289 |
ut_free(event); |
|
290 |
}
|
|
291 |
||
292 |
/**************************************************************
|
|
293 |
Waits for an event object until it is in the signaled state. If
|
|
294 |
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
|
|
295 |
waiting thread when the event becomes signaled (or immediately if the
|
|
296 |
event is already in the signaled state). */
|
|
297 |
||
298 |
void
|
|
299 |
os_event_wait( |
|
300 |
/*==========*/
|
|
301 |
os_event_t event) /* in: event to wait */ |
|
302 |
{
|
|
303 |
#ifdef __WIN__
|
|
304 |
DWORD err; |
|
305 |
||
306 |
ut_a(event); |
|
307 |
||
308 |
/* Specify an infinite time limit for waiting */
|
|
309 |
err = WaitForSingleObject(event->handle, INFINITE); |
|
310 |
||
311 |
ut_a(err == WAIT_OBJECT_0); |
|
312 |
||
313 |
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { |
|
314 |
os_thread_exit(NULL); |
|
315 |
}
|
|
316 |
#else
|
|
317 |
ib_longlong old_signal_count; |
|
318 |
||
319 |
os_fast_mutex_lock(&(event->os_mutex)); |
|
320 |
||
321 |
old_signal_count = event->signal_count; |
|
322 |
||
323 |
for (;;) { |
|
324 |
if (event->is_set == TRUE |
|
325 |
|| event->signal_count != old_signal_count) { |
|
326 |
||
327 |
os_fast_mutex_unlock(&(event->os_mutex)); |
|
328 |
||
329 |
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { |
|
330 |
||
331 |
os_thread_exit(NULL); |
|
332 |
}
|
|
333 |
/* Ok, we may return */
|
|
334 |
||
335 |
return; |
|
336 |
}
|
|
337 |
||
338 |
pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); |
|
339 |
||
340 |
/* Solaris manual said that spurious wakeups may occur: we
|
|
341 |
have to check if the event really has been signaled after
|
|
342 |
we came here to wait */
|
|
343 |
}
|
|
344 |
#endif
|
|
345 |
}
|
|
346 |
||
347 |
/**************************************************************
|
|
348 |
Waits for an event object until it is in the signaled state or
|
|
349 |
a timeout is exceeded. In Unix the timeout is always infinite. */
|
|
350 |
||
351 |
ulint
|
|
352 |
os_event_wait_time( |
|
353 |
/*===============*/
|
|
354 |
/* out: 0 if success, OS_SYNC_TIME_EXCEEDED if
|
|
355 |
timeout was exceeded */
|
|
356 |
os_event_t event, /* in: event to wait */ |
|
357 |
ulint time) /* in: timeout in microseconds, or |
|
358 |
OS_SYNC_INFINITE_TIME */
|
|
359 |
{
|
|
360 |
#ifdef __WIN__
|
|
361 |
DWORD err; |
|
362 |
||
363 |
ut_a(event); |
|
364 |
||
365 |
if (time != OS_SYNC_INFINITE_TIME) { |
|
366 |
err = WaitForSingleObject(event->handle, (DWORD) time / 1000); |
|
367 |
} else { |
|
368 |
err = WaitForSingleObject(event->handle, INFINITE); |
|
369 |
}
|
|
370 |
||
371 |
if (err == WAIT_OBJECT_0) { |
|
372 |
||
373 |
return(0); |
|
374 |
} else if (err == WAIT_TIMEOUT) { |
|
375 |
||
376 |
return(OS_SYNC_TIME_EXCEEDED); |
|
377 |
} else { |
|
378 |
ut_error; |
|
379 |
return(1000000); /* dummy value to eliminate compiler warn. */ |
|
380 |
}
|
|
381 |
#else
|
|
382 |
UT_NOT_USED(time); |
|
383 |
||
384 |
/* In Posix this is just an ordinary, infinite wait */
|
|
385 |
||
386 |
os_event_wait(event); |
|
387 |
||
388 |
return(0); |
|
389 |
#endif
|
|
390 |
}
|
|
391 |
||
392 |
#ifdef __WIN__
|
|
393 |
/**************************************************************
|
|
394 |
Waits for any event in an OS native event array. Returns if even a single
|
|
395 |
one is signaled or becomes signaled. */
|
|
396 |
||
397 |
ulint
|
|
398 |
os_event_wait_multiple( |
|
399 |
/*===================*/
|
|
400 |
/* out: index of the event
|
|
401 |
which was signaled */
|
|
402 |
ulint n, /* in: number of events in the |
|
403 |
array */
|
|
404 |
os_native_event_t* native_event_array) |
|
405 |
/* in: pointer to an array of event
|
|
406 |
handles */
|
|
407 |
{
|
|
408 |
DWORD index; |
|
409 |
||
410 |
ut_a(native_event_array); |
|
411 |
ut_a(n > 0); |
|
412 |
||
413 |
index = WaitForMultipleObjects((DWORD) n, native_event_array, |
|
414 |
FALSE, /* Wait for any 1 event */ |
|
415 |
INFINITE); /* Infinite wait time |
|
416 |
limit */
|
|
417 |
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */ |
|
418 |
ut_a(index < WAIT_OBJECT_0 + n); |
|
419 |
||
420 |
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { |
|
421 |
os_thread_exit(NULL); |
|
422 |
}
|
|
423 |
||
424 |
return(index - WAIT_OBJECT_0); |
|
425 |
}
|
|
426 |
#endif
|
|
427 |
||
428 |
/*************************************************************
|
|
429 |
Creates an operating system mutex semaphore. Because these are slow, the
|
|
430 |
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
|
431 |
||
432 |
os_mutex_t
|
|
433 |
os_mutex_create( |
|
434 |
/*============*/
|
|
435 |
/* out: the mutex handle */
|
|
436 |
const char* name) /* in: the name of the mutex, if NULL |
|
437 |
the mutex is created without a name */
|
|
438 |
{
|
|
439 |
#ifdef __WIN__
|
|
440 |
HANDLE mutex; |
|
441 |
os_mutex_t mutex_str; |
|
442 |
||
443 |
mutex = CreateMutex(NULL, /* No security attributes */ |
|
444 |
FALSE, /* Initial state: no owner */ |
|
445 |
(LPCTSTR) name); |
|
446 |
ut_a(mutex); |
|
447 |
#else
|
|
448 |
os_fast_mutex_t* mutex; |
|
449 |
os_mutex_t mutex_str; |
|
450 |
||
451 |
UT_NOT_USED(name); |
|
452 |
||
453 |
mutex = ut_malloc(sizeof(os_fast_mutex_t)); |
|
454 |
||
455 |
os_fast_mutex_init(mutex); |
|
456 |
#endif
|
|
457 |
mutex_str = ut_malloc(sizeof(os_mutex_str_t)); |
|
458 |
||
459 |
mutex_str->handle = mutex; |
|
460 |
mutex_str->count = 0; |
|
461 |
||
462 |
if (os_sync_mutex_inited) { |
|
463 |
/* When creating os_sync_mutex itself we cannot reserve it */
|
|
464 |
os_mutex_enter(os_sync_mutex); |
|
465 |
}
|
|
466 |
||
467 |
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); |
|
468 |
||
469 |
os_mutex_count++; |
|
470 |
||
471 |
if (os_sync_mutex_inited) { |
|
472 |
os_mutex_exit(os_sync_mutex); |
|
473 |
}
|
|
474 |
||
475 |
return(mutex_str); |
|
476 |
}
|
|
477 |
||
478 |
/**************************************************************
|
|
479 |
Acquires ownership of a mutex semaphore. */
|
|
480 |
||
481 |
void
|
|
482 |
os_mutex_enter( |
|
483 |
/*===========*/
|
|
484 |
os_mutex_t mutex) /* in: mutex to acquire */ |
|
485 |
{
|
|
486 |
#ifdef __WIN__
|
|
487 |
DWORD err; |
|
488 |
||
489 |
ut_a(mutex); |
|
490 |
||
491 |
/* Specify infinite time limit for waiting */
|
|
492 |
err = WaitForSingleObject(mutex->handle, INFINITE); |
|
493 |
||
494 |
ut_a(err == WAIT_OBJECT_0); |
|
495 |
||
496 |
(mutex->count)++; |
|
497 |
ut_a(mutex->count == 1); |
|
498 |
#else
|
|
499 |
os_fast_mutex_lock(mutex->handle); |
|
500 |
||
501 |
(mutex->count)++; |
|
502 |
||
503 |
ut_a(mutex->count == 1); |
|
504 |
#endif
|
|
505 |
}
|
|
506 |
||
507 |
/**************************************************************
|
|
508 |
Releases ownership of a mutex. */
|
|
509 |
||
510 |
void
|
|
511 |
os_mutex_exit( |
|
512 |
/*==========*/
|
|
513 |
os_mutex_t mutex) /* in: mutex to release */ |
|
514 |
{
|
|
515 |
ut_a(mutex); |
|
516 |
||
517 |
ut_a(mutex->count == 1); |
|
518 |
||
519 |
(mutex->count)--; |
|
520 |
#ifdef __WIN__
|
|
521 |
ut_a(ReleaseMutex(mutex->handle)); |
|
522 |
#else
|
|
523 |
os_fast_mutex_unlock(mutex->handle); |
|
524 |
#endif
|
|
525 |
}
|
|
526 |
||
527 |
/**************************************************************
|
|
528 |
Frees a mutex object. */
|
|
529 |
||
530 |
void
|
|
531 |
os_mutex_free( |
|
532 |
/*==========*/
|
|
533 |
os_mutex_t mutex) /* in: mutex to free */ |
|
534 |
{
|
|
535 |
ut_a(mutex); |
|
536 |
||
537 |
if (os_sync_mutex_inited) { |
|
538 |
os_mutex_enter(os_sync_mutex); |
|
539 |
}
|
|
540 |
||
541 |
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); |
|
542 |
||
543 |
os_mutex_count--; |
|
544 |
||
545 |
if (os_sync_mutex_inited) { |
|
546 |
os_mutex_exit(os_sync_mutex); |
|
547 |
}
|
|
548 |
||
549 |
#ifdef __WIN__
|
|
550 |
ut_a(CloseHandle(mutex->handle)); |
|
551 |
||
552 |
ut_free(mutex); |
|
553 |
#else
|
|
554 |
os_fast_mutex_free(mutex->handle); |
|
555 |
ut_free(mutex->handle); |
|
556 |
ut_free(mutex); |
|
557 |
#endif
|
|
558 |
}
|
|
559 |
||
560 |
/*************************************************************
|
|
561 |
Initializes an operating system fast mutex semaphore. */
|
|
562 |
||
563 |
void
|
|
564 |
os_fast_mutex_init( |
|
565 |
/*===============*/
|
|
566 |
os_fast_mutex_t* fast_mutex) /* in: fast mutex */ |
|
567 |
{
|
|
568 |
#ifdef __WIN__
|
|
569 |
ut_a(fast_mutex); |
|
570 |
||
571 |
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); |
|
572 |
#else
|
|
573 |
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
|
|
574 |
ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default)); |
|
575 |
#else
|
|
576 |
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); |
|
577 |
#endif
|
|
578 |
#endif
|
|
579 |
if (os_sync_mutex_inited) { |
|
580 |
/* When creating os_sync_mutex itself (in Unix) we cannot
|
|
581 |
reserve it */
|
|
582 |
||
583 |
os_mutex_enter(os_sync_mutex); |
|
584 |
}
|
|
585 |
||
586 |
os_fast_mutex_count++; |
|
587 |
||
588 |
if (os_sync_mutex_inited) { |
|
589 |
os_mutex_exit(os_sync_mutex); |
|
590 |
}
|
|
591 |
}
|
|
592 |
||
593 |
/**************************************************************
|
|
594 |
Acquires ownership of a fast mutex. */
|
|
595 |
||
596 |
void
|
|
597 |
os_fast_mutex_lock( |
|
598 |
/*===============*/
|
|
599 |
os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */ |
|
600 |
{
|
|
601 |
#ifdef __WIN__
|
|
602 |
EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex); |
|
603 |
#else
|
|
604 |
pthread_mutex_lock(fast_mutex); |
|
605 |
#endif
|
|
606 |
}
|
|
607 |
||
608 |
/**************************************************************
|
|
609 |
Releases ownership of a fast mutex. */
|
|
610 |
||
611 |
void
|
|
612 |
os_fast_mutex_unlock( |
|
613 |
/*=================*/
|
|
614 |
os_fast_mutex_t* fast_mutex) /* in: mutex to release */ |
|
615 |
{
|
|
616 |
#ifdef __WIN__
|
|
617 |
LeaveCriticalSection(fast_mutex); |
|
618 |
#else
|
|
619 |
pthread_mutex_unlock(fast_mutex); |
|
620 |
#endif
|
|
621 |
}
|
|
622 |
||
623 |
/**************************************************************
|
|
624 |
Frees a mutex object. */
|
|
625 |
||
626 |
void
|
|
627 |
os_fast_mutex_free( |
|
628 |
/*===============*/
|
|
629 |
os_fast_mutex_t* fast_mutex) /* in: mutex to free */ |
|
630 |
{
|
|
631 |
#ifdef __WIN__
|
|
632 |
ut_a(fast_mutex); |
|
633 |
||
634 |
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); |
|
635 |
#else
|
|
636 |
int ret; |
|
637 |
||
638 |
ret = pthread_mutex_destroy(fast_mutex); |
|
639 |
||
640 |
if (ret != 0) { |
|
641 |
ut_print_timestamp(stderr); |
|
642 |
fprintf(stderr, |
|
643 |
" InnoDB: error: return value %lu when calling\n" |
|
644 |
"InnoDB: pthread_mutex_destroy().\n", (ulint)ret); |
|
645 |
fprintf(stderr, |
|
646 |
"InnoDB: Byte contents of the pthread mutex at %p:\n", |
|
647 |
(void*) fast_mutex); |
|
648 |
ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t)); |
|
649 |
fprintf(stderr, "\n"); |
|
650 |
}
|
|
651 |
#endif
|
|
652 |
if (os_sync_mutex_inited) { |
|
653 |
/* When freeing the last mutexes, we have
|
|
654 |
already freed os_sync_mutex */
|
|
655 |
||
656 |
os_mutex_enter(os_sync_mutex); |
|
657 |
}
|
|
658 |
||
659 |
os_fast_mutex_count--; |
|
660 |
||
661 |
if (os_sync_mutex_inited) { |
|
662 |
os_mutex_exit(os_sync_mutex); |
|
663 |
}
|
|
664 |
}
|