00001 /****************************************************** 00002 The interface to the operating system 00003 synchronization primitives. 00004 00005 (c) 1995 Innobase Oy 00006 00007 Created 9/6/1995 Heikki Tuuri 00008 *******************************************************/ 00009 00010 #include "os0sync.h" 00011 #ifdef UNIV_NONINL 00012 #include "os0sync.ic" 00013 #endif 00014 00015 #ifdef __WIN__ 00016 #include <windows.h> 00017 #endif 00018 00019 #include "ut0mem.h" 00020 #include "srv0start.h" 00021 00022 /* Type definition for an operating system mutex struct */ 00023 struct os_mutex_struct{ 00024 void* handle; /* OS handle to mutex */ 00025 ulint count; /* we use this counter to check 00026 that the same thread does not 00027 recursively lock the mutex: we 00028 do not assume that the OS mutex 00029 supports recursive locking, though 00030 NT seems to do that */ 00031 UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list; 00032 /* list of all 'slow' OS mutexes created */ 00033 }; 00034 00035 /* Mutex protecting counts and the lists of OS mutexes and events */ 00036 os_mutex_t os_sync_mutex; 00037 ibool os_sync_mutex_inited = FALSE; 00038 00039 /* This is incremented by 1 in os_thread_create and decremented by 1 in 00040 os_thread_exit */ 00041 ulint os_thread_count = 0; 00042 00043 /* The list of all events created */ 00044 UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list; 00045 00046 /* The list of all OS 'slow' mutexes */ 00047 UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list; 00048 00049 ulint os_event_count = 0; 00050 ulint os_mutex_count = 0; 00051 ulint os_fast_mutex_count = 0; 00052 00053 00054 /************************************************************* 00055 Initializes global event and OS 'slow' mutex lists. */ 00056 00057 void 00058 os_sync_init(void) 00059 /*==============*/ 00060 { 00061 UT_LIST_INIT(os_event_list); 00062 UT_LIST_INIT(os_mutex_list); 00063 00064 os_sync_mutex = os_mutex_create(NULL); 00065 00066 os_sync_mutex_inited = TRUE; 00067 } 00068 00069 /************************************************************* 00070 Frees created events and OS 'slow' mutexes. */ 00071 00072 void 00073 os_sync_free(void) 00074 /*==============*/ 00075 { 00076 os_event_t event; 00077 os_mutex_t mutex; 00078 00079 event = UT_LIST_GET_FIRST(os_event_list); 00080 00081 while (event) { 00082 00083 os_event_free(event); 00084 00085 event = UT_LIST_GET_FIRST(os_event_list); 00086 } 00087 00088 mutex = UT_LIST_GET_FIRST(os_mutex_list); 00089 00090 while (mutex) { 00091 if (mutex == os_sync_mutex) { 00092 /* Set the flag to FALSE so that we do not try to 00093 reserve os_sync_mutex any more in remaining freeing 00094 operations in shutdown */ 00095 os_sync_mutex_inited = FALSE; 00096 } 00097 00098 os_mutex_free(mutex); 00099 00100 mutex = UT_LIST_GET_FIRST(os_mutex_list); 00101 } 00102 } 00103 00104 /************************************************************* 00105 Creates an event semaphore, i.e., a semaphore which may just have two 00106 states: signaled and nonsignaled. The created event is manual reset: it 00107 must be reset explicitly by calling sync_os_reset_event. */ 00108 00109 os_event_t 00110 os_event_create( 00111 /*============*/ 00112 /* out: the event handle */ 00113 const char* name) /* in: the name of the event, if NULL 00114 the event is created without a name */ 00115 { 00116 #ifdef __WIN__ 00117 os_event_t event; 00118 00119 event = ut_malloc(sizeof(struct os_event_struct)); 00120 00121 event->handle = CreateEvent(NULL,/* No security attributes */ 00122 TRUE, /* Manual reset */ 00123 FALSE, /* Initial state nonsignaled */ 00124 (LPCTSTR) name); 00125 if (!event->handle) { 00126 fprintf(stderr, 00127 "InnoDB: Could not create a Windows event semaphore; Windows error %lu\n", 00128 (ulong) GetLastError()); 00129 } 00130 #else /* Unix */ 00131 os_event_t event; 00132 00133 UT_NOT_USED(name); 00134 00135 event = ut_malloc(sizeof(struct os_event_struct)); 00136 00137 os_fast_mutex_init(&(event->os_mutex)); 00138 00139 #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) 00140 ut_a(0 == pthread_cond_init(&(event->cond_var), 00141 pthread_condattr_default)); 00142 #else 00143 ut_a(0 == pthread_cond_init(&(event->cond_var), NULL)); 00144 #endif 00145 event->is_set = FALSE; 00146 event->signal_count = 0; 00147 #endif /* __WIN__ */ 00148 00149 /* Put to the list of events */ 00150 os_mutex_enter(os_sync_mutex); 00151 00152 UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); 00153 00154 os_event_count++; 00155 00156 os_mutex_exit(os_sync_mutex); 00157 00158 return(event); 00159 } 00160 00161 #ifdef __WIN__ 00162 /************************************************************* 00163 Creates an auto-reset event semaphore, i.e., an event which is automatically 00164 reset when a single thread is released. Works only in Windows. */ 00165 00166 os_event_t 00167 os_event_create_auto( 00168 /*=================*/ 00169 /* out: the event handle */ 00170 const char* name) /* in: the name of the event, if NULL 00171 the event is created without a name */ 00172 { 00173 os_event_t event; 00174 00175 event = ut_malloc(sizeof(struct os_event_struct)); 00176 00177 event->handle = CreateEvent(NULL,/* No security attributes */ 00178 FALSE, /* Auto-reset */ 00179 FALSE, /* Initial state nonsignaled */ 00180 (LPCTSTR) name); 00181 00182 if (!event->handle) { 00183 fprintf(stderr, 00184 "InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n", 00185 (ulong) GetLastError()); 00186 } 00187 00188 /* Put to the list of events */ 00189 os_mutex_enter(os_sync_mutex); 00190 00191 UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); 00192 00193 os_event_count++; 00194 00195 os_mutex_exit(os_sync_mutex); 00196 00197 return(event); 00198 } 00199 #endif 00200 00201 /************************************************************** 00202 Sets an event semaphore to the signaled state: lets waiting threads 00203 proceed. */ 00204 00205 void 00206 os_event_set( 00207 /*=========*/ 00208 os_event_t event) /* in: event to set */ 00209 { 00210 #ifdef __WIN__ 00211 ut_a(event); 00212 ut_a(SetEvent(event->handle)); 00213 #else 00214 ut_a(event); 00215 00216 os_fast_mutex_lock(&(event->os_mutex)); 00217 00218 if (event->is_set) { 00219 /* Do nothing */ 00220 } else { 00221 event->is_set = TRUE; 00222 event->signal_count += 1; 00223 ut_a(0 == pthread_cond_broadcast(&(event->cond_var))); 00224 } 00225 00226 os_fast_mutex_unlock(&(event->os_mutex)); 00227 #endif 00228 } 00229 00230 /************************************************************** 00231 Resets an event semaphore to the nonsignaled state. Waiting threads will 00232 stop to wait for the event. */ 00233 00234 void 00235 os_event_reset( 00236 /*===========*/ 00237 os_event_t event) /* in: event to reset */ 00238 { 00239 #ifdef __WIN__ 00240 ut_a(event); 00241 00242 ut_a(ResetEvent(event->handle)); 00243 #else 00244 ut_a(event); 00245 00246 os_fast_mutex_lock(&(event->os_mutex)); 00247 00248 if (!event->is_set) { 00249 /* Do nothing */ 00250 } else { 00251 event->is_set = FALSE; 00252 } 00253 00254 os_fast_mutex_unlock(&(event->os_mutex)); 00255 #endif 00256 } 00257 00258 /************************************************************** 00259 Frees an event object. */ 00260 00261 void 00262 os_event_free( 00263 /*==========*/ 00264 os_event_t event) /* in: event to free */ 00265 00266 { 00267 #ifdef __WIN__ 00268 ut_a(event); 00269 00270 ut_a(CloseHandle(event->handle)); 00271 #else 00272 ut_a(event); 00273 00274 os_fast_mutex_free(&(event->os_mutex)); 00275 ut_a(0 == pthread_cond_destroy(&(event->cond_var))); 00276 #endif 00277 /* Remove from the list of events */ 00278 00279 os_mutex_enter(os_sync_mutex); 00280 00281 UT_LIST_REMOVE(os_event_list, os_event_list, event); 00282 00283 os_event_count--; 00284 00285 os_mutex_exit(os_sync_mutex); 00286 00287 ut_free(event); 00288 } 00289 00290 /************************************************************** 00291 Waits for an event object until it is in the signaled state. If 00292 srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the 00293 waiting thread when the event becomes signaled (or immediately if the 00294 event is already in the signaled state). */ 00295 00296 void 00297 os_event_wait( 00298 /*==========*/ 00299 os_event_t event) /* in: event to wait */ 00300 { 00301 #ifdef __WIN__ 00302 DWORD err; 00303 00304 ut_a(event); 00305 00306 /* Specify an infinite time limit for waiting */ 00307 err = WaitForSingleObject(event->handle, INFINITE); 00308 00309 ut_a(err == WAIT_OBJECT_0); 00310 00311 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { 00312 os_thread_exit(NULL); 00313 } 00314 #else 00315 ib_longlong old_signal_count; 00316 00317 os_fast_mutex_lock(&(event->os_mutex)); 00318 00319 old_signal_count = event->signal_count; 00320 00321 for (;;) { 00322 if (event->is_set == TRUE 00323 || event->signal_count != old_signal_count) { 00324 00325 os_fast_mutex_unlock(&(event->os_mutex)); 00326 00327 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { 00328 00329 os_thread_exit(NULL); 00330 } 00331 /* Ok, we may return */ 00332 00333 return; 00334 } 00335 00336 pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); 00337 00338 /* Solaris manual said that spurious wakeups may occur: we 00339 have to check if the event really has been signaled after 00340 we came here to wait */ 00341 } 00342 #endif 00343 } 00344 00345 /************************************************************** 00346 Waits for an event object until it is in the signaled state or 00347 a timeout is exceeded. In Unix the timeout is always infinite. */ 00348 00349 ulint 00350 os_event_wait_time( 00351 /*===============*/ 00352 /* out: 0 if success, OS_SYNC_TIME_EXCEEDED if 00353 timeout was exceeded */ 00354 os_event_t event, /* in: event to wait */ 00355 ulint time) /* in: timeout in microseconds, or 00356 OS_SYNC_INFINITE_TIME */ 00357 { 00358 #ifdef __WIN__ 00359 DWORD err; 00360 00361 ut_a(event); 00362 00363 if (time != OS_SYNC_INFINITE_TIME) { 00364 err = WaitForSingleObject(event->handle, (DWORD) time / 1000); 00365 } else { 00366 err = WaitForSingleObject(event->handle, INFINITE); 00367 } 00368 00369 if (err == WAIT_OBJECT_0) { 00370 00371 return(0); 00372 } else if (err == WAIT_TIMEOUT) { 00373 00374 return(OS_SYNC_TIME_EXCEEDED); 00375 } else { 00376 ut_error; 00377 return(1000000); /* dummy value to eliminate compiler warn. */ 00378 } 00379 #else 00380 UT_NOT_USED(time); 00381 00382 /* In Posix this is just an ordinary, infinite wait */ 00383 00384 os_event_wait(event); 00385 00386 return(0); 00387 #endif 00388 } 00389 00390 #ifdef __WIN__ 00391 /************************************************************** 00392 Waits for any event in an OS native event array. Returns if even a single 00393 one is signaled or becomes signaled. */ 00394 00395 ulint 00396 os_event_wait_multiple( 00397 /*===================*/ 00398 /* out: index of the event 00399 which was signaled */ 00400 ulint n, /* in: number of events in the 00401 array */ 00402 os_native_event_t* native_event_array) 00403 /* in: pointer to an array of event 00404 handles */ 00405 { 00406 DWORD index; 00407 00408 ut_a(native_event_array); 00409 ut_a(n > 0); 00410 00411 index = WaitForMultipleObjects((DWORD) n, native_event_array, 00412 FALSE, /* Wait for any 1 event */ 00413 INFINITE); /* Infinite wait time 00414 limit */ 00415 ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */ 00416 ut_a(index < WAIT_OBJECT_0 + n); 00417 00418 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { 00419 os_thread_exit(NULL); 00420 } 00421 00422 return(index - WAIT_OBJECT_0); 00423 } 00424 #endif 00425 00426 /************************************************************* 00427 Creates an operating system mutex semaphore. Because these are slow, the 00428 mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */ 00429 00430 os_mutex_t 00431 os_mutex_create( 00432 /*============*/ 00433 /* out: the mutex handle */ 00434 const char* name) /* in: the name of the mutex, if NULL 00435 the mutex is created without a name */ 00436 { 00437 #ifdef __WIN__ 00438 HANDLE mutex; 00439 os_mutex_t mutex_str; 00440 00441 mutex = CreateMutex(NULL, /* No security attributes */ 00442 FALSE, /* Initial state: no owner */ 00443 (LPCTSTR) name); 00444 ut_a(mutex); 00445 #else 00446 os_fast_mutex_t* mutex; 00447 os_mutex_t mutex_str; 00448 00449 UT_NOT_USED(name); 00450 00451 mutex = ut_malloc(sizeof(os_fast_mutex_t)); 00452 00453 os_fast_mutex_init(mutex); 00454 #endif 00455 mutex_str = ut_malloc(sizeof(os_mutex_str_t)); 00456 00457 mutex_str->handle = mutex; 00458 mutex_str->count = 0; 00459 00460 if (os_sync_mutex_inited) { 00461 /* When creating os_sync_mutex itself we cannot reserve it */ 00462 os_mutex_enter(os_sync_mutex); 00463 } 00464 00465 UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); 00466 00467 os_mutex_count++; 00468 00469 if (os_sync_mutex_inited) { 00470 os_mutex_exit(os_sync_mutex); 00471 } 00472 00473 return(mutex_str); 00474 } 00475 00476 /************************************************************** 00477 Acquires ownership of a mutex semaphore. */ 00478 00479 void 00480 os_mutex_enter( 00481 /*===========*/ 00482 os_mutex_t mutex) /* in: mutex to acquire */ 00483 { 00484 #ifdef __WIN__ 00485 DWORD err; 00486 00487 ut_a(mutex); 00488 00489 /* Specify infinite time limit for waiting */ 00490 err = WaitForSingleObject(mutex->handle, INFINITE); 00491 00492 ut_a(err == WAIT_OBJECT_0); 00493 00494 (mutex->count)++; 00495 ut_a(mutex->count == 1); 00496 #else 00497 os_fast_mutex_lock(mutex->handle); 00498 00499 (mutex->count)++; 00500 00501 ut_a(mutex->count == 1); 00502 #endif 00503 } 00504 00505 /************************************************************** 00506 Releases ownership of a mutex. */ 00507 00508 void 00509 os_mutex_exit( 00510 /*==========*/ 00511 os_mutex_t mutex) /* in: mutex to release */ 00512 { 00513 ut_a(mutex); 00514 00515 ut_a(mutex->count == 1); 00516 00517 (mutex->count)--; 00518 #ifdef __WIN__ 00519 ut_a(ReleaseMutex(mutex->handle)); 00520 #else 00521 os_fast_mutex_unlock(mutex->handle); 00522 #endif 00523 } 00524 00525 /************************************************************** 00526 Frees a mutex object. */ 00527 00528 void 00529 os_mutex_free( 00530 /*==========*/ 00531 os_mutex_t mutex) /* in: mutex to free */ 00532 { 00533 ut_a(mutex); 00534 00535 if (os_sync_mutex_inited) { 00536 os_mutex_enter(os_sync_mutex); 00537 } 00538 00539 UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); 00540 00541 os_mutex_count--; 00542 00543 if (os_sync_mutex_inited) { 00544 os_mutex_exit(os_sync_mutex); 00545 } 00546 00547 #ifdef __WIN__ 00548 ut_a(CloseHandle(mutex->handle)); 00549 00550 ut_free(mutex); 00551 #else 00552 os_fast_mutex_free(mutex->handle); 00553 ut_free(mutex->handle); 00554 ut_free(mutex); 00555 #endif 00556 } 00557 00558 /************************************************************* 00559 Initializes an operating system fast mutex semaphore. */ 00560 00561 void 00562 os_fast_mutex_init( 00563 /*===============*/ 00564 os_fast_mutex_t* fast_mutex) /* in: fast mutex */ 00565 { 00566 #ifdef __WIN__ 00567 ut_a(fast_mutex); 00568 00569 InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); 00570 #else 00571 #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) 00572 ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default)); 00573 #else 00574 ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); 00575 #endif 00576 #endif 00577 if (os_sync_mutex_inited) { 00578 /* When creating os_sync_mutex itself (in Unix) we cannot 00579 reserve it */ 00580 00581 os_mutex_enter(os_sync_mutex); 00582 } 00583 00584 os_fast_mutex_count++; 00585 00586 if (os_sync_mutex_inited) { 00587 os_mutex_exit(os_sync_mutex); 00588 } 00589 } 00590 00591 /************************************************************** 00592 Acquires ownership of a fast mutex. */ 00593 00594 void 00595 os_fast_mutex_lock( 00596 /*===============*/ 00597 os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */ 00598 { 00599 #ifdef __WIN__ 00600 EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex); 00601 #else 00602 pthread_mutex_lock(fast_mutex); 00603 #endif 00604 } 00605 00606 /************************************************************** 00607 Releases ownership of a fast mutex. */ 00608 00609 void 00610 os_fast_mutex_unlock( 00611 /*=================*/ 00612 os_fast_mutex_t* fast_mutex) /* in: mutex to release */ 00613 { 00614 #ifdef __WIN__ 00615 LeaveCriticalSection(fast_mutex); 00616 #else 00617 pthread_mutex_unlock(fast_mutex); 00618 #endif 00619 } 00620 00621 /************************************************************** 00622 Frees a mutex object. */ 00623 00624 void 00625 os_fast_mutex_free( 00626 /*===============*/ 00627 os_fast_mutex_t* fast_mutex) /* in: mutex to free */ 00628 { 00629 #ifdef __WIN__ 00630 ut_a(fast_mutex); 00631 00632 DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); 00633 #else 00634 int ret; 00635 00636 ret = pthread_mutex_destroy(fast_mutex); 00637 00638 if (ret != 0) { 00639 ut_print_timestamp(stderr); 00640 fprintf(stderr, 00641 " InnoDB: error: return value %lu when calling\n" 00642 "InnoDB: pthread_mutex_destroy().\n", (ulint)ret); 00643 fprintf(stderr, 00644 "InnoDB: Byte contents of the pthread mutex at %p:\n", (void*) fast_mutex); 00645 ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t)); 00646 fprintf(stderr, "\n"); 00647 } 00648 #endif 00649 if (os_sync_mutex_inited) { 00650 /* When freeing the last mutexes, we have 00651 already freed os_sync_mutex */ 00652 00653 os_mutex_enter(os_sync_mutex); 00654 } 00655 00656 os_fast_mutex_count--; 00657 00658 if (os_sync_mutex_inited) { 00659 os_mutex_exit(os_sync_mutex); 00660 } 00661 }
1.4.7

