static bool lock_record_wait(threadobject *thread, lock_record_t *lr, s8 millis, s4 nanos)
{
s4 lockcount;
- bool wasinterrupted;
+ bool wasinterrupted = false;
DEBUGLOCKS(("[lock_record_wait : lr=%p, t=%p, millis=%lld, nanos=%d]",
lr, thread, millis, nanos));
/* wait until notified/interrupted/timed out */
- wasinterrupted = threads_wait_with_timeout_relative(thread, millis, nanos);
+ threads_wait_with_timeout_relative(thread, millis, nanos);
/* re-enter the monitor */
lr->count = lockcount;
+ /* We can only be signaled OR interrupted, not both. If both flags
+ are set, reset only signaled and leave the thread in
+ interrupted state. Otherwise, clear both. */
+
+ if (!thread->signaled) {
+ wasinterrupted = thread->interrupted;
+ thread->interrupted = false;
+ }
+
+ thread->signaled = false;
+
/* return if we have been interrupted */
return wasinterrupted;
waitingthread = w->thread;
- /* If the thread was already signaled but hasn't removed
- itself from the list yet, just ignore it. */
+ /* We must skip threads which have already been notified or
+ interrupted. They will remove themselves from the list. */
- if (waitingthread->signaled == true)
+ if (waitingthread->signaled || waitingthread->interrupted)
continue;
/* Enter the wait-mutex. */
DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, sleeping=%d, one=%d]",
lr, t, waitingthread, waitingthread->sleeping, one));
- /* Signal the thread if it's sleeping. */
+ /* Signal the thread if it's sleeping. sleeping can be false
+ when the waiting thread is blocked between giving up the
+ monitor and entering the waitmutex. It will eventually
+ observe that it's signaled and refrain from going to
+ sleep. */
if (waitingthread->sleeping)
pthread_cond_signal(&(waitingthread->waitcond));
If both tv_sec and tv_nsec are zero, this function
waits for an unlimited amount of time.
- RETURN VALUE:
- true.........if the wait has been interrupted,
- false........if the wait was ended by notification or timeout
-
*******************************************************************************/
-static bool threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
+static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
{
- bool wasinterrupted;
-
/* acquire the waitmutex */
pthread_mutex_lock(&t->waitmutex);
}
}
- /* check if we were interrupted */
-
- wasinterrupted = t->interrupted;
-
- /* reset all flags */
-
- t->interrupted = false;
- t->signaled = false;
t->sleeping = false;
/* release the waitmutex */
pthread_mutex_unlock(&t->waitmutex);
-
- return wasinterrupted;
}
millis.......milliseconds to wait
nanos........nanoseconds to wait
- RETURN VALUE:
- true.........if the wait has been interrupted,
- false........if the wait was ended by notification or timeout
-
*******************************************************************************/
-bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
+void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
s4 nanos)
{
struct timespec wakeupTime;
/* wait */
- return threads_wait_with_timeout(thread, &wakeupTime);
+ threads_wait_with_timeout(thread, &wakeupTime);
}
thread = THREADOBJECT;
+ pthread_mutex_lock(&thread->waitmutex);
+
/* get interrupted flag */
intr = thread->interrupted;
thread->interrupted = false;
+ pthread_mutex_unlock(&thread->waitmutex);
+
return intr;
}
threads_calc_absolute_time(&wakeupTime, millis, nanos);
- wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
+ threads_wait_with_timeout(thread, &wakeupTime);
+
+ wasinterrupted = threads_check_if_interrupted_and_reset();
if (wasinterrupted)
exceptions_throw_interruptedexception();
void threads_sleep(s8 millis, s4 nanos);
-bool threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
+void threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
void threads_thread_interrupt(threadobject *thread);
bool threads_check_if_interrupted_and_reset(void);