locks: unix: timedlock: better handling of spurious wakeups that may be
inherent to some native/OS condvar implementation.
@@ -701,29 +701,33 @@ static apr_status_t proc_mutex_pthread_acquire_ex(apr_proc_mutex_t *mutex,
}
if (!proc_pthread_mutex_cond_locked(mutex)) {
- proc_pthread_mutex_cond_locked(mutex) = 1;
+ rv = APR_SUCCESS;
}
else if (!timeout) {
rv = APR_TIMEUP;
}
else {
+ struct timespec abstime;
+
+ if (timeout > 0) {
+ timeout += apr_time_now();
+ abstime.tv_sec = apr_time_sec(timeout);
+ abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
+ }
+
proc_pthread_mutex_cond_num_waiters(mutex)++;
+ do {
if (timeout < 0) {
rv = pthread_cond_wait(&proc_pthread_mutex_cond(mutex),
&proc_pthread_mutex(mutex));
-#ifdef HAVE_ZOS_PTHREADS
if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
rv = errno;
- }
#endif
+ break;
+ }
}
else {
- struct timespec abstime;
-
- timeout += apr_time_now();
- abstime.tv_sec = apr_time_sec(timeout);
- abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
-
rv = pthread_cond_timedwait(&proc_pthread_mutex_cond(mutex),
&proc_pthread_mutex(mutex),
&abstime);
@@ -734,15 +738,19 @@ static apr_status_t proc_mutex_pthread_acquire_ex(apr_proc_mutex_t *mutex,
if (rv == ETIMEDOUT) {
rv = APR_TIMEUP;
}
+ break;
}
}
+ } while (proc_pthread_mutex_cond_locked(mutex));
proc_pthread_mutex_cond_num_waiters(mutex)--;
}
- if (rv) {
+ if (rv != APR_SUCCESS) {
pthread_mutex_unlock(&proc_pthread_mutex(mutex));
return rv;
}
+ proc_pthread_mutex_cond_locked(mutex) = 1;
+
rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex));
if (rv) {
#ifdef HAVE_ZOS_PTHREADS
@@ -853,22 +861,23 @@ static apr_status_t proc_mutex_pthread_release(apr_proc_mutex_t *mutex)
if (!proc_pthread_mutex_cond_locked(mutex)) {
rv = APR_EINVAL;
}
- else if (proc_pthread_mutex_cond_num_waiters(mutex)) {
+ else if (!proc_pthread_mutex_cond_num_waiters(mutex)) {
+ rv = APR_SUCCESS;
+ }
+ else {
rv = pthread_cond_signal(&proc_pthread_mutex_cond(mutex));
- if (rv) {
#ifdef HAVE_ZOS_PTHREADS
+ if (rv) {
rv = errno;
-#endif
- }
}
- else {
- proc_pthread_mutex_cond_locked(mutex) = 0;
- rv = APR_SUCCESS;
+#endif
}
- if (rv) {
+ if (rv != APR_SUCCESS) {
pthread_mutex_unlock(&proc_pthread_mutex(mutex));
return rv;
}
+
+ proc_pthread_mutex_cond_locked(mutex) = 0;
}
#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
