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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
1
/******************************************************
21
2
The interface to the operating system
22
3
synchronization primitives.
24
7
Created 9/6/1995 Heikki Tuuri
25
8
*******************************************************/
52
33
/* list of all 'slow' OS mutexes created */
55
/** Mutex protecting counts and the lists of OS mutexes and events */
36
/* Mutex protecting counts and the lists of OS mutexes and events */
56
37
UNIV_INTERN os_mutex_t os_sync_mutex;
57
/** TRUE if os_sync_mutex has been initialized */
58
38
static ibool os_sync_mutex_inited = FALSE;
59
/** TRUE when os_sync_free() is being executed */
60
39
static ibool os_sync_free_called = FALSE;
62
/** This is incremented by 1 in os_thread_create and decremented by 1 in
41
/* This is incremented by 1 in os_thread_create and decremented by 1 in
64
43
UNIV_INTERN ulint os_thread_count = 0;
66
/** The list of all events created */
45
/* The list of all events created */
67
46
static UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
69
/** The list of all OS 'slow' mutexes */
48
/* The list of all OS 'slow' mutexes */
70
49
static UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
72
51
UNIV_INTERN ulint os_event_count = 0;
78
57
This version of the free event function doesn't acquire the global lock */
79
58
static void os_event_free_internal(os_event_t event);
81
/* On Windows (Vista and later), load function pointers for condition
82
variable handling. Those functions are not available in prior versions,
83
so we have to use them via runtime loading, as long as we support XP. */
84
static void os_cond_module_init(void);
87
/* Prototypes and function pointers for condition variable functions */
88
typedef VOID (WINAPI* InitializeConditionVariableProc)
89
(PCONDITION_VARIABLE ConditionVariable);
90
static InitializeConditionVariableProc initialize_condition_variable;
92
typedef BOOL (WINAPI* SleepConditionVariableCSProc)
93
(PCONDITION_VARIABLE ConditionVariable,
94
PCRITICAL_SECTION CriticalSection,
95
DWORD dwMilliseconds);
96
static SleepConditionVariableCSProc sleep_condition_variable;
98
typedef VOID (WINAPI* WakeAllConditionVariableProc)
99
(PCONDITION_VARIABLE ConditionVariable);
100
static WakeAllConditionVariableProc wake_all_condition_variable;
102
typedef VOID (WINAPI* WakeConditionVariableProc)
103
(PCONDITION_VARIABLE ConditionVariable);
104
static WakeConditionVariableProc wake_condition_variable;
107
/*********************************************************//**
108
Initialitze condition variable */
113
os_cond_t* cond) /*!< in: condition variable. */
118
ut_a(initialize_condition_variable != NULL);
119
initialize_condition_variable(cond);
121
ut_a(pthread_cond_init(cond, NULL) == 0);
125
/*********************************************************//**
126
Wait on condition variable */
131
os_cond_t* cond, /*!< in: condition variable. */
132
os_fast_mutex_t* mutex) /*!< in: fast mutex */
138
ut_a(sleep_condition_variable != NULL);
139
ut_a(sleep_condition_variable(cond, mutex, INFINITE));
141
ut_a(pthread_cond_wait(cond, mutex) == 0);
145
/*********************************************************//**
146
Wakes all threads waiting for condition variable */
151
os_cond_t* cond) /*!< in: condition variable. */
156
ut_a(wake_all_condition_variable != NULL);
157
wake_all_condition_variable(cond);
159
ut_a(pthread_cond_broadcast(cond) == 0);
163
/*********************************************************//**
164
Wakes one thread waiting for condition variable */
169
os_cond_t* cond) /*!< in: condition variable. */
174
ut_a(wake_condition_variable != NULL);
175
wake_condition_variable(cond);
177
ut_a(pthread_cond_signal(cond) == 0);
181
/*********************************************************//**
182
Destroys condition variable */
187
os_cond_t* cond) /*!< in: condition variable. */
192
ut_a(pthread_cond_destroy(cond) == 0);
196
/*********************************************************//**
197
On Windows (Vista and later), load function pointers for condition variable
198
handling. Those functions are not available in prior versions, so we have to
199
use them via runtime loading, as long as we support XP. */
202
os_cond_module_init(void)
203
/*=====================*/
208
if (!srv_use_native_conditions)
211
h_dll = GetModuleHandle("kernel32");
213
initialize_condition_variable = (InitializeConditionVariableProc)
214
GetProcAddress(h_dll, "InitializeConditionVariable");
215
sleep_condition_variable = (SleepConditionVariableCSProc)
216
GetProcAddress(h_dll, "SleepConditionVariableCS");
217
wake_all_condition_variable = (WakeAllConditionVariableProc)
218
GetProcAddress(h_dll, "WakeAllConditionVariable");
219
wake_condition_variable = (WakeConditionVariableProc)
220
GetProcAddress(h_dll, "WakeConditionVariable");
222
/* When using native condition variables, check function pointers */
223
ut_a(initialize_condition_variable);
224
ut_a(sleep_condition_variable);
225
ut_a(wake_all_condition_variable);
226
ut_a(wake_condition_variable);
230
/*********************************************************//**
60
/*************************************************************
231
61
Initializes global event and OS 'slow' mutex lists. */
285
109
os_sync_free_called = FALSE;
288
/*********************************************************//**
112
/*************************************************************
289
113
Creates an event semaphore, i.e., a semaphore which may just have two
290
114
states: signaled and nonsignaled. The created event is manual reset: it
291
must be reset explicitly by calling sync_os_reset_event.
292
@return the event handle */
115
must be reset explicitly by calling sync_os_reset_event. */
297
const char* name) /*!< in: the name of the event, if NULL
120
/* out: the event handle */
121
const char* name) /* in: the name of the event, if NULL
298
122
the event is created without a name */
127
event = ut_malloc(sizeof(struct os_event_struct));
129
event->handle = CreateEvent(NULL, /* No security attributes */
130
TRUE, /* Manual reset */
131
FALSE, /* Initial state nonsignaled */
133
if (!event->handle) {
135
"InnoDB: Could not create a Windows event semaphore;"
136
" Windows error %lu\n",
137
(ulong) GetLastError());
300
140
os_event_t event;
303
if(!srv_use_native_conditions) {
305
event = ut_malloc(sizeof(struct os_event_struct));
307
event->handle = CreateEvent(NULL,
311
if (!event->handle) {
313
"InnoDB: Could not create a Windows event"
314
" semaphore; Windows error %lu\n",
315
(ulong) GetLastError());
317
} else /* Windows with condition variables */
144
event = ut_malloc(sizeof(struct os_event_struct));
146
os_fast_mutex_init(&(event->os_mutex));
148
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
149
ut_a(0 == pthread_cond_init(&(event->cond_var),
150
pthread_condattr_default));
152
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
323
event = ut_malloc(sizeof(struct os_event_struct));
325
os_fast_mutex_init(&(event->os_mutex));
327
os_cond_init(&(event->cond_var));
329
event->is_set = FALSE;
331
/* We return this value in os_event_reset(), which can then be
332
be used to pass to the os_event_wait_low(). The value of zero
333
is reserved in os_event_wait_low() for the case when the
334
caller does not want to pass any signal_count value. To
335
distinguish between the two cases we initialize signal_count
337
event->signal_count = 1;
154
event->is_set = FALSE;
156
/* We return this value in os_event_reset(), which can then be
157
be used to pass to the os_event_wait_low(). The value of zero
158
is reserved in os_event_wait_low() for the case when the
159
caller does not want to pass any signal_count value. To
160
distinguish between the two cases we initialize signal_count
162
event->signal_count = 1;
340
165
/* The os_sync_mutex can be NULL because during startup an event
341
166
can be created [ because it's embedded in the mutex/rwlock ] before
359
/**********************************************************//**
185
/*************************************************************
186
Creates an auto-reset event semaphore, i.e., an event which is automatically
187
reset when a single thread is released. Works only in Windows. */
190
os_event_create_auto(
191
/*=================*/
192
/* out: the event handle */
193
const char* name) /* in: the name of the event, if NULL
194
the event is created without a name */
198
event = ut_malloc(sizeof(struct os_event_struct));
200
event->handle = CreateEvent(NULL, /* No security attributes */
201
FALSE, /* Auto-reset */
202
FALSE, /* Initial state nonsignaled */
205
if (!event->handle) {
207
"InnoDB: Could not create a Windows auto"
208
" event semaphore; Windows error %lu\n",
209
(ulong) GetLastError());
212
/* Put to the list of events */
213
os_mutex_enter(os_sync_mutex);
215
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
219
os_mutex_exit(os_sync_mutex);
225
/**************************************************************
360
226
Sets an event semaphore to the signaled state: lets waiting threads
366
os_event_t event) /*!< in: event to set */
232
os_event_t event) /* in: event to set */
371
if (!srv_use_native_conditions) {
372
ut_a(SetEvent(event->handle));
236
ut_a(SetEvent(event->handle));
379
240
os_fast_mutex_lock(&(event->os_mutex));
384
245
event->is_set = TRUE;
385
246
event->signal_count += 1;
386
os_cond_broadcast(&(event->cond_var));
247
ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
389
250
os_fast_mutex_unlock(&(event->os_mutex));
392
/**********************************************************//**
254
/**************************************************************
393
255
Resets an event semaphore to the nonsignaled state. Waiting threads will
394
256
stop to wait for the event.
395
257
The return value should be passed to os_even_wait_low() if it is desired
396
258
that this thread should not wait in case of an intervening call to
397
259
os_event_set() between this os_event_reset() and the
398
os_event_wait_low() call. See comments for os_event_wait_low().
399
@return current signal_count. */
260
os_event_wait_low() call. See comments for os_event_wait_low(). */
404
os_event_t event) /*!< in: event to reset */
265
/* out: current signal_count. */
266
os_event_t event) /* in: event to reset */
406
268
ib_int64_t ret = 0;
411
if(!srv_use_native_conditions) {
412
ut_a(ResetEvent(event->handle));
273
ut_a(ResetEvent(event->handle));
417
277
os_fast_mutex_lock(&(event->os_mutex));
424
284
ret = event->signal_count;
426
286
os_fast_mutex_unlock(&(event->os_mutex));
430
/**********************************************************//**
291
/**************************************************************
431
292
Frees an event object, without acquiring the global lock. */
434
295
os_event_free_internal(
435
296
/*===================*/
436
os_event_t event) /*!< in: event to free */
297
os_event_t event) /* in: event to free */
439
if(!srv_use_native_conditions) {
441
ut_a(CloseHandle(event->handle));
302
ut_a(CloseHandle(event->handle));
306
/* This is to avoid freeing the mutex twice */
307
os_fast_mutex_free(&(event->os_mutex));
309
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
447
/* This is to avoid freeing the mutex twice */
448
os_fast_mutex_free(&(event->os_mutex));
450
os_cond_destroy(&(event->cond_var));
453
311
/* Remove from the list of events */
454
313
UT_LIST_REMOVE(os_event_list, os_event_list, event);
456
315
os_event_count--;
461
/**********************************************************//**
320
/**************************************************************
462
321
Frees an event object. */
467
os_event_t event) /*!< in: event to free */
326
os_event_t event) /* in: event to free */
472
if(!srv_use_native_conditions){
473
ut_a(CloseHandle(event->handle));
474
} else /*Windows with condition variables */
332
ut_a(CloseHandle(event->handle));
336
os_fast_mutex_free(&(event->os_mutex));
337
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
477
os_fast_mutex_free(&(event->os_mutex));
479
os_cond_destroy(&(event->cond_var));
482
339
/* Remove from the list of events */
483
341
os_mutex_enter(os_sync_mutex);
485
343
UT_LIST_REMOVE(os_event_list, os_event_list, event);
516
374
os_event_wait_low(
517
375
/*==============*/
518
os_event_t event, /*!< in: event to wait */
519
ib_int64_t reset_sig_count)/*!< in: zero or the value
376
os_event_t event, /* in: event to wait */
377
ib_int64_t reset_sig_count)/* in: zero or the value
520
378
returned by previous call of
521
379
os_event_reset(). */
386
UT_NOT_USED(reset_sig_count);
388
/* Specify an infinite time limit for waiting */
389
err = WaitForSingleObject(event->handle, INFINITE);
391
ut_a(err == WAIT_OBJECT_0);
393
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
394
os_thread_exit(NULL);
523
397
ib_int64_t old_signal_count;
526
if(!srv_use_native_conditions) {
531
UT_NOT_USED(reset_sig_count);
533
/* Specify an infinite wait */
534
err = WaitForSingleObject(event->handle, INFINITE);
536
ut_a(err == WAIT_OBJECT_0);
538
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
539
os_thread_exit(NULL);
545
399
os_fast_mutex_lock(&(event->os_mutex));
547
401
if (reset_sig_count) {
568
os_cond_wait(&(event->cond_var), &(event->os_mutex));
422
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
570
424
/* Solaris manual said that spurious wakeups may occur: we
571
425
have to check if the event really has been signaled after
572
426
we came here to wait */
576
/*********************************************************//**
431
/**************************************************************
432
Waits for an event object until it is in the signaled state or
433
a timeout is exceeded. In Unix the timeout is always infinite. */
438
/* out: 0 if success, OS_SYNC_TIME_EXCEEDED if
439
timeout was exceeded */
440
os_event_t event, /* in: event to wait */
441
ulint time) /* in: timeout in microseconds, or
442
OS_SYNC_INFINITE_TIME */
449
if (time != OS_SYNC_INFINITE_TIME) {
450
err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
452
err = WaitForSingleObject(event->handle, INFINITE);
455
if (err == WAIT_OBJECT_0) {
458
} else if (err == WAIT_TIMEOUT) {
460
return(OS_SYNC_TIME_EXCEEDED);
463
return(1000000); /* dummy value to eliminate compiler warn. */
468
/* In Posix this is just an ordinary, infinite wait */
470
os_event_wait(event);
477
/**************************************************************
478
Waits for any event in an OS native event array. Returns if even a single
479
one is signaled or becomes signaled. */
482
os_event_wait_multiple(
483
/*===================*/
484
/* out: index of the event
485
which was signaled */
486
ulint n, /* in: number of events in the
488
os_native_event_t* native_event_array)
489
/* in: pointer to an array of event
494
ut_a(native_event_array);
497
index = WaitForMultipleObjects((DWORD) n, native_event_array,
498
FALSE, /* Wait for any 1 event */
499
INFINITE); /* Infinite wait time
501
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */
502
ut_a(index < WAIT_OBJECT_0 + n);
504
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
505
os_thread_exit(NULL);
508
return(index - WAIT_OBJECT_0);
512
/*************************************************************
577
513
Creates an operating system mutex semaphore. Because these are slow, the
578
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
579
@return the mutex handle */
514
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
582
os_mutex_create(void)
583
/*=================*/
519
/* out: the mutex handle */
520
const char* name) /* in: the name of the mutex, if NULL
521
the mutex is created without a name */
525
os_mutex_t mutex_str;
527
mutex = CreateMutex(NULL, /* No security attributes */
528
FALSE, /* Initial state: no owner */
585
532
os_fast_mutex_t* mutex;
586
533
os_mutex_t mutex_str;
588
537
mutex = ut_malloc(sizeof(os_fast_mutex_t));
590
539
os_fast_mutex_init(mutex);
591
541
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
593
543
mutex_str->handle = mutex;
610
560
return(mutex_str);
613
/**********************************************************//**
563
/**************************************************************
614
564
Acquires ownership of a mutex semaphore. */
619
os_mutex_t mutex) /*!< in: mutex to acquire */
569
os_mutex_t mutex) /* in: mutex to acquire */
576
/* Specify infinite time limit for waiting */
577
err = WaitForSingleObject(mutex->handle, INFINITE);
579
ut_a(err == WAIT_OBJECT_0);
582
ut_a(mutex->count == 1);
621
584
os_fast_mutex_lock(mutex->handle);
623
586
(mutex->count)++;
625
588
ut_a(mutex->count == 1);
628
/**********************************************************//**
592
/**************************************************************
629
593
Releases ownership of a mutex. */
634
os_mutex_t mutex) /*!< in: mutex to release */
598
os_mutex_t mutex) /* in: mutex to release */
638
602
ut_a(mutex->count == 1);
640
604
(mutex->count)--;
606
ut_a(ReleaseMutex(mutex->handle));
641
608
os_fast_mutex_unlock(mutex->handle);
644
/**********************************************************//**
612
/**************************************************************
645
613
Frees a mutex object. */
650
os_mutex_t mutex) /*!< in: mutex to free */
618
os_mutex_t mutex) /* in: mutex to free */
667
635
os_mutex_exit(os_sync_mutex);
639
ut_a(CloseHandle(mutex->handle));
670
643
os_fast_mutex_free(mutex->handle);
671
644
ut_free(mutex->handle);
675
/*********************************************************//**
649
/*************************************************************
676
650
Initializes an operating system fast mutex semaphore. */
679
653
os_fast_mutex_init(
680
654
/*===============*/
681
os_fast_mutex_t* fast_mutex) /*!< in: fast mutex */
655
os_fast_mutex_t* fast_mutex) /* in: fast mutex */
684
658
ut_a(fast_mutex);
686
660
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
688
ut_a(0 == innobase_fast_mutex_init(fast_mutex));
662
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
663
ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
665
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
690
668
if (UNIV_LIKELY(os_sync_mutex_inited)) {
691
669
/* When creating os_sync_mutex itself (in Unix) we cannot