s32 os_main(u32 sp) { struct __os_task__ *ptask; int_init(); uart_init(); dram_init(); timer_init(); mmc_init(); PRINT_INFO("%s\n", sys_banner); coretimer_init(); task_init(); semaphore_init(); PRINT_INFO("cpu_mode: %s; lr: 0x%x; sp: 0x%x; cpsr: 0x%x\n", get_cpu_mode(NULL), __get_lr(), sp, __get_cpsr()); gpio_set_function(GPIO_16, OUTPUT); gpio_set_output(GPIO_16, 0); /* set_log_level(LOG_DEBUG); */ /* create idle task */ if ((ptask = tcb_alloc()) == NULL) { panic(); } tcb_init(ptask, idle_task, 0, 256); /*os_ready_insert(ptask);*/ current_task = &tcb[IDLE_TASK_ID]; /* assume that this is idle_task */ /* create main task */ if ((ptask = tcb_alloc()) == NULL) { panic(); } tcb_init(ptask, main_task, 0, 100); os_ready_insert(ptask); /* 'slip into idle task', cause the os_main() is not a task (it's the god code of system) */ __set_sp(&(task_stack[0][TASK_STK_SIZE])); current_task->state = TASK_RUNNING; idle_task(0); kassert(0); return 0; }
/** * Get a tcb and initialize it with the entry and entry_arg. * * @param entry routine to call to start thread * @param entry_arg is the argument to pass to entry * * Return AC_NULL if an error, i.e. nono available */ STATIC tcb_x86* get_tcb(void*(*entry)(void*), void* entry_arg) { tcb_x86* ptcb; // There must always be at least one ac_threads ac_debug_assert(pthreads != AC_NULL); // Search all of the ac_threads for an empty tcb ac_threads* pcur = pthreads; do { // Find an empty tcb; for (ac_u32 i = 0; i < pcur->max_count; i++) { ptcb = &pcur->tcbs[i]; ac_u32 empty = AC_THREAD_ID_EMPTY; ac_s32* pthread_id = &ptcb->thread_id; ac_bool ok = __atomic_compare_exchange_n(pthread_id, &empty, AC_THREAD_ID_STARTING, AC_TRUE, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); if (ok) { // Found an empty tcb, initialize and return it tcb_init(ptcb, i, entry, entry_arg); return ptcb; } } pcur = pcur->pnext; } while (pcur != pthreads); // No empty tcbs return AC_NULL; }
/** * Early initialization of this module */ void ac_thread_early_init() { // Initialize timer first, the main reason // is it set slice_default. init_timer(); // Initialize reschedule isr set_intr_handler(RESCHEDULE_ISR_INTR, reschedule_isr); set_intr_handler(TIMER_RESCHEDULE_ISR_INTR, timer_reschedule_isr); // Allocate the initial array total_threads = 0; pthreads = AC_NULL; ac_thread_init(SYSTEM_THREAD_COUNT); ac_assert(pthreads != AC_NULL); pidle_tcb = &pthreads->tcbs[0]; pmain_tcb = &pthreads->tcbs[1]; // Initialize idle and main tcbs tcb_init(pidle_tcb, 0, idle, AC_NULL); tcb_init(pmain_tcb, 1, AC_NULL, AC_NULL); // Initialize idle's stack init_stack_frame(idle_stack, sizeof(idle_stack), DEFAULT_FLAGS, idle, pidle_tcb, &pidle_tcb->sp, &pidle_tcb->ss); // Add main as the initial pready list pmain_tcb->pnext_tcb = pmain_tcb; pmain_tcb->pprev_tcb = pmain_tcb; pready = pmain_tcb; #ifdef SUPPORT_READY_LENGTH ready_length = 1; #endif // Add idle to the pready list add_tcb_after(pidle_tcb, pready); // Initialize waiting tcbs data structures waiting_tcbs_init(SYSTEM_THREAD_COUNT); print_waiting_tcbs(); ac_printf("ac_thread_early_init: pmain=0x%lx pidle=0x%lx rl=%d\n", pmain_tcb, pidle_tcb, get_ready_length()); print_tcb_list("ac_thread_early_init:-ready: ", pready); }
/** * @brief This function initializes the idle TCB and makes it runnable */ static void idle_init(void){ task_t idle_task; idle_task.lambda = (void *) idle; idle_task.data = 0; idle_task.C = 0; idle_task.T = 0; idle_task.stack_pos = (void *) idle_stack_high; tcb_init(&idle_task, &system_tcb[IDLE_PRIO], IDLE_PRIO); runqueue_add(&system_tcb[IDLE_PRIO], IDLE_PRIO); }
/** * Initializes all the thread queues with * tqueue_init_at_id. */ void tqueue_init(unsigned int mbi_addr) { // TODO: define your local variables here. unsigned int chid; tcb_init(mbi_addr); for (chid = 0; chid < NUM_IDS + 1; chid++) { tqueue_init_at_id(chid); } }
/** * @brief Creates the main user program as a main task * and sets it to run. * * This function is only called when the user program is * first run. * */ void sched_init(task_t* main_task) { main_task->lambda = (void *)0xa0000000; main_task->data = 0; main_task->stack_pos = (void *)0xa3000000; main_task->C = 1; main_task->T = 1; tcb_init(main_task, &system_tcb[FIRST_MAIN_PRIO], FIRST_MAIN_PRIO); runqueue_add(&system_tcb[FIRST_MAIN_PRIO], FIRST_MAIN_PRIO); dispatch_init(&system_tcb[FIRST_MAIN_PRIO]); }
/** * @brief Allocate user-stacks and initializes the kernel contexts of the * given threads. * * This function assumes that: * - num_tasks < number of tasks allowed on the system. * - the tasks have already been deemed schedulable and have been appropriately * scheduled. In particular, this means that the task list is sorted in order * of priority -- higher priority tasks come first. * * @param tasks A list of scheduled task descriptors. * @param size The number of tasks is the list. */ void allocate_tasks(task_t** ptasks, size_t num_tasks) { //set up system tcb for each task in 'tasks' - loop through each task uint8_t i; runqueue_init(); dev_init(); for(i = 1; i <= num_tasks; i++) { tcb_init(ptasks[i], &system_tcb[i], i); runqueue_add(&system_tcb[i], i); } /* add the idle task */ idle_init(); }
/** * Initialize this module */ void ac_thread_init(ac_u32 max_threads) { ac_assert(max_threads > 0); max_threads += SYSTEM_THREAD_COUNT; ac_uint flags = disable_intr(); if (max_threads > total_threads) { // Create array of the threads ac_u32 count = max_threads - total_threads; ac_u32 size = sizeof(ac_threads) + (count * sizeof(tcb_x86)); ac_threads* pnew = ac_malloc(size); ac_assert(pnew != AC_NULL); pnew->max_count = count; // Initialize new entries to AC_THREAD_EMPTY for (ac_u32 i = 0; i < count; i++) { tcb_init(&pnew->tcbs[i], AC_THREAD_ID_EMPTY, AC_NULL, AC_NULL); } if (pthreads == AC_NULL) { // Add frist set of threads pnew->pnext = pnew; pnew->pprev = pnew; pthreads = pnew; } else { // Add these new ones to the beginning of the list // by adding after the pthreads then move pthreads ac_threads* ptmp = pthreads->pnext; pnew->pnext = ptmp; pnew->pprev = pthreads; ptmp->pprev = pnew; pthreads->pnext = pnew; // Point pthreads at pnew to make it head of the list pthreads = pnew; } total_threads += max_threads; // Gurantee all threads can wait simultaneously waiting_tcbs_update_max(total_threads); } restore_intr(flags); }
int task_create( void (*task_function)(void), stack_item *stack_bottom, int priority) { mem_address task_sp; /* a stack pointer */ int task_id; /* task id */ task_control_block tcb; /* TCB to be installed */ #ifdef BUILD_ARM_BB int n_saved_registers = 14; int n_bytes_per_register = 4; #endif #ifdef BUILD_X86_HOST int n_saved_registers = 7; int n_bytes_per_register = 4; #endif #ifdef BUILD_X86_64_HOST int n_saved_registers = 5; int n_bytes_per_register = 8; #endif #ifdef BUILD_X86_MAC_HOST int n_saved_registers = 5; int n_bytes_per_register = 8; #endif prepare_stack(stack_bottom, &task_sp, task_function, n_saved_registers, n_bytes_per_register); /* initialise the tcb */ tcb_init(&tcb, task_sp, priority); /* install the tcb */ task_id = tcb_storage_install_tcb(tcb); /* return task id of created task */ return task_id; }