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
144
const char* name) /*!< in: the name of the event, if NULL
368
145
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;
150
event = ut_malloc(sizeof(struct os_event_struct));
152
event->handle = CreateEvent(NULL, /* No security attributes */
153
TRUE, /* Manual reset */
154
FALSE, /* Initial state nonsignaled */
156
if (!event->handle) {
158
"InnoDB: Could not create a Windows event semaphore;"
159
" Windows error %lu\n",
160
(ulong) GetLastError());
167
event = ut_malloc(sizeof(struct os_event_struct));
169
os_fast_mutex_init(&(event->os_mutex));
171
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
173
event->is_set = FALSE;
175
/* We return this value in os_event_reset(), which can then be
176
be used to pass to the os_event_wait_low(). The value of zero
177
is reserved in os_event_wait_low() for the case when the
178
caller does not want to pass any signal_count value. To
179
distinguish between the two cases we initialize signal_count
181
event->signal_count = 1;
410
184
/* The os_sync_mutex can be NULL because during startup an event
411
185
can be created [ because it's embedded in the mutex/rwlock ] before
638
os_cond_wait(&(event->cond_var), &(event->os_mutex));
400
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
640
402
/* Solaris manual said that spurious wakeups may occur: we
641
403
have to check if the event really has been signaled after
642
404
we came here to wait */
646
409
/**********************************************************//**
647
410
Waits for an event object until it is in the signaled state or
648
a timeout is exceeded.
411
a timeout is exceeded. In Unix the timeout is always infinite.
649
412
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
652
os_event_wait_time_low(
417
os_event_t event, /*!< in: event to wait */
418
ulint time) /*!< in: timeout in microseconds, or
419
OS_SYNC_INFINITE_TIME */
426
if (time != OS_SYNC_INFINITE_TIME) {
427
err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
429
err = WaitForSingleObject(event->handle, INFINITE);
432
if (err == WAIT_OBJECT_0) {
435
} else if (err == WAIT_TIMEOUT) {
437
return(OS_SYNC_TIME_EXCEEDED);
440
return(1000000); /* dummy value to eliminate compiler warn. */
445
/* In Posix this is just an ordinary, infinite wait */
447
os_event_wait(event);
454
/**********************************************************//**
455
Waits for any event in an OS native event array. Returns if even a single
456
one is signaled or becomes signaled.
457
@return index of the event which was signaled */
460
os_event_wait_multiple(
653
461
/*===================*/
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
462
ulint n, /*!< in: number of events in the
464
os_native_event_t* native_event_array)
465
/*!< 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);
470
ut_a(native_event_array);
473
index = WaitForMultipleObjects((DWORD) n, native_event_array,
474
FALSE, /* Wait for any 1 event */
475
INFINITE); /* Infinite wait time
477
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparison */
478
ut_a(index < WAIT_OBJECT_0 + n);
760
480
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
762
481
os_thread_exit(NULL);
765
return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
484
return(index - WAIT_OBJECT_0);
768
488
/*********************************************************//**
769
489
Creates an operating system mutex semaphore. Because these are slow, the