/* * Atomically release the specified test-and-set lock and * block the calling thread. This is a convenience function that * does not add much (if any) power, but makes for more readable * code and simplifies the possible system states, making it * easier to reason about application correctness. */ int minithread_unlock_and_stop(tas_lock_t *lock) { interrupt_level_t old_int = set_interrupt_level(DISABLED); atomic_clear(lock); minithread_stop(); set_interrupt_level(old_int); return 0; }
/* * sleep with timeout in milliseconds. Need to disable interrupts during method call as we are not using semaphore for sleeping minithreads. */ void minithread_sleep_with_timeout(int delay) { interrupt_level_t old_level = set_interrupt_level(DISABLED); minithread_t* current_thread = schedule_data->running_thread; register_alarm(delay, wakeup_thread, (void *) current_thread); //registers alarm minithread_stop(); //moves to next thread set_interrupt_level(old_level); }
/* * sleep with timeout in milliseconds */ void minithread_sleep_with_timeout(int delay) { interrupt_level_t l = set_interrupt_level(DISABLED); register_alarm(delay, get_new_alarm_handler(), minithread_self()); set_interrupt_level(l); minithread_stop(); }
/* * semaphore_P(semaphore_t sem) * Wait on the semaphore. */ void semaphore_P(semaphore_t sem) { while(atomic_test_and_set(&(sem->mutex))); if (--sem->limit < 0) { queue_append(sem->waiting, minithread_self()); sem->mutex = 0; minithread_stop(); } else { sem->mutex = 0; } }
/* * semaphore_P(semaphore_t sem) * P on the sempahore. */ void semaphore_P(semaphore_t sem) { /* while (1 == atomic_test_and_set(&(sem->lock))) ; */ if (0 > --(sem->count)) { queue_append(sem->wait, minithread_self()); /* atomic_clear(&(sem->lock)); */ minithread_stop(); } /* else { atomic_clear(&(sem->lock)); } */ }
/* Final proc of all newly created minithreads. Will never terminate and threads add * themselves to the cleanup_queue and then context switch to the reaper thread to perform * all the necesary cleanup steps to dispose of the thread properly and safely. */ int minithread_cleanup(int* id) { minithread_t* mini = minithread_self(); mini->status = ZOMBIE; interrupt_level_t old_level = set_interrupt_level(DISABLED); queue_append(schedule_data->cleanup_queue, mini); set_interrupt_level(old_level); // notify reaper thread and let it run semaphore_V(reaper_sema); minithread_stop(); return 0; }
/* * minithread_unlock_and_stop(tas_lock_t* lock) * Atomically release the specified test-and-set lock and * block the calling thread. */ void minithread_unlock_and_stop(tas_lock_t* lock) { // Make it atomic set_interrupt_level(DISABLED); // Atomically clear the lock atomic_clear(lock); // Stop the thread minithread_stop(); // Don't need to re-enable interrupts because mt_stop() performs a context // switch and mt_switch() reenables interrupts }
/* * semaphore_P(semaphore_t sem) * P on the sempahore. */ void semaphore_P(semaphore_t sem) { //Loop until we succeed semaphore_spinlock(&(sem->lock)); while (sem->count == 0) { queue_append(sem->thread_queue, minithread_self()); atomic_clear(&(sem->lock)); minithread_stop(); semaphore_spinlock(&(sem->lock)); } //Got the semaphore. Decrement and break sem->count--; atomic_clear(&(sem->lock)); }
void semaphore_P(semaphore_t *sem) { //Validate input arguments, abort if invalid argument is seen AbortOnCondition(sem == NULL, "Null argument sem in semaphore_P()"); assert(sem->semaWaitQ != NULL); //sanity check interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interrupts //critical section if (sem->count > 0) sem->count--; else { minithread_t* currThread = minithread_self(); //get the calling thread AbortOnCondition(currThread == NULL, "Failed in minithread_self() method in semaphore_P()"); queue_append(sem->semaWaitQ, currThread); //put thread onto semaphore's wait queue minithread_stop(); //block calling thread, yield processor } set_interrupt_level(old_level); //restore interrupt level }