//Create a new thread and call minithread_start on it minithread_t minithread_fork(proc_t proc, arg_t arg) { minithread_t new_thread = minithread_create(proc, arg); if (new_thread == NULL) return NULL; minithread_start(new_thread); return new_thread; }
/** * This function does need to be protected because it is only called * from within a semaphore V, during which interrupts are disabled. * */ void minithread_dequeue_and_run(queue_t q) { minithread_t blocked_thread = NULL; queue_dequeue(q, (void**)(&blocked_thread) ); if (blocked_thread->status != BLOCKED) { printf("thread %d should have status BLOCKED\n", minithread_id()); } minithread_start(blocked_thread); }
minithread_t* minithread_fork(proc_t proc, arg_t arg) { minithread_t *mthread = minithread_create(proc, arg); if (!mthread) { return NULL; } minithread_start(mthread); return mthread; }
/* * semaphore_V(semaphore_t sem) * Signal on the semaphore. */ void semaphore_V(semaphore_t sem) { minithread_t thread; while(atomic_test_and_set(&(sem->mutex))); if(++sem->limit <= 0) { queue_dequeue(sem->waiting,(void**) &thread); minithread_start((minithread_t) thread); } sem->mutex = 0; }
/* * semaphore_V(semaphore_t sem) * V on the sempahore. * If a thread is waiting to P the semaphore, * wake it up. */ void semaphore_V(semaphore_t sem) { minithread_t waiting_thread; semaphore_spinlock(&(sem->lock)); sem->count++; if ( queue_length(sem->thread_queue) ) { queue_dequeue(sem->thread_queue, &waiting_thread); minithread_start(waiting_thread); } atomic_clear(&(sem->lock)); }
/* * semaphore_V(semaphore_t sem) * V on the sempahore. */ void semaphore_V(semaphore_t sem) { minithread_t t; /* while (1 == atomic_test_and_set(&(sem->lock))) ; */ if (0 >= ++(sem->count)) { queue_dequeue(sem->wait,(void**)&t); minithread_start(t); } /* atomic_clear(&(sem->lock)); */ }
/* * Initialization. * Initializes reaper and idle threads, starts and initializes main thread. * Also creates the scheduler and other data * */ void minithread_system_initialize(proc_t mainproc, arg_t mainarg) { //allocate room for schedule data (global) schedule_data = (scheduler *) malloc(sizeof(scheduler)); if (schedule_data == NULL) { exit(1); //OOM } schedule_data->cleanup_queue = queue_new(); schedule_data->multi_run_queue = multilevel_queue_new(num_levels); reaper_sema = semaphore_create(); semaphore_initialize(reaper_sema, 0); // create main thread minithread_t* main_thread = minithread_fork(mainproc, mainarg); // initialize idle thread idle_thread = (minithread_t *) malloc(sizeof(minithread_t)); idle_thread->stacktop = NULL; idle_thread->thread_id = -1; //initialize alarm bookeeping data structure (priority queue) alarm_init(); //remove from run queue and run it schedule_data->running_thread = main_thread; main_thread->status = RUNNING; multilevel_queue_dequeue(schedule_data->multi_run_queue, 0, (void *) main_thread); //reaper thread init reaper_thread = minithread_create(reaper_queue_cleanup, NULL); minithread_start(reaper_thread); //Start clock minithread_clock_init(clock_period, clock_handler); //Initialize network network_initialize(network_handler); //START MAIN PROC //minithread_switch also enables clock interrupts minithread_switch(&idle_thread->stacktop, &main_thread->stacktop); //always comes back here to idle in the kernel level (allows freeing resources) while (1) { minithread_t* next = next_runnable(); set_interrupt_level(DISABLED); next->status = RUNNING; schedule_data->running_thread = next; minithread_switch(&idle_thread->stacktop, &next->stacktop); } }
void semaphore_V(semaphore_t *sem) { //Validate input arguments, abort if invalid argument is seen AbortOnCondition(sem == NULL, "Null argument sem in semaphore_V()"); //validate argument assert(sem->semaWaitQ != NULL); interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interrupts //critical section if (queue_length(sem->semaWaitQ) == 0) sem->count++; else { //if the semaphore wait queue is not empty, then there are threads waiting and the count must be at 0 assert(sem->count == 0); minithread_t* t = NULL; int dequeueSuccess = queue_dequeue(sem->semaWaitQ, (void**) &t); assert(t != NULL); AbortOnCondition(dequeueSuccess != 0, "Failed in queue_dequeue operation in semaphore_V()"); minithread_start(t); } set_interrupt_level(old_level); //restore interrupts }
/* * Thread Awaken Callback - for sleep with timeout */ void minithread_awaken_callback(arg_t arg) { minithread_start( (minithread_t)arg ); }
void wakeup_thread(void* wakeup_mini) { //need to cast this back to the correct data type of a minithread_t //Note that we have decided to put the waking thread in the same priority level //as when it was sleeping minithread_start((minithread_t *) wakeup_mini); }
/* Creates and then starts a minithread, making it RUNNABLE by placing it on the run_queue */ minithread_t* minithread_fork(proc_t proc, arg_t arg) { minithread_t* mini = minithread_create(proc, arg); minithread_start(mini); return mini; }