summaryrefslogtreecommitdiff
path: root/storage/innobase/os/os0sync.c
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-07-02 22:08:51 +0200
committerSergei Golubchik <sergii@pisem.net>2011-07-02 22:08:51 +0200
commit9809f05199aeb0b67991fac41bd86f38730768dc (patch)
treefa2792ff86d0da014b535d743759810612338042 /storage/innobase/os/os0sync.c
parent0accbd0364e0333e0b119aa9ce93e34ded9df6cb (diff)
parent5a0e7394a5ae0c7b6a1ea35b7ea3a8985325987a (diff)
downloadmariadb-git-9809f05199aeb0b67991fac41bd86f38730768dc.tar.gz
5.5-merge
Diffstat (limited to 'storage/innobase/os/os0sync.c')
-rw-r--r--storage/innobase/os/os0sync.c211
1 files changed, 184 insertions, 27 deletions
diff --git a/storage/innobase/os/os0sync.c b/storage/innobase/os/os0sync.c
index 3c70e93aae0..41a19843812 100644
--- a/storage/innobase/os/os0sync.c
+++ b/storage/innobase/os/os0sync.c
@@ -72,6 +72,9 @@ UNIV_INTERN ulint os_event_count = 0;
UNIV_INTERN ulint os_mutex_count = 0;
UNIV_INTERN ulint os_fast_mutex_count = 0;
+/* The number of microsecnds in a second. */
+static const ulint MICROSECS_IN_A_SECOND = 1000000;
+
/* Because a mutex is embedded inside an event and there is an
event embedded inside a mutex, on free, this generates a recursive call.
This version of the free event function doesn't acquire the global lock */
@@ -122,6 +125,70 @@ os_cond_init(
}
/*********************************************************//**
+Do a timed wait on condition variable.
+@return TRUE if timed out, FALSE otherwise */
+UNIV_INLINE
+ibool
+os_cond_wait_timed(
+/*===============*/
+ os_cond_t* cond, /*!< in: condition variable. */
+ os_fast_mutex_t* mutex, /*!< in: fast mutex */
+#ifndef __WIN__
+ const struct timespec* abstime /*!< in: timeout */
+#else
+ DWORD time_in_ms /*!< in: timeout in
+ milliseconds*/
+#endif /* !__WIN__ */
+)
+{
+#ifdef __WIN__
+ BOOL ret;
+ DWORD err;
+
+ ut_a(sleep_condition_variable != NULL);
+
+ ret = sleep_condition_variable(cond, mutex, time_in_ms);
+
+ if (!ret) {
+ err = GetLastError();
+ /* From http://msdn.microsoft.com/en-us/library/ms686301%28VS.85%29.aspx,
+ "Condition variables are subject to spurious wakeups
+ (those not associated with an explicit wake) and stolen wakeups
+ (another thread manages to run before the woken thread)."
+ Check for both types of timeouts.
+ Conditions are checked by the caller.*/
+ if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
+ return(TRUE);
+ }
+ }
+
+ ut_a(ret);
+
+ return(FALSE);
+#else
+ int ret;
+
+ ret = pthread_cond_timedwait(cond, mutex, abstime);
+
+ switch (ret) {
+ case 0:
+ case ETIMEDOUT:
+ /* We play it safe by checking for EINTR even though
+ according to the POSIX documentation it can't return EINTR. */
+ case EINTR:
+ break;
+
+ default:
+ fprintf(stderr, " InnoDB: pthread_cond_timedwait() returned: "
+ "%d: abstime={%lu,%lu}\n",
+ ret, (ulong) abstime->tv_sec, (ulong) abstime->tv_nsec);
+ ut_error;
+ }
+
+ return(ret == ETIMEDOUT);
+#endif
+}
+/*********************************************************//**
Wait on condition variable */
UNIV_INLINE
void
@@ -491,10 +558,7 @@ os_event_free(
}
/**********************************************************//**
-Waits for an event object until it is in the signaled state. If
-srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
-waiting thread when the event becomes signaled (or immediately if the
-event is already in the signaled state).
+Waits for an event object until it is in the signaled state.
Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE.
@@ -519,8 +583,6 @@ os_event_wait_low(
returned by previous call of
os_event_reset(). */
{
- ib_int64_t old_signal_count;
-
#ifdef __WIN__
if(!srv_use_native_conditions) {
DWORD err;
@@ -533,43 +595,138 @@ os_event_wait_low(
err = WaitForSingleObject(event->handle, INFINITE);
ut_a(err == WAIT_OBJECT_0);
-
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
return;
}
#endif
- os_fast_mutex_lock(&(event->os_mutex));
+ os_fast_mutex_lock(&event->os_mutex);
+
+ if (!reset_sig_count) {
+ reset_sig_count = event->signal_count;
+ }
+
+ while (!event->is_set && event->signal_count == reset_sig_count) {
+ os_cond_wait(&(event->cond_var), &(event->os_mutex));
- if (reset_sig_count) {
- old_signal_count = reset_sig_count;
+ /* Solaris manual said that spurious wakeups may occur: we
+ have to check if the event really has been signaled after
+ we came here to wait */
+ }
+
+ os_fast_mutex_unlock(&event->os_mutex);
+}
+
+/**********************************************************//**
+Waits for an event object until it is in the signaled state or
+a timeout is exceeded.
+@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+UNIV_INTERN
+ulint
+os_event_wait_time_low(
+/*===================*/
+ os_event_t event, /*!< in: event to wait */
+ ulint time_in_usec, /*!< in: timeout in
+ microseconds, or
+ OS_SYNC_INFINITE_TIME */
+ ib_int64_t reset_sig_count) /*!< in: zero or the value
+ returned by previous call of
+ os_event_reset(). */
+
+{
+ ibool timed_out = FALSE;
+
+#ifdef __WIN__
+ DWORD time_in_ms;
+
+ if (!srv_use_native_conditions) {
+ DWORD err;
+
+ ut_a(event);
+
+ if (time_in_usec != OS_SYNC_INFINITE_TIME) {
+ time_in_ms = time_in_usec / 1000;
+ err = WaitForSingleObject(event->handle, time_in_ms);
+ } else {
+ err = WaitForSingleObject(event->handle, INFINITE);
+ }
+
+ if (err == WAIT_OBJECT_0) {
+ return(0);
+ } else if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
+ return(OS_SYNC_TIME_EXCEEDED);
+ }
+
+ ut_error;
+ /* Dummy value to eliminate compiler warning. */
+ return(42);
} else {
- old_signal_count = event->signal_count;
+ ut_a(sleep_condition_variable != NULL);
+
+ if (time_in_usec != OS_SYNC_INFINITE_TIME) {
+ time_in_ms = time_in_usec / 1000;
+ } else {
+ time_in_ms = INFINITE;
+ }
}
+#else
+ struct timespec abstime;
- for (;;) {
- if (event->is_set == TRUE
- || event->signal_count != old_signal_count) {
+ if (time_in_usec != OS_SYNC_INFINITE_TIME) {
+ struct timeval tv;
+ int ret;
+ ulint sec;
+ ulint usec;
- os_fast_mutex_unlock(&(event->os_mutex));
+ ret = ut_usectime(&sec, &usec);
+ ut_a(ret == 0);
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
- os_thread_exit(NULL);
- }
- /* Ok, we may return */
+ tv.tv_usec += time_in_usec;
- return;
+ if ((ulint) tv.tv_usec >= MICROSECS_IN_A_SECOND) {
+ tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
+ tv.tv_usec %= MICROSECS_IN_A_SECOND;
}
- os_cond_wait(&(event->cond_var), &(event->os_mutex));
+ abstime.tv_sec = tv.tv_sec;
+ abstime.tv_nsec = tv.tv_usec * 1000;
+ } else {
+ abstime.tv_nsec = 999999999;
+ abstime.tv_sec = (time_t) ULINT_MAX;
+ }
- /* Solaris manual said that spurious wakeups may occur: we
- have to check if the event really has been signaled after
- we came here to wait */
+ ut_a(abstime.tv_nsec <= 999999999);
+
+#endif /* __WIN__ */
+
+ os_fast_mutex_lock(&event->os_mutex);
+
+ if (!reset_sig_count) {
+ reset_sig_count = event->signal_count;
}
+
+ do {
+ if (event->is_set || event->signal_count != reset_sig_count) {
+
+ break;
+ }
+
+ timed_out = os_cond_wait_timed(
+ &event->cond_var, &event->os_mutex,
+#ifndef __WIN__
+ &abstime
+#else
+ time_in_ms
+#endif /* !__WIN__ */
+ );
+
+ } while (!timed_out);
+
+ os_fast_mutex_unlock(&event->os_mutex);
+
+ return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
}
/*********************************************************//**