diff options
Diffstat (limited to 'innobase/os/os0sync.c')
-rw-r--r-- | innobase/os/os0sync.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c new file mode 100644 index 00000000000..1647dd982f3 --- /dev/null +++ b/innobase/os/os0sync.c @@ -0,0 +1,461 @@ +/****************************************************** +The interface to the operating system +synchronization primitives. + +(c) 1995 Innobase Oy + +Created 9/6/1995 Heikki Tuuri +*******************************************************/ + +#include "os0sync.h" +#ifdef UNIV_NONINL +#include "os0sync.ic" +#endif + +#ifdef __WIN__ +#include <windows.h> +#endif + +#include "ut0mem.h" + +/* Type definition for an operating system mutex struct */ +struct os_mutex_struct{ + void* handle; /* OS handle to mutex */ + ulint count; /* we use this counter to check + that the same thread does not + recursively lock the mutex: we + do not assume that the OS mutex + supports recursive locking, though + NT seems to do that */ +}; + +/************************************************************* +Creates an event semaphore, i.e., a semaphore which may +just have two states: signaled and nonsignaled. +The created event is manual reset: it must be reset +explicitly by calling sync_os_reset_event. */ + +os_event_t +os_event_create( +/*============*/ + /* out: the event handle */ + char* name) /* in: the name of the event, if NULL + the event is created without a name */ +{ +#ifdef __WIN__ + HANDLE event; + + event = CreateEvent(NULL, /* No security attributes */ + TRUE, /* Manual reset */ + FALSE, /* Initial state nonsignaled */ + name); + ut_a(event); + + return(event); +#else + os_event_t event; + + UT_NOT_USED(name); + + event = ut_malloc(sizeof(struct os_event_struct)); + + os_fast_mutex_init(&(event->os_mutex)); + os_fast_mutex_init(&(event->wait_mutex)); + + event->is_set = TRUE; + + return(event); +#endif +} + +/************************************************************* +Creates an auto-reset event semaphore, i.e., an event +which is automatically reset when a single thread is +released. */ + +os_event_t +os_event_create_auto( +/*=================*/ + /* out: the event handle */ + char* name) /* in: the name of the event, if NULL + the event is created without a name */ +{ +#ifdef __WIN__ + HANDLE event; + + event = CreateEvent(NULL, /* No security attributes */ + FALSE, /* Auto-reset */ + FALSE, /* Initial state nonsignaled */ + name); + ut_a(event); + + return(event); +#else + /* Does nothing in Posix because we do not need this with MySQL */ + + UT_NOT_USED(name); + + return(NULL); +#endif +} + +/************************************************************** +Sets an event semaphore to the signaled state: lets waiting threads +proceed. */ + +void +os_event_set( +/*=========*/ + os_event_t event) /* in: event to set */ +{ +#ifdef __WIN__ + ut_a(event); + ut_a(SetEvent(event)); +#else + ut_a(event); + + os_fast_mutex_lock(&(event->os_mutex)); + + if (event->is_set) { + /* Do nothing */ + } else { + os_fast_mutex_unlock(&(event->wait_mutex)); + event->is_set = TRUE; + } + + os_fast_mutex_unlock(&(event->os_mutex)); +#endif +} + +/************************************************************** +Resets an event semaphore to the nonsignaled state. Waiting threads will +stop to wait for the event. */ + +void +os_event_reset( +/*===========*/ + os_event_t event) /* in: event to reset */ +{ +#ifdef __WIN__ + ut_a(event); + + ut_a(ResetEvent(event)); +#else + ut_a(event); + + os_fast_mutex_lock(&(event->os_mutex)); + + if (!event->is_set) { + /* Do nothing */ + } else { + os_fast_mutex_lock(&(event->wait_mutex)); + event->is_set = FALSE; + } + + os_fast_mutex_unlock(&(event->os_mutex)); +#endif +} + +/************************************************************** +Frees an event object. */ + +void +os_event_free( +/*==========*/ + os_event_t event) /* in: event to free */ + +{ +#ifdef __WIN__ + ut_a(event); + + ut_a(CloseHandle(event)); +#else + ut_a(event); + + os_fast_mutex_free(&(event->os_mutex)); + os_fast_mutex_free(&(event->wait_mutex)); + + ut_free(event); +#endif +} + +/************************************************************** +Waits for an event object until it is in the signaled state. */ + +void +os_event_wait( +/*==========*/ + os_event_t event) /* in: event to wait */ +{ +#ifdef __WIN__ + DWORD err; + + ut_a(event); + + /* Specify an infinite time limit for waiting */ + err = WaitForSingleObject(event, INFINITE); + + ut_a(err == WAIT_OBJECT_0); +#else + os_fast_mutex_lock(&(event->wait_mutex)); + os_fast_mutex_unlock(&(event->wait_mutex)); +#endif +} + +/************************************************************** +Waits for an event object until it is in the signaled state or +a timeout is exceeded. */ + +ulint +os_event_wait_time( +/*===============*/ + /* out: 0 if success, OS_SYNC_TIME_EXCEEDED if + timeout was exceeded */ + os_event_t event, /* in: event to wait */ + ulint time) /* in: timeout in microseconds, or + OS_SYNC_INFINITE_TIME */ +{ +#ifdef __WIN__ + DWORD err; + + ut_a(event); + + if (time != OS_SYNC_INFINITE_TIME) { + err = WaitForSingleObject(event, time / 1000); + } else { + err = WaitForSingleObject(event, INFINITE); + } + + if (err == WAIT_OBJECT_0) { + + return(0); + } else if (err == WAIT_TIMEOUT) { + + return(OS_SYNC_TIME_EXCEEDED); + } else { + ut_error; + } +#else + UT_NOT_USED(time); + + /* In Posix this is just an ordinary, infinite wait */ + + os_event_wait(event); + + return(0); +#endif +} + +/************************************************************** +Waits for any event in an event array. Returns if even a single +one is signaled or becomes signaled. */ + +ulint +os_event_wait_multiple( +/*===================*/ + /* out: index of the event + which was signaled */ + ulint n, /* in: number of events in the + array */ + os_event_t* event_array) /* in: pointer to an array of event + handles */ +{ +#ifdef __WIN__ + DWORD index; + + ut_a(event_array); + ut_a(n > 0); + + index = WaitForMultipleObjects(n, + event_array, + FALSE, /* Wait for any 1 event */ + INFINITE); /* Infinite wait time + limit */ + ut_a(index >= WAIT_OBJECT_0); + ut_a(index < WAIT_OBJECT_0 + n); + + return(index - WAIT_OBJECT_0); +#else + ut_a(n == 0); + + /* In Posix we can only wait for a single event */ + + os_event_wait(*event_array); + + return(0); +#endif +} + +/************************************************************* +Creates an operating system mutex semaphore. +Because these are slow, the mutex semaphore of the database +itself (sync_mutex_t) should be used where possible. */ + +os_mutex_t +os_mutex_create( +/*============*/ + /* out: the mutex handle */ + char* name) /* in: the name of the mutex, if NULL + the mutex is created without a name */ +{ +#ifdef __WIN__ + HANDLE mutex; + os_mutex_t mutex_str; + + mutex = CreateMutex(NULL, /* No security attributes */ + FALSE, /* Initial state: no owner */ + name); + ut_a(mutex); + + mutex_str = ut_malloc(sizeof(os_mutex_str_t)); + + mutex_str->handle = mutex; + mutex_str->count = 0; + + return(mutex_str); +#else + os_fast_mutex_t* os_mutex; + os_mutex_t mutex_str; + + UT_NOT_USED(name); + + os_mutex = ut_malloc(sizeof(os_fast_mutex_t)); + + os_fast_mutex_init(os_mutex); + + mutex_str = ut_malloc(sizeof(os_mutex_str_t)); + + mutex_str->handle = os_mutex; + mutex_str->count = 0; + + return(mutex_str); +#endif +} + +/************************************************************** +Acquires ownership of a mutex semaphore. */ + +void +os_mutex_enter( +/*===========*/ + os_mutex_t mutex) /* in: mutex to acquire */ +{ +#ifdef __WIN__ + DWORD err; + + ut_a(mutex); + + /* Specify infinite time limit for waiting */ + err = WaitForSingleObject(mutex->handle, INFINITE); + + ut_a(err == WAIT_OBJECT_0); + + (mutex->count)++; + ut_a(mutex->count == 1); +#else + os_fast_mutex_lock(mutex->handle); + + (mutex->count)++; + + ut_a(mutex->count == 1); +#endif +} + +/************************************************************** +Releases ownership of a mutex. */ + +void +os_mutex_exit( +/*==========*/ + os_mutex_t mutex) /* in: mutex to release */ +{ +#ifdef __WIN__ + ut_a(mutex); + + ut_a(mutex->count == 1); + + (mutex->count)--; + + ut_a(ReleaseMutex(mutex->handle)); +#else + ut_a(mutex); + + ut_a(mutex->count == 1); + + (mutex->count)--; + + os_fast_mutex_unlock(mutex->handle); +#endif +} + +/************************************************************** +Frees a mutex object. */ + +void +os_mutex_free( +/*==========*/ + os_mutex_t mutex) /* in: mutex to free */ +{ +#ifdef __WIN__ + ut_a(mutex); + + ut_a(CloseHandle(mutex->handle)); + ut_free(mutex); +#else + os_fast_mutex_free(mutex->handle); + ut_free(mutex->handle); + ut_free(mutex); +#endif +} + +#ifndef _WIN32 +/************************************************************* +Initializes an operating system fast mutex semaphore. */ + +void +os_fast_mutex_init( +/*===============*/ + os_fast_mutex_t* fast_mutex) /* in: fast mutex */ +{ +#ifdef __WIN__ + ut_a(fast_mutex); + + InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); +#else + pthread_mutex_init(fast_mutex, NULL); +#endif +} + +/************************************************************** +Acquires ownership of a fast mutex. */ + +void +os_fast_mutex_lock( +/*===============*/ + os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */ +{ +#ifdef __WIN__ + EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex); +#else + pthread_mutex_lock(fast_mutex); +#endif +} + +/************************************************************** +Frees a mutex object. */ + +void +os_fast_mutex_free( +/*===============*/ + os_fast_mutex_t* fast_mutex) /* in: mutex to free */ +{ +#ifdef __WIN__ + ut_a(fast_mutex); + + DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); +#else + UT_NOT_USED(fast_mutex); + +#endif +} +#endif |