{
suspend(self);
if (THREAD_GETMEM(self, p_condvar_avail) == 0
- && THREAD_GETMEM(self, p_woken_by_cancel) == 0)
+ && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+ || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
{
/* Count resumes that don't belong to us. */
spurious_wakeup_count++;
}
if (THREAD_GETMEM(self, p_condvar_avail) == 0
- && THREAD_GETMEM(self, p_woken_by_cancel) == 0)
+ && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+ || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
{
/* Count resumes that don't belong to us. */
spurious_wakeup_count++;
void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif)
{
- __pthread_lock(self->p_lock, self);
+ __pthread_lock(THREAD_GETMEM(self, p_lock), self);
THREAD_SETMEM(self, p_extricate, peif);
- __pthread_unlock(self->p_lock);
+ __pthread_unlock(THREAD_GETMEM (self, p_lock));
}
/* Primitives for controlling thread execution */
sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
+ THREAD_SETMEM(self, p_signal, 0);
do {
- self->p_signal = 0;
sigsuspend(&mask); /* Wait for signal */
- } while (self->p_signal !=__pthread_sig_restart );
+ } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
}
#if !__ASSUME_REALTIME_SIGNALS
volatile pthread_descr self = thread_self();
pthread_extricate_if extr;
int already_canceled = 0;
+ int spurious_wakeup_count;
/* Set up extrication interface */
extr.pu_object = sem;
return 0;
}
/* Register extrication interface */
+ THREAD_SETMEM(self, p_sem_avail, 0);
__pthread_set_own_extricate_if(self, &extr);
/* Enqueue only if not already cancelled. */
if (!(THREAD_GETMEM(self, p_canceled)
}
/* Wait for sem_post or cancellation, or fall through if already canceled */
- suspend(self);
+ spurious_wakeup_count = 0;
+ while (1)
+ {
+ suspend(self);
+ if (THREAD_GETMEM(self, p_sem_avail) == 0
+ && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+ || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+ {
+ /* Count resumes that don't belong to us. */
+ spurious_wakeup_count++;
+ continue;
+ }
+ break;
+ }
__pthread_set_own_extricate_if(self, 0);
/* Terminate only if the wakeup came from cancellation. */
} else {
th = dequeue(&sem->__sem_waiting);
__pthread_unlock((struct _pthread_fastlock *) &sem->__sem_lock);
+ th->p_sem_avail = 1;
+ WRITE_MEMORY_BARRIER();
restart(th);
}
} else {
pthread_descr self = thread_self();
pthread_extricate_if extr;
int already_canceled = 0;
+ int spurious_wakeup_count;
__pthread_lock((struct _pthread_fastlock *) &sem->__sem_lock, self);
if (sem->__sem_value > 0) {
extr.pu_extricate_func = new_sem_extricate_func;
/* Register extrication interface */
+ THREAD_SETMEM(self, p_sem_avail, 0);
__pthread_set_own_extricate_if(self, &extr);
/* Enqueue only if not already cancelled. */
if (!(THREAD_GETMEM(self, p_canceled)
pthread_exit(PTHREAD_CANCELED);
}
- if (timedsuspend(self, abstime) == 0) {
- int was_on_queue;
+ spurious_wakeup_count = 0;
+ while (1)
+ {
+ if (timedsuspend(self, abstime) == 0) {
+ int was_on_queue;
+
+ /* __pthread_lock will queue back any spurious restarts that
+ may happen to it. */
- /* __pthread_lock will queue back any spurious restarts that
- may happen to it. */
+ __pthread_lock((struct _pthread_fastlock *)&sem->__sem_lock, self);
+ was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
+ __pthread_unlock((struct _pthread_fastlock *)&sem->__sem_lock);
- __pthread_lock((struct _pthread_fastlock *)&sem->__sem_lock, self);
- was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
- __pthread_unlock((struct _pthread_fastlock *)&sem->__sem_lock);
+ if (was_on_queue) {
+ __pthread_set_own_extricate_if(self, 0);
+ return ETIMEDOUT;
+ }
- if (was_on_queue) {
- __pthread_set_own_extricate_if(self, 0);
- return ETIMEDOUT;
+ /* Eat the outstanding restart() from the signaller */
+ suspend(self);
+ }
+
+ if (THREAD_GETMEM(self, p_sem_avail) == 0
+ && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+ || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+ {
+ /* Count resumes that don't belong to us. */
+ spurious_wakeup_count++;
+ continue;
+ }
+ break;
}
- /* Eat the outstanding restart() from the signaller */
- suspend(self);
- }
__pthread_set_own_extricate_if(self, 0);
/* Terminate only if the wakeup came from cancellation. */