Drizzled Public API Documentation

os0sync.cc

00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
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 /* Type definition for an operating system mutex struct */
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         /* list of all 'slow' OS mutexes created */
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 /* The number of microsecnds in a second. */
00080 static const ulint MICROSECS_IN_A_SECOND = 1000000;
00081 
00082 /* Because a mutex is embedded inside an event and there is an
00083 event embedded inside a mutex, on free, this generates a recursive call.
00084 This version of the free event function doesn't acquire the global lock */
00085 static void os_event_free_internal(os_event_t event);
00086 
00087 /* On Windows (Vista and later), load function pointers for condition
00088 variable handling. Those functions are not available in prior versions,
00089 so we have to use them via runtime loading, as long as we support XP. */
00090 static void os_cond_module_init(void);
00091 
00092 #ifdef __WIN__
00093 /* Prototypes and function pointers for condition variable functions */
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 /* !__WIN__ */
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     /* From http://msdn.microsoft.com/en-us/library/ms686301%28VS.85%29.aspx,
00159     "Condition variables are subject to spurious wakeups
00160     (those not associated with an explicit wake) and stolen wakeups
00161     (another thread manages to run before the woken thread)."
00162     Check for both types of timeouts.
00163     Conditions are checked by the caller.*/
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   /* We play it safe by checking for EINTR even though
00181   according to the POSIX documentation it can't return EINTR. */
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   /* Do nothing */
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   /* When using native condition variables, check function pointers */
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   /* Now for Windows only */
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       /* Set the flag to FALSE so that we do not try to
00346       reserve os_sync_mutex any more in remaining freeing
00347       operations in shutdown */
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 /* Windows with condition variables */
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     /* We return this value in os_event_reset(), which can then be
00402     be used to pass to the os_event_wait_low(). The value of zero
00403     is reserved in os_event_wait_low() for the case when the
00404     caller does not want to pass any signal_count value. To
00405     distinguish between the two cases we initialize signal_count
00406     to 1 here. */
00407     event->signal_count = 1;
00408   }
00409 
00410   /* The os_sync_mutex can be NULL because during startup an event
00411   can be created [ because it's embedded in the mutex/rwlock ] before
00412   this module has been initialized */
00413   if (os_sync_mutex != NULL) {
00414     os_mutex_enter(os_sync_mutex);
00415   }
00416 
00417   /* Put to the list of events */
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     /* Do nothing */
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     /* Do nothing */
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     /* This is to avoid freeing the mutex twice */
00518     os_fast_mutex_free(&(event->os_mutex));
00519 
00520     os_cond_destroy(&(event->cond_var));
00521   }
00522 
00523   /* Remove from the list of events */
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 /*Windows with condition variables */
00545 #endif
00546   {
00547     os_fast_mutex_free(&(event->os_mutex));
00548 
00549     os_cond_destroy(&(event->cond_var));
00550   }
00551 
00552   /* Remove from the list of events */
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     /* Specify an infinite wait */
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       /* Ok, we may return */
00634 
00635       return;
00636     }
00637 
00638     os_cond_wait(&(event->cond_var), &(event->os_mutex));
00639 
00640     /* Solaris manual said that spurious wakeups may occur: we
00641     have to check if the event really has been signaled after
00642     we came here to wait */
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     /* Dummy value to eliminate compiler warning. */
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 /* __WIN__ */
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 /* !__WIN__ */
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     /* When creating os_sync_mutex itself we cannot reserve it */
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     /* When creating os_sync_mutex itself (in Unix) we cannot
00884     reserve it */
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     /* When freeing the last mutexes, we have
00957     already freed os_sync_mutex */
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 }