void mem_init(struct multiboot_info *mb) { uint64_t max_avail = 0; multiboot_module_t *kernel; size_t i; /* the loader should really do this for us */ clear_bss(); for (i = 0; i < mb->mmap_length; i += sizeof(multiboot_memory_map_t)) { multiboot_memory_map_t *m; m = (multiboot_memory_map_t *)(mb->mmap_addr + i); max_addr = m->addr + m->len; if ( m->type == MULTIBOOT_MEMORY_AVAILABLE ) max_avail = max_addr; } kernel = (multiboot_module_t *)((uint64_t)mb->mods_addr); kernel_start = kernel->mod_start; kernel_end = kernel->mod_end; page_table_area = (kernel_end & PAGE_MASK) + PAGE_SIZE; page_bitmap_init(mb->mmap_addr, mb->mmap_length); heap_start = (page_bitmap_area + PGBITS_SIZE(max_addr) + PAGE_SIZE - 1) & PAGE_MASK; heap_top = heap_start; allocate_stack(max_avail - 8); }
PRIVATE void setup_context(int task_no, int max) /* setup the thread context */ { char c; if (setjmp(thread_table[task_no].context)) { if (DEBUG_LEVEL >= 2) { printf("Starting now thread %d\n", task_no); } kernel_mode=NO; thread_table[task_no].start_function(); /* if the thread reaches this point it is actually exiting; kill it */ if (DEBUG_LEVEL > 0) printf("Thread %d exhausts\n", task_no); kill_thread(task_no); } else { /* Pass to create next task */ if (DEBUG_LEVEL >= 1) printf("Thread %d created\n", task_no); thread_table[task_no].stack_start = &c; allocate_stack(task_no+1, max); /* this never returns...*/ } }
PUBLIC void initialize_threads(void) /* build the thread stacks and their context structures */ { struct thread* t; if (!setjmp(home)) allocate_stack(0, MAX_THREADS); /* save the context in order to restore it at the top of the stack if the thread dies -- to recover stack space */ for_all_threads(t) { copy_context(t->context, t->original_context); } alive = 0; sleeping = 0; to_alarm = 0; }
yarn_t yarn_new ( void (*routine)(void*), void* udata, int nice ) { // grab memory yarn* active_yarn; yarn_t pid; //prepare_context(0); pool* p = get_yarn_pool(); active_yarn = (yarn*)pool_allocate(p); assert(active_yarn); // prepare the context init_context(&active_yarn->context); // set up stack and such active_yarn->stackBase = allocate_stack(&(active_yarn->context)); // run yarn_context_make to direct it over to the bootstrap prepare_context(active_yarn, routine, udata); // insert it into the yarn list pid = list_insert(active_yarn, nice); if (live) master_sched_schedule(pid, prio_lookup(nice)); return pid; }
uint32_t exec_elf(const char* name) { fs_node_t* file = finddir(fs_root, name); open(file, 1, 0); // disable interrupts asm volatile("cli"); // save directory and create one for new task page_directory_t* old_dir = current_directory; page_directory_t* new_dir = clone_directory(old_dir); // switch to new directory (this is where we set up process) switch_page_directory(new_dir); // load elf and get entry point uint32_t entry = load_elf_binary(file); // setup stack uint32_t stack = (uint32_t) allocate_stack(THREAD_STACK_SIZE); // create scheduling structures thread_t* new_thread = create_thread((int(*)(void*)) entry, 0, (uint32_t*) stack, THREAD_STACK_SIZE); task_t* new_task = create_task(new_thread, new_dir); schedule_add_task(new_task); // switch back to parents directory switch_page_directory(old_dir); // close executable image close(file); // reenable interrupts asm volatile("sti"); // like in fork return child pid return new_task->pid; }
static void yarn_processor ( unsigned long procID ) { // this is the main routine run by each thread struct sigaction sa; void* stackRoot; volatile int breakProcessor = 0; int rc; unsigned deadSleepTime = YARNS_DEAD_SLEEP_TIME; // init the thread yarn data TTDINIT(); TTDGET(); // make sure it initted properly assert(&TTD); // repeatedly ask the scheduler for the next job scheduler_job activeJob; #ifdef BASE_CONTEXT_NEEDS_STACK stackRoot = allocate_stack(&(TTD.sched_context)); #endif #if YARNS_SYNERGY == YARNS_SYNERGY_PREEMPTIVE sa.sa_sigaction = (void (*)(int, struct __siginfo *, void *))preempt_signal_handler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGUSR2); sigaction(SIGUSR2, &sa, 0); #endif activeJob.pid = 0; activeJob.runtime = 0; activeJob.data = 0; activeJob.next = 0; activeJob.priority = SCHED_PRIO_NORMAL; while (!breakProcessor) { TTD.shouldSuspend = 0; if (procID == wgProcResponsibility) { wait_graph_lock(wg); wait_graph_time_process(wg); wait_graph_unlock(wg); wgProcResponsibility++; wgProcResponsibility %= coreCount; } master_sched_select(procID, &activeJob); if (activeJob.pid == 0) { usleep(deadSleepTime); deadSleepTime += (deadSleepTime / 2); continue; } DEBUG("job %lu @ proc %d (rt: %lu us)\n", activeJob.pid, (int)procID, activeJob.runtime); if (activeJob.pid >= maxpid) { DEBUG("got pid %lu which is out-of-bound!\n", activeJob.pid); usleep(deadSleepTime); continue; } if (!PTABLE(activeJob.pid)) { DEBUG("got dead pid %lu\n", activeJob.pid); usleep(deadSleepTime); continue; } // set all the stuff up TTD.yarn_current = PTABLE(activeJob.pid); TTD.start_time = yarns_time(); TTD.next = 0; TTD.runtime = activeJob.runtime; // swap contexts DEBUG("yarn_context_swap to yarn: %p\n", TTD.yarn_current); #if YARNS_SYNERGY == YARNS_SYNERGY_PREEMPTIVE preempt(yarns_time() + activeJob.runtime, procID); preempt_enable(); #endif rc = yarn_context_swap(&(TTD.sched_context), &(TTD.yarn_current->context)); #if YARNS_SYNERGY == YARNS_SYNERGY_PREEMPTIVE preempt_disable(); #endif activeJob.next = TTD.next; // check it actually worked if (rc == 0) perror("yarn_context_swap failed"); // set the runtime #ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) #endif activeJob.runtime = MIN(TTD.runtime, activeJob.runtime); // if we're unscheduling, yfree up memory if (TTD.runtime == UNSCHEDULE) { master_sched_unschedule(procID, &activeJob); deallocate_stack(TTD.yarn_current->stackBase); pool_free(get_yarn_pool(), TTD.yarn_current); } else if (TTD.shouldSuspend) { TTD.yarn_current->isSuspended = 1; TTD.yarn_current->suspensionCore = procID; memcpy(&(TTD.yarn_current->suspensionJob), &activeJob, sizeof(activeJob)); } else { master_sched_reschedule(procID, &activeJob); } deadSleepTime = YARNS_DEAD_SLEEP_TIME; } #ifdef BASE_CONTEXT_NEEDS_STACK deallocate_stack(stackRoot); #endif }
uint32_t exec_thread(int(*fn)(void*), void* arg) { thread_t * new_thread = create_thread(fn, arg, allocate_stack(THREAD_STACK_SIZE), THREAD_STACK_SIZE); task_add_thread(current_task, new_thread); return new_thread->tid; }
/** * \private * create a pcb with all the needed value at the specified location */ uint32_t create_proc(char *name, uint32_t prio, uint32_t argc, char **params) { uint32_t *i, j; int32_t pid; pcb *p; prgm *prg; //kdebug_println("Create process in"); if (name == NULL) return NULLPTR; if (prio > MAX_PRI || prio < MIN_PRI) return INVARG; if (pcb_counter <= MAXPCB) { /* * Allocate a pcb */ p = alloc_pcb(); if (p == NULL) return OUTOMEM; /* * Reset the pcb */ pcb_reset(p); /* * Check that the program exist */ prg = search_prgm(name); if (prg == NULL) return INVARG; /* * Set the name */ pcb_set_name(p, name); /* * init the program counter */ pcb_set_epc(p, (uint32_t) prg->address); /* * get a pid */ pid = get_next_pid(); if (pid < 0) return pid; /* contain an error code */ pcb_set_pid(p, pid); /* set the pid */ pcb_set_pri(p, prio); /* set the priority */ /* * Set the supervisor of the process, which is the one we ask for the creation * or -1 if the system ask. * This value is in the global variable current_pcb */ if (current_pcb != NULL) { pcb_set_supervisor(p, pcb_get_pid(current_pcb)); pcb_set_supervised(current_pcb, pid); } else pcb_set_supervisor(p, -1); /* <<<<<<< HEAD:src/kernel/kprocess.c <<<<<<< HEAD:src/kernel/kprocess.c * Set the parameters of the function */ //p->registers.a_reg[0] = (params == NULL) ? 0 : stoi(get_arg(params, 0)) + 1; //p->registers.a_reg[1] = (uint32_t) params; /* the adresse of the first arg */ if (params != NULL) { p->registers.a_reg[0] = argc + 1; p->registers.a_reg[1] = (uint32_t) params; } else { p->registers.a_reg[0] = 0; p->registers.a_reg[1] = 0; } /* ======= >>>>>>> 3e4887fd7d8130975ae6c220ed2077f5f2538be9:src/kernel/kprocess.c * Set the stack pointer ======= * Set the stack pointer >>>>>>> ef0b08729fd10e82db039bea92d2ce232b3a027b:src/kernel/kprocess.c */ i = allocate_stack(pcb_get_pid(p)); if (i == NULL) return OUTOMEM; /* * We add the arg on the stack */ //kprint("sp set\n"); if (params != NULL) { //kprint((char *) params); //kprint("params not null\n"); //kprint(itos((uint32_t) i, c)); //kprint("\n"); i = (uint32_t *) ((uint32_t) i - (ARG_SIZE * (argc + 1) * sizeof(char))); /* set the sp after the arg */ //kprint(itos((uint32_t) i, c)); //kprint("\n"); pcb_set_sp(p, (uint32_t) i); /* set the stack pointer */ for (j = 0; j < (argc + 1) * (ARG_SIZE * sizeof(char) / sizeof(uint32_t)); j++) { //kprint("Copy params\n"); *i = (uint32_t) * params; //kprint("Param copied\n"); //i += ARG_SIZE * sizeof(char); i++; (uint32_t *) params++; } //kprint((char *) pcb_get_sp(p)); } else pcb_set_sp(p, (uint32_t) i); //kprint("copy arg done\n"); /* * Set the parameters of the function * The begin of the parameters are pointed by the stack pointer */ if (params != NULL) { p->registers.a_reg[0] = argc + 1; p->registers.a_reg[1] = (uint32_t) pcb_get_sp(p); } else { p->registers.a_reg[0] = 0; p->registers.a_reg[1] = 0; } /* * Set the state */ pcb_set_state(p, READY); /* * Set the last error */ pcb_set_error(p, OMGROXX); /* * The pcb is no more empty */ pcb_set_empty(p, FALSE); /* * Now we can add the pcb to the ready list */ if (pls_add(&plsready, p) == OUTOMEM) { /* * Adding fail, don't forget to dealloc every allocated stuff */ deallocate_stack(pcb_get_pid(p)); pcb_reset(p); return OUTOMEM; } /* * Everything goes well, we add one to the pcb_counter */ pcb_counter++; } else return OUTOMEM; //kdebug_println("Create process out"); return pid; }