summaryrefslogtreecommitdiff
path: root/innobase/os/os0sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/os/os0sync.c')
-rw-r--r--innobase/os/os0sync.c461
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