/* * Initialization. * * minithread_system_initialize: * This procedure should be called from your C main procedure * to turn a single threaded UNIX process into a multithreaded * program. * * Initialize any private data structures. * Create the idle thread. * Fork the thread which should call mainproc(mainarg) * Start scheduling. * * Note that the runnable_q is protected by disabling interrupts. * All other data structures are protected with binary semaphores. * */ void minithread_system_initialize(proc_t mainproc, arg_t mainarg) { minithread_t clean_up_thread = NULL; minithread_t process_packets_thread = NULL; int a = 0; void* dummy_ptr = NULL; dummy_ptr = (void*)&a; current_id = 0; // the next thread id to be assigned id_lock = semaphore_create(); semaphore_initialize(id_lock,1); runnable_q = multilevel_queue_new(4); blocked_q = queue_new(); blocked_q_lock = semaphore_create(); semaphore_initialize(blocked_q_lock,1); dead_q = queue_new(); dead_q_lock = semaphore_create(); semaphore_initialize(dead_q_lock,1); dead_sem = semaphore_create(); semaphore_initialize(dead_sem,0); clean_up_thread = minithread_create(clean_up, NULL); multilevel_queue_enqueue(runnable_q, clean_up_thread->priority,clean_up_thread); runnable_count++; minimsg_initialize(); process_packets_thread = minithread_create(process_packets, NULL); multilevel_queue_enqueue(runnable_q, process_packets_thread->priority,process_packets_thread); runnable_count++; minithread_clock_init(TIME_QUANTA, (interrupt_handler_t)clock_handler); network_initialize((network_handler_t) network_handler); init_alarm(); current_thread = minithread_create(mainproc, mainarg); minithread_switch(&dummy_ptr, &(current_thread->stacktop)); return; }
/* * Initialize the system to run the first minithread at * mainproc(mainarg). This procedure should be called from your * main program with the callback procedure and argument specified * as arguments. */ void minithread_system_initialize(proc_t mainproc, arg_t mainarg) { runnable_queue = multilevel_queue_new(MAX_LEVELS); stopped_queue = queue_new(); scheduler_thread = scheduler_thread_create(); assert(scheduler_thread); running_thread = scheduler_thread; int res = network_initialize((network_handler_t) network_handler); assert(res == 0); alarm_system_initialize(); minimsg_initialize(); minisocket_initialize(); reaper_thread = minithread_create(clean_stopped_threads, NULL); minithread_fork(mainproc, mainarg); interrupt_level_t prev_level = set_interrupt_level(ENABLED); minithread_clock_init(PERIOD * MILLISECOND, clock_handler); while (1) { if (!multilevel_queue_is_empty(runnable_queue)) { minithread_yield(); } } set_interrupt_level(prev_level); multilevel_queue_free(runnable_queue); queue_free(stopped_queue); }
/* * Initialization. * * minithread_system_initialize: * This procedure should be called from your C main procedure * to turn a single threaded UNIX process into a multithreaded * program. * * Initialize any private data structures. * Create the idle thread. * Fork the thread which should call mainproc(mainarg) * Start scheduling. * */ void minithread_system_initialize(proc_t mainproc, arg_t mainarg) { // create an initial TCB minithread_t tcb = (minithread_t) malloc(sizeof(minithread)); // Create a dummy pointer that points nowhere for the idle thread's stack stack_pointer_t* stack_top = (stack_pointer_t*) malloc(sizeof(stack_pointer_t)); // Create the ready queue ready_queue = multilevel_queue_new(4); // There are currently 0 ready threads ready_threads = 0; // Set the current level we inspect in the ML queue to 0 current_level = 0; // The first level of the queue has quanta of 1 period ticks_until_switch = 1; // The number of ticks to spend in the first ML queue level ticks_until_next_level = 80; // Create the waiting queue cleanup_queue = queue_new(); // Create the alarm queue alarm_queue = queue_new(); // Create the cleanup semaphore cleanup_sem = semaphore_create(); semaphore_initialize(cleanup_sem, 0); // Initialize the TCB tcb->id = 0; tcb->priority = 0; tcb->proc = (proc_t) minithread_idle; tcb->arg = NULL; tcb->dir_block_id = 0; // it'll never be used anyway // remember to update the initialize stack call a few lines down too - // the first 2 nulls should also be proc/arg // Allocate the stack tcb->stack_base = NULL; // don't need this // just give it a dummy pointer so it can context switch tcb->stack_top = stack_top; // Set the global variables idle = tcb; running = idle; // Setup interrupts minithread_clock_init(&interrupt_handler); // Setup disk interrupts install_disk_handler((interrupt_handler_t) &disk_interrupt_handler); // Initialize the keyboard miniterm_initialize(); // Initialize the minimsg layer minimsg_initialize(); // Initialize the minisocket layer minisocket_initialize(); // Initialize the miniroute layer miniroute_initialize(); // Before interrupts are enabled, start the network handler network_initialize((interrupt_handler_t) &network_handler); // Initialize the filesystem minifile_initialize(); // Fork the mainproc(mainarg) thread minithread_fork(mainproc, mainarg); // Fork a cleanup thread cleanup = minithread_fork((proc_t) minithread_cleanup, NULL); // Enable the interrupts set_interrupt_level(ENABLED); // Start the idle procedure minithread_idle(NULL); }