static ke_handle memory_virtual_alloc(struct sysreq_memory_virtual_alloc *req) { unsigned long base, sz, type; ke_handle handle; struct ko_section *ks_virtual; if (req->name) { type = KS_TYPE_SHARE; TRACE_UNIMPLEMENTED("命名内存空间还没有支持"); goto err0; } else type = KS_TYPE_PRIVATE; base = req->base_address; sz = req->size; ks_virtual = ks_create(KP_CURRENT(), type, base, sz, req->mem_prot); if (!ks_virtual) goto err0; handle = ke_handle_create(ks_virtual); if (handle == KE_INVALID_HANDLE) goto err1; /* Fill output */ req->out_base = ks_virtual->node.start; req->out_size = ks_virtual->node.size; return handle; err1: TODO("分配内存段错误,须回收"); err0: return KE_INVALID_HANDLE; }
/** @brief Create a thread */ struct ko_thread *kt_create(struct ko_process *where, struct kt_thread_creating_context *ctx) { struct ko_thread *p = NULL; /* Handle stack */ ctx->cpl = where->cpl; if (ctx->cpl == KP_USER) { struct ko_section *ks; int stack_size = KT_THREAD_FIRST_STACK_SIZE; //TODO: 一般,不是第一个线程无需这么大的堆栈 ks = ks_create(where, KS_TYPE_STACK, 0, stack_size, KM_PROT_READ|KM_PROT_WRITE); if (!ks) goto err0; ctx->stack_pos = ks->node.start + stack_size; } if (!ctx->stack0_size/* If caller give a specific stack(driver system will), we do not need to create */) { ctx->stack0_size = KT_ARCH_THREAD_CP0_STACK_SIZE; ctx->stack0 = km_page_alloc_kerneled(ctx->stack0_size / PAGE_SIZE); } /* Has command line param? Caller will make sure the ctx->param is a valid kernel buffer */ if (ctx->flags & KT_CREATE_STACK_AS_PARA) { /* Write the cmdline to kernel stack(底部) for user to fetch */ if (strlen((char*)ctx->para) >= ctx->stack0_size) goto err1; strcpy((char*)ctx->stack0, (char*)ctx->para); /* Write the real thread param for this address, so we know where to fetch */ ctx->para = (unsigned long)ctx->stack0; } /* Fate entry only can default if we are creating ring0 thread */ if (!ctx->fate_entry) { if (ctx->cpl == KP_USER) goto err1; ctx->fate_entry = (void*)kernel_thread_fate_entry; } /* Thread Object */ p = cl_object_create(&thread_type); if (!p) goto err1; kt_arch_init_thread(p, ctx); p->process = where; if (ctx->flags & KT_CREATE_RUN) kt_wakeup(p); return p; err1: //TODO: To recall all resources err0: return NULL; }
static struct ko_section *create_file_map(struct ko_process *to, void *fp, size_t size, page_prot_t prot) { struct ko_section *ks_file; if (NULL == (ks_file = ks_create(to, KS_TYPE_FILE, NULL, size, prot))) goto err0; ks_file->priv.file.file = fp; return ks_file; err0: return NULL; }
static struct ko_section *map_file(struct ko_process *to, xstring name, page_prot_t prot, unsigned long *map_size) { struct ko_section *ks_file; unsigned long size; void *fp; fp = fss_open(kt_current()->current_dir, name); if (!fp) goto end; *map_size = size = fss_get_size(fp); ks_file = ks_create(to, KS_TYPE_FILE, NULL, size, prot); if (!ks_file) goto err1; ks_file->priv.file.file = fp; return ks_file; err1: fss_close(fp); end: return NULL; }
/** @brief run startup process */ void ke_run_first_user_process(void *data, int size, char *cmdline) { char *first_space, first_exe_name[128] = {0}; struct ko_section *ks; void *entry_address; struct ko_exe *kee, *ke_tmp = kp_exe_create_temp(); first_space = strchr(cmdline, ' '); if (!first_space) goto err; if (first_space - cmdline >= sizeof(first_exe_name) - sizeof(xchar)) goto err; strncpy(first_exe_name, cmdline, first_space - cmdline); /* Kernel file process, because early we cannot copy lv2 table of driver */ kernel_file_process = kp_create(KP_CPL0_FAKE, "操作系统文件进程"); if (!kernel_file_process) goto err; printk("启动用户第一个可执行文件%x, size %d.\n", data, size); if (size == 0/*no file*/ || size == 1/*buffer error*/) goto err; if (elf_analyze(data, size, &entry_address, KO_EXE_TO_PRIVATE(ke_tmp)) == false) goto err; ks = ks_create(kp_get_file_process(), KS_TYPE_PRIVATE, 0, size, KM_PROT_READ|KM_PROT_WRITE); if (!ks) goto err; kee = kp_exe_create_from_file(first_exe_name, ks, KO_EXE_TO_PRIVATE(ke_tmp), entry_address); if (!kee) goto err; /* But this is a special one, we have to fill the data on it */ do { struct kt_thread_creating_context ctx = {0}; struct file_process_startup_para package; package.ks_start = ks->node.start; package.size = size; package.data = data; ctx.thread_entry = file_thread; ctx.flags = KT_CREATE_RUN; ctx.para = (unsigned long)&package; if (kt_create(kernel_file_process, &ctx) == NULL) goto err; /* Wait it to finish */ while (package.data) kt_schedule(); } while(0); /* OK, create the process */ if (kp_run_user(kee, ++first_space/*Real application*/) == false) goto err; return; err: printk("启动第一可执行文件失败。\n"); }