Merge pull request #7216 from smlng/posix/pthread/cond_wait
Posix: fix pthread_cond_wait and timedwait
This commit is contained in:
commit
e2cce62aed
@ -18,6 +18,7 @@
|
|||||||
*
|
*
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "pthread_cond.h"
|
#include "pthread_cond.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
@ -92,44 +93,69 @@ int pthread_cond_destroy(pthread_cond_t *cond)
|
|||||||
return 0;
|
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.priority = sched_active_thread->priority;
|
n->data = sched_active_pid;
|
||||||
n.data = sched_active_pid;
|
n->next = NULL;
|
||||||
n.next = NULL;
|
|
||||||
|
|
||||||
/* the signaling thread may not hold the mutex, the queue is not thread safe */
|
/* the signaling thread may not hold the mutex, the queue is not thread safe */
|
||||||
unsigned old_state = irq_disable();
|
unsigned old_state = irq_disable();
|
||||||
priority_queue_add(&(cond->queue), &n);
|
priority_queue_add(&(cond->queue), n);
|
||||||
irq_restore(old_state);
|
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_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(mutex);
|
mutex_lock(mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_cond_timedwait(pthread_cond_t *cond, mutex_t *mutex, const struct timespec *abstime)
|
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 now = xtimer_now_usec64();
|
||||||
uint64_t then = ((uint64_t)abstime->tv_sec * US_PER_SEC) +
|
uint64_t then = ((uint64_t)abstime->tv_sec * US_PER_SEC) +
|
||||||
(abstime->tv_nsec / NS_PER_US);
|
(abstime->tv_nsec / NS_PER_US);
|
||||||
|
|
||||||
xtimer_t timer;
|
int ret = 0;
|
||||||
xtimer_set_wakeup64(&timer, (then - now) , sched_active_pid);
|
if (then > now) {
|
||||||
int result = pthread_cond_wait(cond, mutex);
|
xtimer_t timer;
|
||||||
xtimer_remove(&timer);
|
priority_queue_node_t n;
|
||||||
|
|
||||||
return result;
|
_init_cond_wait(cond, &n);
|
||||||
|
xtimer_set_wakeup64(&timer, (then - now), sched_active_pid);
|
||||||
|
|
||||||
|
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 */
|
||||||
|
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)
|
int pthread_cond_signal(pthread_cond_t *cond)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user