1
/******************************************************
2
The interface to the operating system
3
synchronization primitives.
7
Created 9/6/1995 Heikki Tuuri
8
*******************************************************/
20
#include "srv0start.h"
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 */
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;
39
/* This is incremented by 1 in os_thread_create and decremented by 1 in
41
ulint os_thread_count = 0;
43
/* The list of all events created */
44
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
46
/* The list of all OS 'slow' mutexes */
47
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
49
ulint os_event_count = 0;
50
ulint os_mutex_count = 0;
51
ulint os_fast_mutex_count = 0;
54
/*************************************************************
55
Initializes global event and OS 'slow' mutex lists. */
61
UT_LIST_INIT(os_event_list);
62
UT_LIST_INIT(os_mutex_list);
64
os_sync_mutex = os_mutex_create(NULL);
66
os_sync_mutex_inited = TRUE;
69
/*************************************************************
70
Frees created events and OS 'slow' mutexes. */
79
event = UT_LIST_GET_FIRST(os_event_list);
85
event = UT_LIST_GET_FIRST(os_event_list);
88
mutex = UT_LIST_GET_FIRST(os_mutex_list);
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;
100
mutex = UT_LIST_GET_FIRST(os_mutex_list);
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. */
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 */
119
event = ut_malloc(sizeof(struct os_event_struct));
121
event->handle = CreateEvent(NULL, /* No security attributes */
122
TRUE, /* Manual reset */
123
FALSE, /* Initial state nonsignaled */
125
if (!event->handle) {
127
"InnoDB: Could not create a Windows event semaphore;"
128
" Windows error %lu\n",
129
(ulong) GetLastError());
136
event = ut_malloc(sizeof(struct os_event_struct));
138
os_fast_mutex_init(&(event->os_mutex));
140
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
141
ut_a(0 == pthread_cond_init(&(event->cond_var),
142
pthread_condattr_default));
144
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
146
event->is_set = FALSE;
147
event->signal_count = 0;
150
/* Put to the list of events */
151
os_mutex_enter(os_sync_mutex);
153
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
157
os_mutex_exit(os_sync_mutex);
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. */
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 */
176
event = ut_malloc(sizeof(struct os_event_struct));
178
event->handle = CreateEvent(NULL, /* No security attributes */
179
FALSE, /* Auto-reset */
180
FALSE, /* Initial state nonsignaled */
183
if (!event->handle) {
185
"InnoDB: Could not create a Windows auto"
186
" event semaphore; Windows error %lu\n",
187
(ulong) GetLastError());
190
/* Put to the list of events */
191
os_mutex_enter(os_sync_mutex);
193
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
197
os_mutex_exit(os_sync_mutex);
203
/**************************************************************
204
Sets an event semaphore to the signaled state: lets waiting threads
210
os_event_t event) /* in: event to set */
214
ut_a(SetEvent(event->handle));
218
os_fast_mutex_lock(&(event->os_mutex));
223
event->is_set = TRUE;
224
event->signal_count += 1;
225
ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
228
os_fast_mutex_unlock(&(event->os_mutex));
232
/**************************************************************
233
Resets an event semaphore to the nonsignaled state. Waiting threads will
234
stop to wait for the event. */
239
os_event_t event) /* in: event to reset */
244
ut_a(ResetEvent(event->handle));
248
os_fast_mutex_lock(&(event->os_mutex));
250
if (!event->is_set) {
253
event->is_set = FALSE;
256
os_fast_mutex_unlock(&(event->os_mutex));
260
/**************************************************************
261
Frees an event object. */
266
os_event_t event) /* in: event to free */
272
ut_a(CloseHandle(event->handle));
276
os_fast_mutex_free(&(event->os_mutex));
277
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
279
/* Remove from the list of events */
281
os_mutex_enter(os_sync_mutex);
283
UT_LIST_REMOVE(os_event_list, os_event_list, event);
287
os_mutex_exit(os_sync_mutex);
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). */
301
os_event_t event) /* in: event to wait */
308
/* Specify an infinite time limit for waiting */
309
err = WaitForSingleObject(event->handle, INFINITE);
311
ut_a(err == WAIT_OBJECT_0);
313
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
314
os_thread_exit(NULL);
317
ib_longlong old_signal_count;
319
os_fast_mutex_lock(&(event->os_mutex));
321
old_signal_count = event->signal_count;
324
if (event->is_set == TRUE
325
|| event->signal_count != old_signal_count) {
327
os_fast_mutex_unlock(&(event->os_mutex));
329
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
331
os_thread_exit(NULL);
333
/* Ok, we may return */
338
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
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 */
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. */
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 */
365
if (time != OS_SYNC_INFINITE_TIME) {
366
err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
368
err = WaitForSingleObject(event->handle, INFINITE);
371
if (err == WAIT_OBJECT_0) {
374
} else if (err == WAIT_TIMEOUT) {
376
return(OS_SYNC_TIME_EXCEEDED);
379
return(1000000); /* dummy value to eliminate compiler warn. */
384
/* In Posix this is just an ordinary, infinite wait */
386
os_event_wait(event);
393
/**************************************************************
394
Waits for any event in an OS native event array. Returns if even a single
395
one is signaled or becomes signaled. */
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
404
os_native_event_t* native_event_array)
405
/* in: pointer to an array of event
410
ut_a(native_event_array);
413
index = WaitForMultipleObjects((DWORD) n, native_event_array,
414
FALSE, /* Wait for any 1 event */
415
INFINITE); /* Infinite wait time
417
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */
418
ut_a(index < WAIT_OBJECT_0 + n);
420
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
421
os_thread_exit(NULL);
424
return(index - WAIT_OBJECT_0);
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. */
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 */
441
os_mutex_t mutex_str;
443
mutex = CreateMutex(NULL, /* No security attributes */
444
FALSE, /* Initial state: no owner */
448
os_fast_mutex_t* mutex;
449
os_mutex_t mutex_str;
453
mutex = ut_malloc(sizeof(os_fast_mutex_t));
455
os_fast_mutex_init(mutex);
457
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
459
mutex_str->handle = mutex;
460
mutex_str->count = 0;
462
if (os_sync_mutex_inited) {
463
/* When creating os_sync_mutex itself we cannot reserve it */
464
os_mutex_enter(os_sync_mutex);
467
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
471
if (os_sync_mutex_inited) {
472
os_mutex_exit(os_sync_mutex);
478
/**************************************************************
479
Acquires ownership of a mutex semaphore. */
484
os_mutex_t mutex) /* in: mutex to acquire */
491
/* Specify infinite time limit for waiting */
492
err = WaitForSingleObject(mutex->handle, INFINITE);
494
ut_a(err == WAIT_OBJECT_0);
497
ut_a(mutex->count == 1);
499
os_fast_mutex_lock(mutex->handle);
503
ut_a(mutex->count == 1);
507
/**************************************************************
508
Releases ownership of a mutex. */
513
os_mutex_t mutex) /* in: mutex to release */
517
ut_a(mutex->count == 1);
521
ut_a(ReleaseMutex(mutex->handle));
523
os_fast_mutex_unlock(mutex->handle);
527
/**************************************************************
528
Frees a mutex object. */
533
os_mutex_t mutex) /* in: mutex to free */
537
if (os_sync_mutex_inited) {
538
os_mutex_enter(os_sync_mutex);
541
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
545
if (os_sync_mutex_inited) {
546
os_mutex_exit(os_sync_mutex);
550
ut_a(CloseHandle(mutex->handle));
554
os_fast_mutex_free(mutex->handle);
555
ut_free(mutex->handle);
560
/*************************************************************
561
Initializes an operating system fast mutex semaphore. */
566
os_fast_mutex_t* fast_mutex) /* in: fast mutex */
571
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
573
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
574
ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
576
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
579
if (os_sync_mutex_inited) {
580
/* When creating os_sync_mutex itself (in Unix) we cannot
583
os_mutex_enter(os_sync_mutex);
586
os_fast_mutex_count++;
588
if (os_sync_mutex_inited) {
589
os_mutex_exit(os_sync_mutex);
593
/**************************************************************
594
Acquires ownership of a fast mutex. */
599
os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */
602
EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex);
604
pthread_mutex_lock(fast_mutex);
608
/**************************************************************
609
Releases ownership of a fast mutex. */
612
os_fast_mutex_unlock(
613
/*=================*/
614
os_fast_mutex_t* fast_mutex) /* in: mutex to release */
617
LeaveCriticalSection(fast_mutex);
619
pthread_mutex_unlock(fast_mutex);
623
/**************************************************************
624
Frees a mutex object. */
629
os_fast_mutex_t* fast_mutex) /* in: mutex to free */
634
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
638
ret = pthread_mutex_destroy(fast_mutex);
641
ut_print_timestamp(stderr);
643
" InnoDB: error: return value %lu when calling\n"
644
"InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
646
"InnoDB: Byte contents of the pthread mutex at %p:\n",
648
ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
649
fprintf(stderr, "\n");
652
if (os_sync_mutex_inited) {
653
/* When freeing the last mutexes, we have
654
already freed os_sync_mutex */
656
os_mutex_enter(os_sync_mutex);
659
os_fast_mutex_count--;
661
if (os_sync_mutex_inited) {
662
os_mutex_exit(os_sync_mutex);