1
/*****************************************************************************
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
21
The interface to the operating system
22
synchronization primitives.
24
Created 9/6/1995 Heikki Tuuri
25
*******************************************************/
37
#include "srv0start.h"
38
#include "ha_prototypes.h"
40
/* Type definition for an operating system mutex struct */
41
struct os_mutex_struct{
42
os_event_t event; /*!< Used by sync0arr.c for queing threads */
43
void* handle; /*!< OS handle to mutex */
44
ulint count; /*!< we use this counter to check
45
that the same thread does not
46
recursively lock the mutex: we
47
do not assume that the OS mutex
48
supports recursive locking, though
49
NT seems to do that */
50
UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
51
/* list of all 'slow' OS mutexes created */
54
/** Mutex protecting counts and the lists of OS mutexes and events */
55
UNIV_INTERN os_mutex_t os_sync_mutex;
56
/** TRUE if os_sync_mutex has been initialized */
57
static ibool os_sync_mutex_inited = FALSE;
58
/** TRUE when os_sync_free() is being executed */
59
static ibool os_sync_free_called = FALSE;
61
/** This is incremented by 1 in os_thread_create and decremented by 1 in
63
UNIV_INTERN ulint os_thread_count = 0;
65
/** The list of all events created */
66
static UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
68
/** The list of all OS 'slow' mutexes */
69
static UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
71
UNIV_INTERN ulint os_event_count = 0;
72
UNIV_INTERN ulint os_mutex_count = 0;
73
UNIV_INTERN ulint os_fast_mutex_count = 0;
75
/* Because a mutex is embedded inside an event and there is an
76
event embedded inside a mutex, on free, this generates a recursive call.
77
This version of the free event function doesn't acquire the global lock */
78
static void os_event_free_internal(os_event_t event);
80
/*********************************************************//**
81
Initializes global event and OS 'slow' mutex lists. */
87
UT_LIST_INIT(os_event_list);
88
UT_LIST_INIT(os_mutex_list);
90
os_sync_mutex = os_mutex_create(NULL);
92
os_sync_mutex_inited = TRUE;
95
/*********************************************************//**
96
Frees created events and OS 'slow' mutexes. */
105
os_sync_free_called = TRUE;
106
event = UT_LIST_GET_FIRST(os_event_list);
110
os_event_free(event);
112
event = UT_LIST_GET_FIRST(os_event_list);
115
mutex = UT_LIST_GET_FIRST(os_mutex_list);
118
if (mutex == os_sync_mutex) {
119
/* Set the flag to FALSE so that we do not try to
120
reserve os_sync_mutex any more in remaining freeing
121
operations in shutdown */
122
os_sync_mutex_inited = FALSE;
125
os_mutex_free(mutex);
127
mutex = UT_LIST_GET_FIRST(os_mutex_list);
129
os_sync_free_called = FALSE;
132
/*********************************************************//**
133
Creates an event semaphore, i.e., a semaphore which may just have two
134
states: signaled and nonsignaled. The created event is manual reset: it
135
must be reset explicitly by calling sync_os_reset_event.
136
@return the event handle */
141
const char* name) /*!< in: the name of the event, if NULL
142
the event is created without a name */
147
event = ut_malloc(sizeof(struct os_event_struct));
149
event->handle = CreateEvent(NULL, /* No security attributes */
150
TRUE, /* Manual reset */
151
FALSE, /* Initial state nonsignaled */
153
if (!event->handle) {
155
"InnoDB: Could not create a Windows event semaphore;"
156
" Windows error %lu\n",
157
(ulong) GetLastError());
164
event = ut_malloc(sizeof(struct os_event_struct));
166
os_fast_mutex_init(&(event->os_mutex));
168
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
170
event->is_set = FALSE;
172
/* We return this value in os_event_reset(), which can then be
173
be used to pass to the os_event_wait_low(). The value of zero
174
is reserved in os_event_wait_low() for the case when the
175
caller does not want to pass any signal_count value. To
176
distinguish between the two cases we initialize signal_count
178
event->signal_count = 1;
181
/* The os_sync_mutex can be NULL because during startup an event
182
can be created [ because it's embedded in the mutex/rwlock ] before
183
this module has been initialized */
184
if (os_sync_mutex != NULL) {
185
os_mutex_enter(os_sync_mutex);
188
/* Put to the list of events */
189
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
193
if (os_sync_mutex != NULL) {
194
os_mutex_exit(os_sync_mutex);
200
/**********************************************************//**
201
Sets an event semaphore to the signaled state: lets waiting threads
207
os_event_t event) /*!< in: event to set */
211
ut_a(SetEvent(event->handle));
215
os_fast_mutex_lock(&(event->os_mutex));
220
event->is_set = TRUE;
221
event->signal_count += 1;
222
ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
225
os_fast_mutex_unlock(&(event->os_mutex));
229
/**********************************************************//**
230
Resets an event semaphore to the nonsignaled state. Waiting threads will
231
stop to wait for the event.
232
The return value should be passed to os_even_wait_low() if it is desired
233
that this thread should not wait in case of an intervening call to
234
os_event_set() between this os_event_reset() and the
235
os_event_wait_low() call. See comments for os_event_wait_low().
236
@return current signal_count. */
241
os_event_t event) /*!< in: event to reset */
248
ut_a(ResetEvent(event->handle));
252
os_fast_mutex_lock(&(event->os_mutex));
254
if (!event->is_set) {
257
event->is_set = FALSE;
259
ret = event->signal_count;
261
os_fast_mutex_unlock(&(event->os_mutex));
266
/**********************************************************//**
267
Frees an event object, without acquiring the global lock. */
270
os_event_free_internal(
271
/*===================*/
272
os_event_t event) /*!< in: event to free */
277
ut_a(CloseHandle(event->handle));
281
/* This is to avoid freeing the mutex twice */
282
os_fast_mutex_free(&(event->os_mutex));
284
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
286
/* Remove from the list of events */
288
UT_LIST_REMOVE(os_event_list, os_event_list, event);
295
/**********************************************************//**
296
Frees an event object. */
301
os_event_t event) /*!< in: event to free */
307
ut_a(CloseHandle(event->handle));
311
os_fast_mutex_free(&(event->os_mutex));
312
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
314
/* Remove from the list of events */
316
os_mutex_enter(os_sync_mutex);
318
UT_LIST_REMOVE(os_event_list, os_event_list, event);
322
os_mutex_exit(os_sync_mutex);
327
/**********************************************************//**
328
Waits for an event object until it is in the signaled state. If
329
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
330
waiting thread when the event becomes signaled (or immediately if the
331
event is already in the signaled state).
333
Typically, if the event has been signalled after the os_event_reset()
334
we'll return immediately because event->is_set == TRUE.
335
There are, however, situations (e.g.: sync_array code) where we may
336
lose this information. For example:
338
thread A calls os_event_reset()
339
thread B calls os_event_set() [event->is_set == TRUE]
340
thread C calls os_event_reset() [event->is_set == FALSE]
341
thread A calls os_event_wait() [infinite wait!]
342
thread C calls os_event_wait() [infinite wait!]
344
Where such a scenario is possible, to avoid infinite wait, the
345
value returned by os_event_reset() should be passed in as
351
os_event_t event, /*!< in: event to wait */
352
ib_int64_t reset_sig_count)/*!< in: zero or the value
353
returned by previous call of
361
UT_NOT_USED(reset_sig_count);
363
/* Specify an infinite time limit for waiting */
364
err = WaitForSingleObject(event->handle, INFINITE);
366
ut_a(err == WAIT_OBJECT_0);
368
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
369
os_thread_exit(NULL);
372
ib_int64_t old_signal_count;
374
os_fast_mutex_lock(&(event->os_mutex));
376
if (reset_sig_count) {
377
old_signal_count = reset_sig_count;
379
old_signal_count = event->signal_count;
383
if (event->is_set == TRUE
384
|| event->signal_count != old_signal_count) {
386
os_fast_mutex_unlock(&(event->os_mutex));
388
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
390
os_thread_exit(NULL);
392
/* Ok, we may return */
397
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
399
/* Solaris manual said that spurious wakeups may occur: we
400
have to check if the event really has been signaled after
401
we came here to wait */
406
/**********************************************************//**
407
Waits for an event object until it is in the signaled state or
408
a timeout is exceeded. In Unix the timeout is always infinite.
409
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
414
os_event_t event, /*!< in: event to wait */
415
ulint time) /*!< in: timeout in microseconds, or
416
OS_SYNC_INFINITE_TIME */
423
if (time != OS_SYNC_INFINITE_TIME) {
424
err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
426
err = WaitForSingleObject(event->handle, INFINITE);
429
if (err == WAIT_OBJECT_0) {
432
} else if (err == WAIT_TIMEOUT) {
434
return(OS_SYNC_TIME_EXCEEDED);
437
return(1000000); /* dummy value to eliminate compiler warn. */
442
/* In Posix this is just an ordinary, infinite wait */
444
os_event_wait(event);
451
/**********************************************************//**
452
Waits for any event in an OS native event array. Returns if even a single
453
one is signaled or becomes signaled.
454
@return index of the event which was signaled */
457
os_event_wait_multiple(
458
/*===================*/
459
ulint n, /*!< in: number of events in the
461
os_native_event_t* native_event_array)
462
/*!< in: pointer to an array of event
467
ut_a(native_event_array);
470
index = WaitForMultipleObjects((DWORD) n, native_event_array,
471
FALSE, /* Wait for any 1 event */
472
INFINITE); /* Infinite wait time
474
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparison */
475
ut_a(index < WAIT_OBJECT_0 + n);
477
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
478
os_thread_exit(NULL);
481
return(index - WAIT_OBJECT_0);
485
/*********************************************************//**
486
Creates an operating system mutex semaphore. Because these are slow, the
487
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
488
@return the mutex handle */
493
const char* name) /*!< in: the name of the mutex, if NULL
494
the mutex is created without a name */
498
os_mutex_t mutex_str;
500
mutex = CreateMutex(NULL, /* No security attributes */
501
FALSE, /* Initial state: no owner */
505
os_fast_mutex_t* mutex;
506
os_mutex_t mutex_str;
510
mutex = ut_malloc(sizeof(os_fast_mutex_t));
512
os_fast_mutex_init(mutex);
514
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
516
mutex_str->handle = mutex;
517
mutex_str->count = 0;
518
mutex_str->event = os_event_create(NULL);
520
if (UNIV_LIKELY(os_sync_mutex_inited)) {
521
/* When creating os_sync_mutex itself we cannot reserve it */
522
os_mutex_enter(os_sync_mutex);
525
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
529
if (UNIV_LIKELY(os_sync_mutex_inited)) {
530
os_mutex_exit(os_sync_mutex);
536
/**********************************************************//**
537
Acquires ownership of a mutex semaphore. */
542
os_mutex_t mutex) /*!< in: mutex to acquire */
549
/* Specify infinite time limit for waiting */
550
err = WaitForSingleObject(mutex->handle, INFINITE);
552
ut_a(err == WAIT_OBJECT_0);
555
ut_a(mutex->count == 1);
557
os_fast_mutex_lock(mutex->handle);
561
ut_a(mutex->count == 1);
565
/**********************************************************//**
566
Releases ownership of a mutex. */
571
os_mutex_t mutex) /*!< in: mutex to release */
575
ut_a(mutex->count == 1);
579
ut_a(ReleaseMutex(mutex->handle));
581
os_fast_mutex_unlock(mutex->handle);
585
/**********************************************************//**
586
Frees a mutex object. */
591
os_mutex_t mutex) /*!< in: mutex to free */
595
if (UNIV_LIKELY(!os_sync_free_called)) {
596
os_event_free_internal(mutex->event);
599
if (UNIV_LIKELY(os_sync_mutex_inited)) {
600
os_mutex_enter(os_sync_mutex);
603
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
607
if (UNIV_LIKELY(os_sync_mutex_inited)) {
608
os_mutex_exit(os_sync_mutex);
612
ut_a(CloseHandle(mutex->handle));
616
os_fast_mutex_free(mutex->handle);
617
ut_free(mutex->handle);
622
/*********************************************************//**
623
Initializes an operating system fast mutex semaphore. */
628
os_fast_mutex_t* fast_mutex) /*!< in: fast mutex */
633
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
635
ut_a(0 == innobase_fast_mutex_init(fast_mutex));
637
if (UNIV_LIKELY(os_sync_mutex_inited)) {
638
/* When creating os_sync_mutex itself (in Unix) we cannot
641
os_mutex_enter(os_sync_mutex);
644
os_fast_mutex_count++;
646
if (UNIV_LIKELY(os_sync_mutex_inited)) {
647
os_mutex_exit(os_sync_mutex);
651
/**********************************************************//**
652
Acquires ownership of a fast mutex. */
657
os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */
660
EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex);
662
pthread_mutex_lock(fast_mutex);
666
/**********************************************************//**
667
Releases ownership of a fast mutex. */
670
os_fast_mutex_unlock(
671
/*=================*/
672
os_fast_mutex_t* fast_mutex) /*!< in: mutex to release */
675
LeaveCriticalSection(fast_mutex);
677
pthread_mutex_unlock(fast_mutex);
681
/**********************************************************//**
682
Frees a mutex object. */
687
os_fast_mutex_t* fast_mutex) /*!< in: mutex to free */
692
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
696
ret = pthread_mutex_destroy(fast_mutex);
698
if (UNIV_UNLIKELY(ret != 0)) {
699
ut_print_timestamp(stderr);
701
" InnoDB: error: return value %lu when calling\n"
702
"InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
704
"InnoDB: Byte contents of the pthread mutex at %p:\n",
706
ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
710
if (UNIV_LIKELY(os_sync_mutex_inited)) {
711
/* When freeing the last mutexes, we have
712
already freed os_sync_mutex */
714
os_mutex_enter(os_sync_mutex);
717
os_fast_mutex_count--;
719
if (UNIV_LIKELY(os_sync_mutex_inited)) {
720
os_mutex_exit(os_sync_mutex);