00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "univ.i"
00027
00028 #include <errno.h>
00029
00030 #include "os0sync.h"
00031 #ifdef UNIV_NONINL
00032 #include "os0sync.ic"
00033 #endif
00034
00035 #ifdef __WIN__
00036 #include <windows.h>
00037 #endif
00038
00039 #include "ut0mem.h"
00040 #include "srv0start.h"
00041 #include "srv0srv.h"
00042 #include "ha_prototypes.h"
00043
00044
00045 struct os_mutex_struct{
00046 os_event_t event;
00047 void* handle;
00048 ulint count;
00054 UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
00055
00056 };
00057
00059 UNIV_INTERN os_mutex_t os_sync_mutex;
00061 static ibool os_sync_mutex_inited = FALSE;
00063 static ibool os_sync_free_called = FALSE;
00064
00067 UNIV_INTERN ulint os_thread_count = 0;
00068
00070 static UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
00071
00073 static UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
00074
00075 UNIV_INTERN ulint os_event_count = 0;
00076 UNIV_INTERN ulint os_mutex_count = 0;
00077 UNIV_INTERN ulint os_fast_mutex_count = 0;
00078
00079
00080 static const ulint MICROSECS_IN_A_SECOND = 1000000;
00081
00082
00083
00084
00085 static void os_event_free_internal(os_event_t event);
00086
00087
00088
00089
00090 static void os_cond_module_init(void);
00091
00092 #ifdef __WIN__
00093
00094 typedef VOID (WINAPI* InitializeConditionVariableProc)
00095 (PCONDITION_VARIABLE ConditionVariable);
00096 static InitializeConditionVariableProc initialize_condition_variable;
00097
00098 typedef BOOL (WINAPI* SleepConditionVariableCSProc)
00099 (PCONDITION_VARIABLE ConditionVariable,
00100 PCRITICAL_SECTION CriticalSection,
00101 DWORD dwMilliseconds);
00102 static SleepConditionVariableCSProc sleep_condition_variable;
00103
00104 typedef VOID (WINAPI* WakeAllConditionVariableProc)
00105 (PCONDITION_VARIABLE ConditionVariable);
00106 static WakeAllConditionVariableProc wake_all_condition_variable;
00107
00108 typedef VOID (WINAPI* WakeConditionVariableProc)
00109 (PCONDITION_VARIABLE ConditionVariable);
00110 static WakeConditionVariableProc wake_condition_variable;
00111 #endif
00112
00113
00115 UNIV_INLINE
00116 void
00117 os_cond_init(
00118
00119 os_cond_t* cond)
00120 {
00121 ut_a(cond);
00122
00123 #ifdef __WIN__
00124 ut_a(initialize_condition_variable != NULL);
00125 initialize_condition_variable(cond);
00126 #else
00127 ut_a(pthread_cond_init(cond, NULL) == 0);
00128 #endif
00129 }
00130
00131
00134 UNIV_INLINE
00135 ibool
00136 os_cond_wait_timed(
00137
00138 os_cond_t* cond,
00139 os_fast_mutex_t* mutex,
00140 #ifndef __WIN__
00141 const struct timespec* abstime
00142 #else
00143 DWORD time_in_ms
00145 #endif
00146 )
00147 {
00148 #ifdef __WIN__
00149 BOOL ret;
00150 DWORD err;
00151
00152 ut_a(sleep_condition_variable != NULL);
00153
00154 ret = sleep_condition_variable(cond, mutex, time_in_ms);
00155
00156 if (!ret) {
00157 err = GetLastError();
00158
00159
00160
00161
00162
00163
00164 if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
00165 return(TRUE);
00166 }
00167 }
00168
00169 ut_a(ret);
00170
00171 return(FALSE);
00172 #else
00173 int ret;
00174
00175 ret = pthread_cond_timedwait(cond, mutex, abstime);
00176
00177 switch (ret) {
00178 case 0:
00179 case ETIMEDOUT:
00180
00181
00182 case EINTR:
00183 break;
00184
00185 default:
00186 fprintf(stderr, " InnoDB: pthread_cond_timedwait() returned: "
00187 "%d: abstime={%lu,%lu}\n",
00188 ret, (ulong) abstime->tv_sec, (ulong) abstime->tv_nsec);
00189 ut_error;
00190 }
00191
00192 return(ret == ETIMEDOUT);
00193 #endif
00194 }
00195
00197 UNIV_INLINE
00198 void
00199 os_cond_wait(
00200
00201 os_cond_t* cond,
00202 os_fast_mutex_t* mutex)
00203 {
00204 ut_a(cond);
00205 ut_a(mutex);
00206
00207 #ifdef __WIN__
00208 ut_a(sleep_condition_variable != NULL);
00209 ut_a(sleep_condition_variable(cond, mutex, INFINITE));
00210 #else
00211 ut_a(pthread_cond_wait(cond, mutex) == 0);
00212 #endif
00213 }
00214
00215
00217 UNIV_INLINE
00218 void
00219 os_cond_broadcast(
00220
00221 os_cond_t* cond)
00222 {
00223 ut_a(cond);
00224
00225 #ifdef __WIN__
00226 ut_a(wake_all_condition_variable != NULL);
00227 wake_all_condition_variable(cond);
00228 #else
00229 ut_a(pthread_cond_broadcast(cond) == 0);
00230 #endif
00231 }
00232
00233
00235 UNIV_INLINE
00236 void
00237 os_cond_signal(
00238
00239 os_cond_t* cond)
00240 {
00241 ut_a(cond);
00242
00243 #ifdef __WIN__
00244 ut_a(wake_condition_variable != NULL);
00245 wake_condition_variable(cond);
00246 #else
00247 ut_a(pthread_cond_signal(cond) == 0);
00248 #endif
00249 }
00250
00251
00253 UNIV_INLINE
00254 void
00255 os_cond_destroy(
00256
00257 os_cond_t* cond)
00258 {
00259 #ifdef __WIN__
00260
00261 #else
00262 ut_a(pthread_cond_destroy(cond) == 0);
00263 #endif
00264 }
00265
00266
00270 static
00271 void
00272 os_cond_module_init(void)
00273
00274 {
00275 #ifdef __WIN__
00276 HMODULE h_dll;
00277
00278 if (!srv_use_native_conditions)
00279 return;
00280
00281 h_dll = GetModuleHandle("kernel32");
00282
00283 initialize_condition_variable = (InitializeConditionVariableProc)
00284 GetProcAddress(h_dll, "InitializeConditionVariable");
00285 sleep_condition_variable = (SleepConditionVariableCSProc)
00286 GetProcAddress(h_dll, "SleepConditionVariableCS");
00287 wake_all_condition_variable = (WakeAllConditionVariableProc)
00288 GetProcAddress(h_dll, "WakeAllConditionVariable");
00289 wake_condition_variable = (WakeConditionVariableProc)
00290 GetProcAddress(h_dll, "WakeConditionVariable");
00291
00292
00293 ut_a(initialize_condition_variable);
00294 ut_a(sleep_condition_variable);
00295 ut_a(wake_all_condition_variable);
00296 ut_a(wake_condition_variable);
00297 #endif
00298 }
00299
00300
00302 UNIV_INTERN
00303 void
00304 os_sync_init(void)
00305
00306 {
00307 UT_LIST_INIT(os_event_list);
00308 UT_LIST_INIT(os_mutex_list);
00309
00310 os_sync_mutex = NULL;
00311 os_sync_mutex_inited = FALSE;
00312
00313
00314 os_cond_module_init();
00315
00316 os_sync_mutex = os_mutex_create();
00317
00318 os_sync_mutex_inited = TRUE;
00319 }
00320
00321
00323 UNIV_INTERN
00324 void
00325 os_sync_free(void)
00326
00327 {
00328 os_event_t event;
00329 os_mutex_t mutex;
00330
00331 os_sync_free_called = TRUE;
00332 event = UT_LIST_GET_FIRST(os_event_list);
00333
00334 while (event) {
00335
00336 os_event_free(event);
00337
00338 event = UT_LIST_GET_FIRST(os_event_list);
00339 }
00340
00341 mutex = UT_LIST_GET_FIRST(os_mutex_list);
00342
00343 while (mutex) {
00344 if (mutex == os_sync_mutex) {
00345
00346
00347
00348 os_sync_mutex_inited = FALSE;
00349 }
00350
00351 os_mutex_free(mutex);
00352
00353 mutex = UT_LIST_GET_FIRST(os_mutex_list);
00354 }
00355 os_sync_free_called = FALSE;
00356 }
00357
00358
00363 UNIV_INTERN
00364 os_event_t
00365 os_event_create(
00366
00367 const char* name)
00369 {
00370 os_event_t event;
00371
00372 #ifdef __WIN__
00373 if(!srv_use_native_conditions) {
00374
00375 event = ut_malloc(sizeof(struct os_event_struct));
00376
00377 event->handle = CreateEvent(NULL,
00378 TRUE,
00379 FALSE,
00380 (LPCTSTR) name);
00381 if (!event->handle) {
00382 fprintf(stderr,
00383 "InnoDB: Could not create a Windows event"
00384 " semaphore; Windows error %lu\n",
00385 (ulong) GetLastError());
00386 }
00387 } else
00388 #endif
00389
00390 {
00391 UT_NOT_USED(name);
00392
00393 event = static_cast<os_event_struct*>(ut_malloc(sizeof(struct os_event_struct)));
00394
00395 os_fast_mutex_init(&(event->os_mutex));
00396
00397 os_cond_init(&(event->cond_var));
00398
00399 event->is_set = FALSE;
00400
00401
00402
00403
00404
00405
00406
00407 event->signal_count = 1;
00408 }
00409
00410
00411
00412
00413 if (os_sync_mutex != NULL) {
00414 os_mutex_enter(os_sync_mutex);
00415 }
00416
00417
00418 UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
00419
00420 os_event_count++;
00421
00422 if (os_sync_mutex != NULL) {
00423 os_mutex_exit(os_sync_mutex);
00424 }
00425
00426 return(event);
00427 }
00428
00429
00432 UNIV_INTERN
00433 void
00434 os_event_set(
00435
00436 os_event_t event)
00437 {
00438 ut_a(event);
00439
00440 #ifdef __WIN__
00441 if (!srv_use_native_conditions) {
00442 ut_a(SetEvent(event->handle));
00443 return;
00444 }
00445 #endif
00446
00447 ut_a(event);
00448
00449 os_fast_mutex_lock(&(event->os_mutex));
00450
00451 if (event->is_set) {
00452
00453 } else {
00454 event->is_set = TRUE;
00455 event->signal_count += 1;
00456 os_cond_broadcast(&(event->cond_var));
00457 }
00458
00459 os_fast_mutex_unlock(&(event->os_mutex));
00460 }
00461
00462
00470 UNIV_INTERN
00471 ib_int64_t
00472 os_event_reset(
00473
00474 os_event_t event)
00475 {
00476 ib_int64_t ret = 0;
00477
00478 ut_a(event);
00479
00480 #ifdef __WIN__
00481 if(!srv_use_native_conditions) {
00482 ut_a(ResetEvent(event->handle));
00483 return(0);
00484 }
00485 #endif
00486
00487 os_fast_mutex_lock(&(event->os_mutex));
00488
00489 if (!event->is_set) {
00490
00491 } else {
00492 event->is_set = FALSE;
00493 }
00494 ret = event->signal_count;
00495
00496 os_fast_mutex_unlock(&(event->os_mutex));
00497 return(ret);
00498 }
00499
00500
00502 static
00503 void
00504 os_event_free_internal(
00505
00506 os_event_t event)
00507 {
00508 #ifdef __WIN__
00509 if(!srv_use_native_conditions) {
00510 ut_a(event);
00511 ut_a(CloseHandle(event->handle));
00512 } else
00513 #endif
00514 {
00515 ut_a(event);
00516
00517
00518 os_fast_mutex_free(&(event->os_mutex));
00519
00520 os_cond_destroy(&(event->cond_var));
00521 }
00522
00523
00524 UT_LIST_REMOVE(os_event_list, os_event_list, event);
00525
00526 os_event_count--;
00527
00528 ut_free(event);
00529 }
00530
00531
00533 UNIV_INTERN
00534 void
00535 os_event_free(
00536
00537 os_event_t event)
00539 {
00540 ut_a(event);
00541 #ifdef __WIN__
00542 if(!srv_use_native_conditions){
00543 ut_a(CloseHandle(event->handle));
00544 } else
00545 #endif
00546 {
00547 os_fast_mutex_free(&(event->os_mutex));
00548
00549 os_cond_destroy(&(event->cond_var));
00550 }
00551
00552
00553 os_mutex_enter(os_sync_mutex);
00554
00555 UT_LIST_REMOVE(os_event_list, os_event_list, event);
00556
00557 os_event_count--;
00558
00559 os_mutex_exit(os_sync_mutex);
00560
00561 ut_free(event);
00562 }
00563
00564
00584 UNIV_INTERN
00585 void
00586 os_event_wait_low(
00587
00588 os_event_t event,
00589 ib_int64_t reset_sig_count)
00592 {
00593 ib_int64_t old_signal_count;
00594
00595 #ifdef __WIN__
00596 if(!srv_use_native_conditions) {
00597 DWORD err;
00598
00599 ut_a(event);
00600
00601 UT_NOT_USED(reset_sig_count);
00602
00603
00604 err = WaitForSingleObject(event->handle, INFINITE);
00605
00606 ut_a(err == WAIT_OBJECT_0);
00607
00608 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
00609 os_thread_exit(NULL);
00610 }
00611 return;
00612 }
00613 #endif
00614
00615 os_fast_mutex_lock(&(event->os_mutex));
00616
00617 if (reset_sig_count) {
00618 old_signal_count = reset_sig_count;
00619 } else {
00620 old_signal_count = event->signal_count;
00621 }
00622
00623 for (;;) {
00624 if (event->is_set == TRUE
00625 || event->signal_count != old_signal_count) {
00626
00627 os_fast_mutex_unlock(&(event->os_mutex));
00628
00629 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
00630
00631 os_thread_exit(NULL);
00632 }
00633
00634
00635 return;
00636 }
00637
00638 os_cond_wait(&(event->cond_var), &(event->os_mutex));
00639
00640
00641
00642
00643 }
00644 }
00645
00646
00650 UNIV_INTERN
00651 ulint
00652 os_event_wait_time_low(
00653
00654 os_event_t event,
00655 ulint time_in_usec,
00658 ib_int64_t reset_sig_count)
00662 {
00663 ibool timed_out = FALSE;
00664 ib_int64_t old_signal_count;
00665
00666 #ifdef __WIN__
00667 DWORD time_in_ms;
00668
00669 if (!srv_use_native_conditions) {
00670 DWORD err;
00671
00672 ut_a(event);
00673
00674 if (time_in_usec != OS_SYNC_INFINITE_TIME) {
00675 time_in_ms = time_in_usec / 1000;
00676 err = WaitForSingleObject(event->handle, time_in_ms);
00677 } else {
00678 err = WaitForSingleObject(event->handle, INFINITE);
00679 }
00680
00681 if (err == WAIT_OBJECT_0) {
00682 return(0);
00683 } else if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
00684 return(OS_SYNC_TIME_EXCEEDED);
00685 }
00686
00687 ut_error;
00688
00689 return(42);
00690 } else {
00691 ut_a(sleep_condition_variable != NULL);
00692
00693 if (time_in_usec != OS_SYNC_INFINITE_TIME) {
00694 time_in_ms = time_in_usec / 1000;
00695 } else {
00696 time_in_ms = INFINITE;
00697 }
00698 }
00699 #else
00700 struct timespec abstime;
00701
00702 if (time_in_usec != OS_SYNC_INFINITE_TIME) {
00703 struct timeval tv;
00704 int ret;
00705 ulint sec;
00706 ulint usec;
00707
00708 ret = ut_usectime(&sec, &usec);
00709 ut_a(ret == 0);
00710
00711 tv.tv_sec = sec;
00712 tv.tv_usec = usec;
00713
00714 tv.tv_usec += time_in_usec;
00715
00716 if ((ulint) tv.tv_usec >= MICROSECS_IN_A_SECOND) {
00717 tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
00718 tv.tv_usec %= MICROSECS_IN_A_SECOND;
00719 }
00720
00721 abstime.tv_sec = tv.tv_sec;
00722 abstime.tv_nsec = tv.tv_usec * 1000;
00723 } else {
00724 abstime.tv_nsec = 999999999;
00725 abstime.tv_sec = (time_t) ULINT_MAX;
00726 }
00727
00728 ut_a(abstime.tv_nsec <= 999999999);
00729
00730 #endif
00731
00732 os_fast_mutex_lock(&event->os_mutex);
00733
00734 if (reset_sig_count) {
00735 old_signal_count = reset_sig_count;
00736 } else {
00737 old_signal_count = event->signal_count;
00738 }
00739
00740 do {
00741 if (event->is_set == TRUE
00742 || event->signal_count != old_signal_count) {
00743
00744 break;
00745 }
00746
00747 timed_out = os_cond_wait_timed(
00748 &event->cond_var, &event->os_mutex,
00749 #ifndef __WIN__
00750 &abstime
00751 #else
00752 time_in_ms
00753 #endif
00754 );
00755
00756 } while (!timed_out);
00757
00758 os_fast_mutex_unlock(&event->os_mutex);
00759
00760 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
00761
00762 os_thread_exit(NULL);
00763 }
00764
00765 return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
00766 }
00767
00768
00772 UNIV_INTERN
00773 os_mutex_t
00774 os_mutex_create(void)
00775
00776 {
00777 os_fast_mutex_t* mutex;
00778 os_mutex_t mutex_str;
00779
00780 mutex = static_cast<os_fast_mutex_t*>(ut_malloc(sizeof(os_fast_mutex_t)));
00781
00782 os_fast_mutex_init(mutex);
00783 mutex_str = static_cast<os_mutex_t>(ut_malloc(sizeof(os_mutex_str_t)));
00784
00785 mutex_str->handle = mutex;
00786 mutex_str->count = 0;
00787 mutex_str->event = os_event_create(NULL);
00788
00789 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00790
00791 os_mutex_enter(os_sync_mutex);
00792 }
00793
00794 UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
00795
00796 os_mutex_count++;
00797
00798 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00799 os_mutex_exit(os_sync_mutex);
00800 }
00801
00802 return(mutex_str);
00803 }
00804
00805
00807 UNIV_INTERN
00808 void
00809 os_mutex_enter(
00810
00811 os_mutex_t mutex)
00812 {
00813 os_fast_mutex_lock(static_cast<os_fast_mutex_t *>(mutex->handle));
00814
00815 (mutex->count)++;
00816
00817 ut_a(mutex->count == 1);
00818 }
00819
00820
00822 UNIV_INTERN
00823 void
00824 os_mutex_exit(
00825
00826 os_mutex_t mutex)
00827 {
00828 ut_a(mutex);
00829
00830 ut_a(mutex->count == 1);
00831
00832 (mutex->count)--;
00833 os_fast_mutex_unlock(static_cast<os_fast_mutex_t *>(mutex->handle));
00834 }
00835
00836
00838 UNIV_INTERN
00839 void
00840 os_mutex_free(
00841
00842 os_mutex_t mutex)
00843 {
00844 ut_a(mutex);
00845
00846 if (UNIV_LIKELY(!os_sync_free_called)) {
00847 os_event_free_internal(mutex->event);
00848 }
00849
00850 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00851 os_mutex_enter(os_sync_mutex);
00852 }
00853
00854 UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
00855
00856 os_mutex_count--;
00857
00858 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00859 os_mutex_exit(os_sync_mutex);
00860 }
00861
00862 os_fast_mutex_free(static_cast<os_fast_mutex_t *>(mutex->handle));
00863 ut_free(mutex->handle);
00864 ut_free(mutex);
00865 }
00866
00867
00869 UNIV_INTERN
00870 void
00871 os_fast_mutex_init(
00872
00873 os_fast_mutex_t* fast_mutex)
00874 {
00875 #ifdef __WIN__
00876 ut_a(fast_mutex);
00877
00878 InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
00879 #else
00880 ut_a(0 == pthread_mutex_init(fast_mutex, NULL));
00881 #endif
00882 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00883
00884
00885
00886 os_mutex_enter(os_sync_mutex);
00887 }
00888
00889 os_fast_mutex_count++;
00890
00891 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00892 os_mutex_exit(os_sync_mutex);
00893 }
00894 }
00895
00896
00898 UNIV_INTERN
00899 void
00900 os_fast_mutex_lock(
00901
00902 os_fast_mutex_t* fast_mutex)
00903 {
00904 #ifdef __WIN__
00905 EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex);
00906 #else
00907 pthread_mutex_lock(fast_mutex);
00908 #endif
00909 }
00910
00911
00913 UNIV_INTERN
00914 void
00915 os_fast_mutex_unlock(
00916
00917 os_fast_mutex_t* fast_mutex)
00918 {
00919 #ifdef __WIN__
00920 LeaveCriticalSection(fast_mutex);
00921 #else
00922 pthread_mutex_unlock(fast_mutex);
00923 #endif
00924 }
00925
00926
00928 UNIV_INTERN
00929 void
00930 os_fast_mutex_free(
00931
00932 os_fast_mutex_t* fast_mutex)
00933 {
00934 #ifdef __WIN__
00935 ut_a(fast_mutex);
00936
00937 DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
00938 #else
00939 int ret;
00940
00941 ret = pthread_mutex_destroy(fast_mutex);
00942
00943 if (UNIV_UNLIKELY(ret != 0)) {
00944 ut_print_timestamp(stderr);
00945 fprintf(stderr,
00946 " InnoDB: error: return value %lu when calling\n"
00947 "InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
00948 fprintf(stderr,
00949 "InnoDB: Byte contents of the pthread mutex at %p:\n",
00950 (void*) fast_mutex);
00951 ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
00952 putc('\n', stderr);
00953 }
00954 #endif
00955 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00956
00957
00958
00959 os_mutex_enter(os_sync_mutex);
00960 }
00961
00962 ut_ad(os_fast_mutex_count > 0);
00963 os_fast_mutex_count--;
00964
00965 if (UNIV_LIKELY(os_sync_mutex_inited)) {
00966 os_mutex_exit(os_sync_mutex);
00967 }
00968 }