void vtimer_remove(vtimer_t *t) { unsigned irq_state = disableIRQ(); priority_queue_remove(&shortterm_priority_queue_root, timer_get_node(t)); priority_queue_remove(&longterm_priority_queue_root, timer_get_node(t)); update_shortterm(); restoreIRQ(irq_state); }
void condition_variable::wait(unique_lock<mutex>& lock) noexcept { #ifdef NOEXCEPTIONS lock.owns_lock(); #else if (!lock.owns_lock()) { throw std::system_error( std::make_error_code(std::errc::operation_not_permitted), "Mutex not locked."); } #endif priority_queue_node_t n; 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 = disableIRQ(); priority_queue_add(&m_queue, &n); restoreIRQ(old_state); mutex_unlock_and_sleep(lock.mutex()->native_handle()); 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 = disableIRQ(); priority_queue_remove(&m_queue, &n); restoreIRQ(old_state); } mutex_lock(lock.mutex()->native_handle()); }
int pthread_cond_wait(struct pthread_cond_t *cond, struct mutex_t *mutex) { priority_queue_node_t n; n.priority = sched_active_thread->priority; n.data = sched_active_thread->pid; n.next = NULL; /* the signaling thread may not hold the mutex, the queue is not thread safe */ unsigned old_state = disableIRQ(); priority_queue_add(&(cond->queue), &n); restoreIRQ(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 = disableIRQ(); priority_queue_remove(&(cond->queue), &n); restoreIRQ(old_state); } mutex_lock(mutex); return 0; }
static int pthread_rwlock_lock(pthread_rwlock_t *rwlock, bool (*is_blocked)(const pthread_rwlock_t *rwlock), bool is_writer, int incr_when_held, bool allow_spurious) { if (rwlock == NULL) { DEBUG("Thread %" PRIkernel_pid": pthread_rwlock_%s(): is_writer=%u, allow_spurious=%u %s\n", thread_getpid(), "lock", is_writer, allow_spurious, "rwlock=NULL"); return EINVAL; } mutex_lock(&rwlock->mutex); if (!is_blocked(rwlock)) { DEBUG("Thread %" PRIkernel_pid ": pthread_rwlock_%s(): is_writer=%u, allow_spurious=%u %s\n", thread_getpid(), "lock", is_writer, allow_spurious, "is open"); rwlock->readers += incr_when_held; } else { DEBUG("Thread %" PRIkernel_pid ": pthread_rwlock_%s(): is_writer=%u, allow_spurious=%u %s\n", thread_getpid(), "lock", is_writer, allow_spurious, "is locked"); /* queue for the lock */ __pthread_rwlock_waiter_node_t waiting_node = { .is_writer = is_writer, .thread = (thread_t *) sched_active_thread, .qnode = { .next = NULL, .data = (uintptr_t) &waiting_node, .priority = sched_active_thread->priority, }, .continue_ = false, }; priority_queue_add(&rwlock->queue, &waiting_node.qnode); while (1) { /* wait to be unlocked, so this thread can try to acquire the lock again */ mutex_unlock_and_sleep(&rwlock->mutex); mutex_lock(&rwlock->mutex); if (waiting_node.continue_) { /* pthread_rwlock_unlock() already set rwlock->readers */ DEBUG("Thread %" PRIkernel_pid ": pthread_rwlock_%s(): is_writer=%u, allow_spurious=%u %s\n", thread_getpid(), "lock", is_writer, allow_spurious, "continued"); break; } else if (allow_spurious) { DEBUG("Thread %" PRIkernel_pid ": pthread_rwlock_%s(): is_writer=%u, allow_spurious=%u %s\n", thread_getpid(), "lock", is_writer, allow_spurious, "is timed out"); priority_queue_remove(&rwlock->queue, &waiting_node.qnode); mutex_unlock(&rwlock->mutex); return ETIMEDOUT; } } } mutex_unlock(&rwlock->mutex); return 0; }
static int set_longterm(vtimer_t *timer) { timer->priority_queue_entry.priority = timer->absolute.seconds; /* *** UGLY FIX BEGINS *** */ /* Workaround for a bug in a so far undiscovered location which causes the * vtimer to add the same timer twice, locking the system in an infinite * loop inside priority_queue_add. */ priority_queue_remove(&longterm_priority_queue_root, timer_get_node(timer)); /* *** UGLY FIX ENDS *** */ priority_queue_add(&longterm_priority_queue_root, timer_get_node(timer)); return 0; }
static int set_shortterm(vtimer_t *timer) { DEBUG("set_shortterm(): Absolute: %" PRIu32 " %" PRIu32 "\n", timer->absolute.seconds, timer->absolute.microseconds); timer->priority_queue_entry.priority = timer->absolute.microseconds; /* *** UGLY FIX BEGINS *** */ /* Workaround for a bug in a so far undiscovered location which causes the * vtimer to add the same timer twice, locking the system in an infinite * loop inside priority_queue_add. */ priority_queue_remove(&shortterm_priority_queue_root, timer_get_node(timer)); /* *** UGLY FIX ENDS *** */ priority_queue_add(&shortterm_priority_queue_root, timer_get_node(timer)); return 1; }