Skip to content

Commit

Permalink
Merge pull request RIOT-OS#7216 from smlng/posix/pthread/cond_wait
Browse files Browse the repository at this point in the history
Posix: fix pthread_cond_wait and timedwait
  • Loading branch information
aabadie authored Jun 24, 2017
2 parents b75479c + d2fd406 commit e2cce62
Showing 1 changed file with 45 additions and 19 deletions.
64 changes: 45 additions & 19 deletions sys/posix/pthread/pthread_cond.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*
* @}
*/
#include <errno.h>

#include "pthread_cond.h"
#include "thread.h"
Expand Down Expand Up @@ -92,44 +93,69 @@ int pthread_cond_destroy(pthread_cond_t *cond)
return 0;
}

int pthread_cond_wait(pthread_cond_t *cond, mutex_t *mutex)
void _init_cond_wait(pthread_cond_t *cond, priority_queue_node_t *n)
{
priority_queue_node_t n;
n.priority = sched_active_thread->priority;
n.data = sched_active_pid;
n.next = NULL;
n->priority = sched_active_thread->priority;
n->data = sched_active_pid;
n->next = NULL;

/* the signaling thread may not hold the mutex, the queue is not thread safe */
unsigned old_state = irq_disable();
priority_queue_add(&(cond->queue), &n);
priority_queue_add(&(cond->queue), n);
irq_restore(old_state);
}

mutex_unlock_and_sleep(mutex);

if (n.data != -1u) {
/* on signaling n.data is set to -1u */
/* if it isn't set, then the wakeup is either spurious or a timer wakeup */
old_state = irq_disable();
priority_queue_remove(&(cond->queue), &n);
irq_restore(old_state);
int pthread_cond_wait(pthread_cond_t *cond, mutex_t *mutex)
{
if (cond == NULL) {
return EINVAL;
}
priority_queue_node_t n;
_init_cond_wait(cond, &n);

mutex_unlock_and_sleep(mutex);

mutex_lock(mutex);

return 0;
}

int pthread_cond_timedwait(pthread_cond_t *cond, mutex_t *mutex, const struct timespec *abstime)
{
if ((cond == NULL) || (abstime->tv_sec < 0)) {
return EINVAL;
}

uint64_t now = xtimer_now_usec64();
uint64_t then = ((uint64_t)abstime->tv_sec * US_PER_SEC) +
(abstime->tv_nsec / NS_PER_US);

xtimer_t timer;
xtimer_set_wakeup64(&timer, (then - now) , sched_active_pid);
int result = pthread_cond_wait(cond, mutex);
xtimer_remove(&timer);
int ret = 0;
if (then > now) {
xtimer_t timer;
priority_queue_node_t n;

_init_cond_wait(cond, &n);
xtimer_set_wakeup64(&timer, (then - now), sched_active_pid);

mutex_unlock_and_sleep(mutex);

return result;
if (n.data != -1u) {
/* on signaling n.data is set to -1u */
/* if it isn't set, then the wakeup is either spurious or a timer wakeup */
unsigned old_state = irq_disable();
priority_queue_remove(&(cond->queue), &n);
irq_restore(old_state);
ret = ETIMEDOUT;
}
xtimer_remove(&timer);
}
else {
mutex_unlock(mutex);
ret = ETIMEDOUT;
}
mutex_lock(mutex);
return ret;
}

int pthread_cond_signal(pthread_cond_t *cond)
Expand Down

0 comments on commit e2cce62

Please sign in to comment.