76
72
UNIV_INTERN ulint os_mutex_count = 0;
77
73
UNIV_INTERN ulint os_fast_mutex_count = 0;
79
/* The number of microsecnds in a second. */
80
static const ulint MICROSECS_IN_A_SECOND = 1000000;
82
75
/* Because a mutex is embedded inside an event and there is an
83
76
event embedded inside a mutex, on free, this generates a recursive call.
84
77
This version of the free event function doesn't acquire the global lock */
85
78
static void os_event_free_internal(os_event_t event);
87
/* On Windows (Vista and later), load function pointers for condition
88
variable handling. Those functions are not available in prior versions,
89
so we have to use them via runtime loading, as long as we support XP. */
90
static void os_cond_module_init(void);
93
/* Prototypes and function pointers for condition variable functions */
94
typedef VOID (WINAPI* InitializeConditionVariableProc)
95
(PCONDITION_VARIABLE ConditionVariable);
96
static InitializeConditionVariableProc initialize_condition_variable;
98
typedef BOOL (WINAPI* SleepConditionVariableCSProc)
99
(PCONDITION_VARIABLE ConditionVariable,
100
PCRITICAL_SECTION CriticalSection,
101
DWORD dwMilliseconds);
102
static SleepConditionVariableCSProc sleep_condition_variable;
104
typedef VOID (WINAPI* WakeAllConditionVariableProc)
105
(PCONDITION_VARIABLE ConditionVariable);
106
static WakeAllConditionVariableProc wake_all_condition_variable;
108
typedef VOID (WINAPI* WakeConditionVariableProc)
109
(PCONDITION_VARIABLE ConditionVariable);
110
static WakeConditionVariableProc wake_condition_variable;
113
/*********************************************************//**
114
Initialitze condition variable */
119
os_cond_t* cond) /*!< in: condition variable. */
124
ut_a(initialize_condition_variable != NULL);
125
initialize_condition_variable(cond);
127
ut_a(pthread_cond_init(cond, NULL) == 0);
131
/*********************************************************//**
132
Do a timed wait on condition variable.
133
@return TRUE if timed out, FALSE otherwise */
138
os_cond_t* cond, /*!< in: condition variable. */
139
os_fast_mutex_t* mutex, /*!< in: fast mutex */
141
const struct timespec* abstime /*!< in: timeout */
143
DWORD time_in_ms /*!< in: timeout in
145
#endif /* !__WIN__ */
152
ut_a(sleep_condition_variable != NULL);
154
ret = sleep_condition_variable(cond, mutex, time_in_ms);
157
err = GetLastError();
158
/* From http://msdn.microsoft.com/en-us/library/ms686301%28VS.85%29.aspx,
159
"Condition variables are subject to spurious wakeups
160
(those not associated with an explicit wake) and stolen wakeups
161
(another thread manages to run before the woken thread)."
162
Check for both types of timeouts.
163
Conditions are checked by the caller.*/
164
if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
175
ret = pthread_cond_timedwait(cond, mutex, abstime);
180
/* We play it safe by checking for EINTR even though
181
according to the POSIX documentation it can't return EINTR. */
186
fprintf(stderr, " InnoDB: pthread_cond_timedwait() returned: "
187
"%d: abstime={%lu,%lu}\n",
188
ret, (ulong) abstime->tv_sec, (ulong) abstime->tv_nsec);
192
return(ret == ETIMEDOUT);
195
/*********************************************************//**
196
Wait on condition variable */
201
os_cond_t* cond, /*!< in: condition variable. */
202
os_fast_mutex_t* mutex) /*!< in: fast mutex */
208
ut_a(sleep_condition_variable != NULL);
209
ut_a(sleep_condition_variable(cond, mutex, INFINITE));
211
ut_a(pthread_cond_wait(cond, mutex) == 0);
215
/*********************************************************//**
216
Wakes all threads waiting for condition variable */
221
os_cond_t* cond) /*!< in: condition variable. */
226
ut_a(wake_all_condition_variable != NULL);
227
wake_all_condition_variable(cond);
229
ut_a(pthread_cond_broadcast(cond) == 0);
233
/*********************************************************//**
234
Wakes one thread waiting for condition variable */
239
os_cond_t* cond) /*!< in: condition variable. */
244
ut_a(wake_condition_variable != NULL);
245
wake_condition_variable(cond);
247
ut_a(pthread_cond_signal(cond) == 0);
251
/*********************************************************//**
252
Destroys condition variable */
257
os_cond_t* cond) /*!< in: condition variable. */
262
ut_a(pthread_cond_destroy(cond) == 0);
266
/*********************************************************//**
267
On Windows (Vista and later), load function pointers for condition variable
268
handling. Those functions are not available in prior versions, so we have to
269
use them via runtime loading, as long as we support XP. */
272
os_cond_module_init(void)
273
/*=====================*/
278
if (!srv_use_native_conditions)
281
h_dll = GetModuleHandle("kernel32");
283
initialize_condition_variable = (InitializeConditionVariableProc)
284
GetProcAddress(h_dll, "InitializeConditionVariable");
285
sleep_condition_variable = (SleepConditionVariableCSProc)
286
GetProcAddress(h_dll, "SleepConditionVariableCS");
287
wake_all_condition_variable = (WakeAllConditionVariableProc)
288
GetProcAddress(h_dll, "WakeAllConditionVariable");
289
wake_condition_variable = (WakeConditionVariableProc)
290
GetProcAddress(h_dll, "WakeConditionVariable");
292
/* When using native condition variables, check function pointers */
293
ut_a(initialize_condition_variable);
294
ut_a(sleep_condition_variable);
295
ut_a(wake_all_condition_variable);
296
ut_a(wake_condition_variable);
300
80
/*********************************************************//**
301
81
Initializes global event and OS 'slow' mutex lists. */
367
141
const char* name) /*!< in: the name of the event, if NULL
368
142
the event is created without a name */
373
if(!srv_use_native_conditions) {
375
event = ut_malloc(sizeof(struct os_event_struct));
377
event->handle = CreateEvent(NULL,
381
if (!event->handle) {
383
"InnoDB: Could not create a Windows event"
384
" semaphore; Windows error %lu\n",
385
(ulong) GetLastError());
387
} else /* Windows with condition variables */
393
event = static_cast<os_event_struct*>(ut_malloc(sizeof(struct os_event_struct)));
395
os_fast_mutex_init(&(event->os_mutex));
397
os_cond_init(&(event->cond_var));
399
event->is_set = FALSE;
401
/* We return this value in os_event_reset(), which can then be
402
be used to pass to the os_event_wait_low(). The value of zero
403
is reserved in os_event_wait_low() for the case when the
404
caller does not want to pass any signal_count value. To
405
distinguish between the two cases we initialize signal_count
407
event->signal_count = 1;
147
event = ut_malloc(sizeof(struct os_event_struct));
149
event->handle = CreateEvent(NULL, /* No security attributes */
150
TRUE, /* Manual reset */
151
FALSE, /* Initial state nonsignaled */
153
if (!event->handle) {
155
"InnoDB: Could not create a Windows event semaphore;"
156
" Windows error %lu\n",
157
(ulong) GetLastError());
164
event = ut_malloc(sizeof(struct os_event_struct));
166
os_fast_mutex_init(&(event->os_mutex));
168
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
170
event->is_set = FALSE;
172
/* We return this value in os_event_reset(), which can then be
173
be used to pass to the os_event_wait_low(). The value of zero
174
is reserved in os_event_wait_low() for the case when the
175
caller does not want to pass any signal_count value. To
176
distinguish between the two cases we initialize signal_count
178
event->signal_count = 1;
410
181
/* The os_sync_mutex can be NULL because during startup an event
411
182
can be created [ because it's embedded in the mutex/rwlock ] before
638
os_cond_wait(&(event->cond_var), &(event->os_mutex));
397
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
640
399
/* Solaris manual said that spurious wakeups may occur: we
641
400
have to check if the event really has been signaled after
642
401
we came here to wait */
646
406
/**********************************************************//**
647
407
Waits for an event object until it is in the signaled state or
648
a timeout is exceeded.
408
a timeout is exceeded. In Unix the timeout is always infinite.
649
409
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
652
os_event_wait_time_low(
414
os_event_t event, /*!< in: event to wait */
415
ulint time) /*!< in: timeout in microseconds, or
416
OS_SYNC_INFINITE_TIME */
423
if (time != OS_SYNC_INFINITE_TIME) {
424
err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
426
err = WaitForSingleObject(event->handle, INFINITE);
429
if (err == WAIT_OBJECT_0) {
432
} else if (err == WAIT_TIMEOUT) {
434
return(OS_SYNC_TIME_EXCEEDED);
437
return(1000000); /* dummy value to eliminate compiler warn. */
442
/* In Posix this is just an ordinary, infinite wait */
444
os_event_wait(event);
451
/**********************************************************//**
452
Waits for any event in an OS native event array. Returns if even a single
453
one is signaled or becomes signaled.
454
@return index of the event which was signaled */
457
os_event_wait_multiple(
653
458
/*===================*/
654
os_event_t event, /*!< in: event to wait */
655
ulint time_in_usec, /*!< in: timeout in
657
OS_SYNC_INFINITE_TIME */
658
ib_int64_t reset_sig_count) /*!< in: zero or the value
659
returned by previous call of
459
ulint n, /*!< in: number of events in the
461
os_native_event_t* native_event_array)
462
/*!< in: pointer to an array of event
663
ibool timed_out = FALSE;
664
ib_int64_t old_signal_count;
669
if (!srv_use_native_conditions) {
674
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
675
time_in_ms = time_in_usec / 1000;
676
err = WaitForSingleObject(event->handle, time_in_ms);
678
err = WaitForSingleObject(event->handle, INFINITE);
681
if (err == WAIT_OBJECT_0) {
683
} else if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
684
return(OS_SYNC_TIME_EXCEEDED);
688
/* Dummy value to eliminate compiler warning. */
691
ut_a(sleep_condition_variable != NULL);
693
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
694
time_in_ms = time_in_usec / 1000;
696
time_in_ms = INFINITE;
700
struct timespec abstime;
702
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
708
ret = ut_usectime(&sec, &usec);
714
tv.tv_usec += time_in_usec;
716
if ((ulint) tv.tv_usec >= MICROSECS_IN_A_SECOND) {
717
tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
718
tv.tv_usec %= MICROSECS_IN_A_SECOND;
721
abstime.tv_sec = tv.tv_sec;
722
abstime.tv_nsec = tv.tv_usec * 1000;
724
abstime.tv_nsec = 999999999;
725
abstime.tv_sec = (time_t) ULINT_MAX;
728
ut_a(abstime.tv_nsec <= 999999999);
732
os_fast_mutex_lock(&event->os_mutex);
734
if (reset_sig_count) {
735
old_signal_count = reset_sig_count;
737
old_signal_count = event->signal_count;
741
if (event->is_set == TRUE
742
|| event->signal_count != old_signal_count) {
747
timed_out = os_cond_wait_timed(
748
&event->cond_var, &event->os_mutex,
753
#endif /* !__WIN__ */
756
} while (!timed_out);
758
os_fast_mutex_unlock(&event->os_mutex);
467
ut_a(native_event_array);
470
index = WaitForMultipleObjects((DWORD) n, native_event_array,
471
FALSE, /* Wait for any 1 event */
472
INFINITE); /* Infinite wait time
474
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparison */
475
ut_a(index < WAIT_OBJECT_0 + n);
760
477
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
762
478
os_thread_exit(NULL);
765
return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
481
return(index - WAIT_OBJECT_0);
768
485
/*********************************************************//**
769
486
Creates an operating system mutex semaphore. Because these are slow, the