int pthread_cond_wait(struct pthread_cond_t *cond, struct mutex_t *mutex) { 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(); queue_priority_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(); queue_remove(&(cond->queue), &n); restoreIRQ(old_state); } mutex_lock(mutex); return 0; }
int main(void) { indicator = 0; count = 0; mutex_init(&mutex); thread_create(stack, KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN - 1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "second_thread"); while (1) { mutex_lock(&mutex); thread_wakeup(2); indicator++; count++; if (indicator > 1 || indicator < -1) { //printf("Error, threads did not sleep properly. [indicator: %d]\n", indicator); return -1; } if ((count % 100000) == 0) { //printf("Still alive alternated [count: %dk] times.\n", count / 1000); } mutex_unlock_and_sleep(&mutex); } }
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 main(void) { uint32_t count = 0; indicator = 0; main_pid = thread_getpid(); kernel_pid_t second_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, second_thread, NULL, "second_thread"); while (1) { mutex_lock(&mutex); thread_wakeup(second_pid); indicator++; count++; if ((indicator > 1) || (indicator < -1)) { printf("[ERROR] threads did not sleep properly (%d).\n", indicator); return 1; } if ((count % 100000) == 0) { printf("[ALIVE] alternated %"PRIu32"k times.\n", (count / 1000)); } mutex_unlock_and_sleep(&mutex); } }
int main(void) { indicator = 0; count = 0; main_pid = thread_getpid(); kernel_pid_t second_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, second_thread, NULL, "second_thread"); while (1) { mutex_lock(&mutex); thread_wakeup(second_pid); indicator++; count++; if (indicator > 1 || indicator < -1) { printf("Error, threads did not sleep properly. [indicator: %d]\n", indicator); return -1; } if ((count % 100000) == 0) { printf("Still alive alternated [count: %dk] times.\n", count / 1000); } mutex_unlock_and_sleep(&mutex); } }
static void *run_get(void *arg) { (void) arg; char next = 0; for (unsigned iteration = 0; iteration < ITERATIONS; ++iteration) { ++next; /* the first element of a stride is always overwritten */ mutex_lock(&mutex); for (unsigned i = BUF_SIZE; i > 0; --i) { assert_avail(i); assert_get_one(next); assert_avail(i - 1); ++next; } assert_avail(0); assert_get_one(-1); assert_avail(0); thread_wakeup(pid_add); mutex_unlock_and_sleep(&mutex); } return NULL; }
static void run_add(void) { char next = 0; for (unsigned iteration = 0; iteration < ITERATIONS; ++iteration) { mutex_lock(&mutex); for (unsigned i = 0; i < BUF_SIZE; ++i) { assert_avail(i); assert_add_one(next, -1); assert_avail(i + 1); ++next; } /* Overwrite oldest element. It should be returned to us. */ assert_avail(BUF_SIZE); assert_add_one(next, next - BUF_SIZE); assert_avail(BUF_SIZE); ++next; thread_wakeup(pid_get); mutex_unlock_and_sleep(&mutex); } thread_wakeup(pid_get); }
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 void second_thread(void) { while (1) { mutex_lock(&mutex); thread_wakeup(1); indicator--; mutex_unlock_and_sleep(&mutex); } }
static void *second_thread(void *arg) { (void) arg; while (1) { mutex_lock(&mutex); thread_wakeup(main_pid); indicator--; mutex_unlock_and_sleep(&mutex); } return NULL; }
/** * @brief This thread tries to lock the mutex to enter the critical section. * Then it signals one waiting thread to check the condition and it goes to sleep again * If is_finished is set to 1 second_thread ends */ static void *second_thread(void *arg) { (void) arg; while (1) { mutex_lock(&mutex); if (is_finished == 1) { break; } pthread_cond_signal(&cv); mutex_unlock_and_sleep(&mutex); } return NULL; }
int pthread_barrier_wait(pthread_barrier_t *barrier) { /* Idea: the count is decreased by every thread that waits on the barrier. * If the value is bigger than zero afterwards, then the thread has to wait * to be woken up. Once the value reaches zero, everyone gets woken up. */ mutex_lock(&barrier->mutex); DEBUG("%s: hit a synchronization barrier. pid=%" PRIkernel_pid"\n", sched_active_thread->name, sched_active_pid); int switch_prio = -1; if (--barrier->count > 0) { /* need to wait for further threads */ DEBUG("%s: waiting for %u threads. pid=%" PRIkernel_pid "\n", sched_active_thread->name, barrier->count, sched_active_pid); pthread_barrier_waiting_node_t node; node.pid = sched_active_pid; node.next = barrier->next; node.cont = 0; barrier->next = &node; mutex_unlock(&barrier->mutex); while (1) { /* The mutex is reacquired before checking if we should continue, * so that the waiting thread don't accidentially run before the * wake up loop has ended. Otherwise the thread could run into the * the barrier again before `barrier->count` was reset. */ mutex_lock(&barrier->mutex); if (node.cont) { break; } mutex_unlock_and_sleep(&barrier->mutex); } } else { /* all threads have arrived, wake everybody up */ DEBUG("%s: waking every other thread up. pid=%" PRIkernel_pid "\n", sched_active_thread->name, sched_active_pid); int count = 1; /* Count number of woken up threads. * The first thread is the current thread. */ pthread_barrier_waiting_node_t *next; for (next = barrier->next; next; next = next->next) { ++count; next->cont = 1; thread_t *other = (thread_t *) sched_threads[next->pid]; switch_prio = priority_min(switch_prio, other->priority); sched_set_status(other, STATUS_PENDING); } barrier->next = NULL; barrier->count = count; } mutex_unlock(&barrier->mutex); if (switch_prio != -1) { sched_switch(switch_prio); } return 0; }