os0sync.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:14k
- /******************************************************
- 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"
- #include "srv0start.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 */
- UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
- /* list of all 'slow' OS mutexes created */
- };
- /* Mutex protecting counts and the lists of OS mutexes and events */
- os_mutex_t os_sync_mutex;
- ibool os_sync_mutex_inited = FALSE;
- /* This is incremented by 1 in os_thread_create and decremented by 1 in
- os_thread_exit */
- ulint os_thread_count = 0;
- /* The list of all events created */
- UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
- /* The list of all OS 'slow' mutexes */
- UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
- ulint os_event_count = 0;
- ulint os_mutex_count = 0;
- ulint os_fast_mutex_count = 0;
- /*************************************************************
- Initializes global event and OS 'slow' mutex lists. */
- void
- os_sync_init(void)
- /*==============*/
- {
- UT_LIST_INIT(os_event_list);
- UT_LIST_INIT(os_mutex_list);
- os_sync_mutex = os_mutex_create(NULL);
- os_sync_mutex_inited = TRUE;
- }
- /*************************************************************
- Frees created events and OS 'slow' mutexes. */
- void
- os_sync_free(void)
- /*==============*/
- {
- os_event_t event;
- os_mutex_t mutex;
- event = UT_LIST_GET_FIRST(os_event_list);
- while (event) {
- os_event_free(event);
- event = UT_LIST_GET_FIRST(os_event_list);
- }
- mutex = UT_LIST_GET_FIRST(os_mutex_list);
- while (mutex) {
- if (mutex == os_sync_mutex) {
- /* Set the flag to FALSE so that we do not try to
- reserve os_sync_mutex any more in remaining freeing
- operations in shutdown */
- os_sync_mutex_inited = FALSE;
- }
- os_mutex_free(mutex);
- mutex = UT_LIST_GET_FIRST(os_mutex_list);
- }
- }
- /*************************************************************
- 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 */
- const char* name) /* in: the name of the event, if NULL
- the event is created without a name */
- {
- #ifdef __WIN__
- os_event_t event;
- event = ut_malloc(sizeof(struct os_event_struct));
- event->handle = CreateEvent(NULL,/* No security attributes */
- TRUE, /* Manual reset */
- FALSE, /* Initial state nonsignaled */
- name);
- if (!event->handle) {
- fprintf(stderr,
- "InnoDB: Could not create a Windows event semaphore; Windows error %lun",
- (ulong) GetLastError());
- }
- #else /* Unix */
- os_event_t event;
- UT_NOT_USED(name);
- event = ut_malloc(sizeof(struct os_event_struct));
- os_fast_mutex_init(&(event->os_mutex));
- #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
- ut_a(0 == pthread_cond_init(&(event->cond_var),
- pthread_condattr_default));
- #else
- ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
- #endif
- event->is_set = FALSE;
- event->signal_count = 0;
- #endif /* __WIN__ */
- /* Put to the list of events */
- os_mutex_enter(os_sync_mutex);
- UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
- os_event_count++;
- os_mutex_exit(os_sync_mutex);
- return(event);
- }
- #ifdef __WIN__
- /*************************************************************
- Creates an auto-reset event semaphore, i.e., an event which is automatically
- reset when a single thread is released. Works only in Windows. */
- os_event_t
- os_event_create_auto(
- /*=================*/
- /* out: the event handle */
- const char* name) /* in: the name of the event, if NULL
- the event is created without a name */
- {
- os_event_t event;
- event = ut_malloc(sizeof(struct os_event_struct));
- event->handle = CreateEvent(NULL,/* No security attributes */
- FALSE, /* Auto-reset */
- FALSE, /* Initial state nonsignaled */
- name);
- if (!event->handle) {
- fprintf(stderr,
- "InnoDB: Could not create a Windows auto event semaphore; Windows error %lun",
- (ulong) GetLastError());
- }
- /* Put to the list of events */
- os_mutex_enter(os_sync_mutex);
- UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
- os_event_count++;
- os_mutex_exit(os_sync_mutex);
- return(event);
- }
- #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->handle));
- #else
- ut_a(event);
- os_fast_mutex_lock(&(event->os_mutex));
- if (event->is_set) {
- /* Do nothing */
- } else {
- event->is_set = TRUE;
- event->signal_count += 1;
- ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
- }
- 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->handle));
- #else
- ut_a(event);
- os_fast_mutex_lock(&(event->os_mutex));
- if (!event->is_set) {
- /* Do nothing */
- } else {
- 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->handle));
- #else
- ut_a(event);
- os_fast_mutex_free(&(event->os_mutex));
- ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
- #endif
- /* Remove from the list of events */
- os_mutex_enter(os_sync_mutex);
- UT_LIST_REMOVE(os_event_list, os_event_list, event);
- os_event_count--;
- os_mutex_exit(os_sync_mutex);
- ut_free(event);
- }
- /**************************************************************
- Waits for an event object until it is in the signaled state. If
- srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
- waiting thread when the event becomes signaled (or immediately if the
- event is already 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->handle, INFINITE);
- ut_a(err == WAIT_OBJECT_0);
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
- #else
- ib_longlong old_signal_count;
- os_fast_mutex_lock(&(event->os_mutex));
- old_signal_count = event->signal_count;
- loop:
- if (event->is_set == TRUE
- || event->signal_count != old_signal_count) {
- os_fast_mutex_unlock(&(event->os_mutex));
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
- /* Ok, we may return */
- return;
- }
- pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
- /* Solaris manual said that spurious wakeups may occur: we have to
- check if the event really has been signaled after we came here to
- wait */
- goto loop;
- #endif
- }
- /**************************************************************
- Waits for an event object until it is in the signaled state or
- a timeout is exceeded. In Unix the timeout is always infinite. */
- 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->handle, (DWORD) time / 1000);
- } else {
- err = WaitForSingleObject(event->handle, INFINITE);
- }
-
- if (err == WAIT_OBJECT_0) {
- return(0);
- } else if (err == WAIT_TIMEOUT) {
- return(OS_SYNC_TIME_EXCEEDED);
- } else {
- ut_error;
- return(1000000); /* dummy value to eliminate compiler warn. */
- }
- #else
- UT_NOT_USED(time);
-
- /* In Posix this is just an ordinary, infinite wait */
- os_event_wait(event);
- return(0);
- #endif
- }
- #ifdef __WIN__
- /**************************************************************
- Waits for any event in an OS native 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_native_event_t* native_event_array)
- /* in: pointer to an array of event
- handles */
- {
- DWORD index;
- ut_a(native_event_array);
- ut_a(n > 0);
- index = WaitForMultipleObjects((DWORD) n, native_event_array,
- FALSE, /* Wait for any 1 event */
- INFINITE); /* Infinite wait time
- limit */
- ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */
- ut_a(index < WAIT_OBJECT_0 + n);
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
- return(index - WAIT_OBJECT_0);
- }
- #endif
- /*************************************************************
- Creates an operating system mutex semaphore. Because these are slow, the
- mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
- os_mutex_t
- os_mutex_create(
- /*============*/
- /* out: the mutex handle */
- const 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);
- #else
- os_fast_mutex_t* mutex;
- os_mutex_t mutex_str;
- UT_NOT_USED(name);
-
- mutex = ut_malloc(sizeof(os_fast_mutex_t));
- os_fast_mutex_init(mutex);
- #endif
- mutex_str = ut_malloc(sizeof(os_mutex_str_t));
- mutex_str->handle = mutex;
- mutex_str->count = 0;
- if (os_sync_mutex_inited) {
- /* When creating os_sync_mutex itself we cannot reserve it */
- os_mutex_enter(os_sync_mutex);
- }
- UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
- os_mutex_count++;
- if (os_sync_mutex_inited) {
- os_mutex_exit(os_sync_mutex);
- }
- return(mutex_str);
- }
- /**************************************************************
- 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 */
- {
- ut_a(mutex);
- ut_a(mutex->count == 1);
- (mutex->count)--;
- #ifdef __WIN__
- ut_a(ReleaseMutex(mutex->handle));
- #else
- os_fast_mutex_unlock(mutex->handle);
- #endif
- }
- /**************************************************************
- Frees a mutex object. */
- void
- os_mutex_free(
- /*==========*/
- os_mutex_t mutex) /* in: mutex to free */
- {
- ut_a(mutex);
- if (os_sync_mutex_inited) {
- os_mutex_enter(os_sync_mutex);
- }
- UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
-
- os_mutex_count--;
- if (os_sync_mutex_inited) {
- os_mutex_exit(os_sync_mutex);
- }
- #ifdef __WIN__
- ut_a(CloseHandle(mutex->handle));
- ut_free(mutex);
- #else
- os_fast_mutex_free(mutex->handle);
- ut_free(mutex->handle);
- ut_free(mutex);
- #endif
- }
- /*************************************************************
- 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
- #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
- ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
- #else
- ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
- #endif
- #endif
- if (os_sync_mutex_inited) {
- /* When creating os_sync_mutex itself (in Unix) we cannot
- reserve it */
- os_mutex_enter(os_sync_mutex);
- }
- os_fast_mutex_count++;
- if (os_sync_mutex_inited) {
- os_mutex_exit(os_sync_mutex);
- }
- }
- /**************************************************************
- 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
- }
- /**************************************************************
- Releases ownership of a fast mutex. */
- void
- os_fast_mutex_unlock(
- /*=================*/
- os_fast_mutex_t* fast_mutex) /* in: mutex to release */
- {
- #ifdef __WIN__
- LeaveCriticalSection(fast_mutex);
- #else
- pthread_mutex_unlock(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
- int ret;
-
- ret = pthread_mutex_destroy(fast_mutex);
- if (ret != 0) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: error: return value %lu when callingn"
- "InnoDB: pthread_mutex_destroy().n", (ulint)ret);
- fprintf(stderr,
- "InnoDB: Byte contents of the pthread mutex at %p:n", fast_mutex);
- ut_print_buf(stderr, (const byte*)fast_mutex,
- sizeof(os_fast_mutex_t));
- fprintf(stderr, "n");
- }
- #endif
- if (os_sync_mutex_inited) {
- /* When freeing the last mutexes, we have
- already freed os_sync_mutex */
- os_mutex_enter(os_sync_mutex);
- }
- os_fast_mutex_count--;
- if (os_sync_mutex_inited) {
- os_mutex_exit(os_sync_mutex);
- }
- }