static int init_task_struct(struct task_struct *task, u32 flag) { struct task_struct *parent; unsigned long flags; /* if thread is a kernel thread, his parent is idle */ if (flag & PROCESS_TYPE_KERNEL) parent = idle; else parent = current; /* get a new pid */ task->pid = get_new_pid(task); if ((task->pid) < 0) return -EINVAL; task->uid = parent->uid; task->stack_base = NULL; task->stack_base = NULL; strncpy(task->name, parent->name, PROCESS_NAME_SIZE); task->flag = flag; task->state = 0; /* add task to the child list of his parent. */ task->parent = parent; init_list(&task->p); init_list(&task->child); init_mutex(&task->mutex); enter_critical(&flags); list_add(&parent->child, &task->p); exit_critical(&flags); return 0; }
////分配一个未使用的任务结构 //返回:未使用的任务结构 struct TASK *task_alloc(void) { int i; struct TASK *task = NULL; for (i = 0; i < MAX_TASKS; i++) { if (taskctl->tasks0[i].flags == 0) { task = &taskctl->tasks0[i]; task->signal = 0; task->pid = get_new_pid(); task->nr = i; debug("alloc pid = %d",task->pid); task->flags = 1; /* 正在使用的标志 */ task->tss.eflags = 0x00000202; /* IF = 1; */ task->tss.eax = 0; /* 这里先设置为0 */ task->tss.ecx = 0; task->tss.edx = 0; task->tss.ebx = 0; task->tss.ebp = 0; task->tss.esi = 0; task->tss.edi = 0; task->tss.es = 0; task->tss.ds = 0; task->tss.fs = 0; task->tss.gs = 0; task->tss.cr3 = PAGE_DIR_ADDR; task->tss.iomap = 0x40000000; task->tss.ss0 = 0; task->forked = 0; //重置是否是fork创建的标志 task->exit_status = -1000; task->pwd = get_root_inode(); task->root = get_root_inode(); task->readKeyboard = 0; /* 打开标准文件:STDIN, STDOUT, STDERR */ open_std_files(task); return task; } } return 0; /* 全部正在使用 */ }
SOS() { readyq = new_dllist(); mt_init(); writeok = mt_sem_create(0); writers = mt_sem_create(1); readers = mt_sem_create(1); nelem = mt_sem_create(0); consoleWait = mt_sem_create(0); wr_iobuf = make_io_buffer(1); cr_iobuf = make_io_buffer(256); crb_no_chars = 0; crb_end = 0; crb_begin = 0; curpid = -1; // pids = make_rb(); init_partitions(); DEBUG('e', "pagesize: %d\n", PageSize); jrbTree = make_jrb(); // Step 20 init = new_pcb(); // Step 22 init->pid = get_new_pid(); // Step 22 cread_vnode = new_vnode(); cread_vnode->iobuf =cr_iobuf; cr_iobuf->nwriters = 1; cwrite_vnode = new_vnode(); cwrite_vnode->iobuf = wr_iobuf; wr_iobuf->nreaders = 1; start_timer(10); bzero(main_memory, MemorySize); mt_create(read_console_io, (void *)cr_iobuf); mt_create(write_console_io, (void *)wr_iobuf); //mt_create(read_console, NULL); mt_create(initialize_user_process, (void *)Argv); schedule(); }
void *initialize_user_process(void *arg) { // printf("Enters initalize_user_process\n"); int i; char **filename = (char **)arg; int argc = 0; while (filename[argc]!=NULL) { printf("This is filename[%i]: %s\n", argc, filename[argc]); argc++; } // printf("This is argc in init: %i\n", argc); //Step 19: putting in argc //k = WordToMachine(argc); //memcpy(main_memory+MemorySize-40+12, &k, 4); //L3 Step 18: start first process, is this init? init=(PCB *)malloc(sizeof(PCB)); init->registers = (int *)malloc(NumTotalRegs*sizeof(int)); for (i=0; i < NumTotalRegs; i++) { init->registers[i] = 0; } init->pid = (int *)0; // printf("This is init's pid: %i\n", (int)init->pid); //L3 Step 19: init->waiter_sem = make_kt_sem(0); init->waiters = new_dllist(); init->children = make_jrb(); //Allocate a new PCB PCB *temp=(PCB *)malloc(sizeof(PCB)); temp->registers = (int *)malloc(NumTotalRegs*sizeof(int)); temp->user_base = 0; //printf("Initial user_base: %i\n", temp->user_base); //Changed Step 12: temp->user_limit = MemorySize-2048; temp->user_limit = MemorySize/8; //printf("Initial user_limt: %i\n", temp->user_limit); //L3 Step 18: temp->parent = init; //L3 Step 19: temp->waiter_sem = make_kt_sem(0); temp->waiters = new_dllist(); //L3 Step 21: make rb tree for children temp->children = make_jrb(); //Changed at Step 12: User_Base = temp->user_base; User_Base = memory8(); User_Limit = temp->user_limit; //printf("This is User_Base in initialize: %i\n", User_Base); //printf("This is User_Limit in initialize: %i\n", User_Limit); //set the regs of the //printf("Setting all the registers to 0 in initalize_user_process\n"); for (i=0; i < NumTotalRegs; i++) temp->registers[i] = 0; //printf("Setting pid in init\n"); temp->pid = (int *)get_new_pid(); printf("First Pid: %i and its parent's should be 0 init: %i\n", temp->pid, temp->parent->pid ); /* set up the program counters and the stack register */ temp->registers[PCReg] = 0; temp->registers[NextPCReg] = 4; //insert the first process as init's child; WOW you can use this function! Jval tempN = new_jval_v((void*)temp); //can only insert Jvals jrb_insert_int(init->children, (int)temp->pid, tempN); //JRB tree, int ikey, Jval val //JRB ptr; // jrb_traverse(ptr, init->children) //{ //printf("This is child pid %i of init %i\n", ptr->key, (int)init->pid); //} //perform_execve(job, fn, argv) // where job is the new PCB, fn is the name of your initial executable (at this point, mine is a.out), //and argv is the argv of this initial job. //returns-> 0 success, errno if error //PrintStack(temp->registers[StackReg], temp->user_base); int errno = perform_execve(temp, filename[0],filename); // printf("This is perform_execve: %i\n", errno); //returns to initialize_user_process(), it either exits because there was an error, or it puts the new job onto the ready queue and calls kt_exit() PrintStack(temp->registers[StackReg], temp->user_base); if (errno!=0) { printf("Perform_execve returned unsucessful\n"); kt_exit(); } //printf("Placing jval into queue\n"); Jval value = new_jval_v((void *)temp); //value.v = temp; //printf("This is the value being placed into the readyq in the initalize_user_process: %s\n",value.v ); dll_append(readyq, value); // printf("Program %s loaded\n", kos_argv[0]); kt_exit(); }
pid loader_load(pso_file* f, int pl) { //me guardo el cr3 viejo. uint_32 old_cr3 = rcr3(); //pido un directorio para la nueva tarea void* task_dir = mm_dir_new(); printf(" >loader_load: task_dir = %x", task_dir); //TODO VER CUANTA MEMORIA NECESITA REALMENTE void* puntero_page_tarea = mm_mem_alloc(); printf(" >loader_load: puntero page tarea : %x", (uint_32) puntero_page_tarea); //stacks de anillo 3 y 0 para la tarea void* task_stack3 = mm_mem_alloc(); void* task_stack0 = mm_mem_alloc(); printf(" >loader_load: pfi after allocs: kernel = %x | usr = %x", *kernel_pf_info, *usr_pf_info); //ver esto donde van mapeados los stacks mm_page_map(STACK_3_VIRTUAL, task_dir, (uint_32) task_stack3, 0, USR_STD_ATTR); mm_page_map(STACK_0_VIRTUAL, task_dir, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //TODO ver estas direcciones temporales donde ponerlas mm_page_map(KERNEL_TEMP_PAGE,(mm_page *) old_cr3, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //inicializamos la pila de nivel 0 para que tenga el contexto para //poder volver del switchto uint_32* stack0 = (uint_32*) (KERNEL_TEMP_PAGE + 0xffC); *stack0-- = 0x23; *stack0-- = STACK_3_VIRTUAL + 0x1000; *stack0-- = 0x202; *stack0-- = (pl)? 0x1B : 0x08; //Elijo el selector de segmento según el privilegio de la tarea *stack0-- = (uint_32) f->_main; *stack0-- = (uint_32) &task_ret; *stack0-- = resp(); *stack0-- = 0x0; *stack0-- = 0x0; *stack0-- = 0x0; mm_page_map((uint_32) f->mem_start, task_dir, (uint_32) puntero_page_tarea, 0, USR_STD_ATTR); //mapeo la direccion virtual temporal para copiar en la pagina que recien se me asigno. mm_page_map((uint_32) KERNEL_TEMP_PAGE,(mm_page *) old_cr3, (uint_32) puntero_page_tarea, 0, USR_STD_ATTR); tlbflush(); //copio la tarea desde donde esta a la pagina que acabo de mapear. uint_8* addr_to_copy = (uint_8*) KERNEL_TEMP_PAGE; uint_8* task_to_copy = (uint_8*) f; uint_32 cant_to_copy = f->mem_end_disk - f->mem_start; int i; printf(" >loader_load: task_to_copy = %x", task_to_copy); for (i = 0; i < cant_to_copy; i++) { *addr_to_copy++ = *task_to_copy++; } //tengo que armar la estreuctura uint_32 requested_pid = get_new_pid(); task_table[requested_pid].cr3 = (uint_32) task_dir; task_table[requested_pid].esp0 = STACK_0_VIRTUAL + 0xFD8; mm_page_free(KERNEL_TEMP_PAGE, (mm_page *) old_cr3); tlbflush(); sched_load(requested_pid); tasks_running++; printf(" >loader_load: finished loading to new pid %d", requested_pid); return requested_pid; }
uint_32 sys_fork(uint_32 org_eip, uint_32 org_esp) { //me guardo el cr3 viejo. uint_32 old_cr3 = rcr3(); printf(" >sys_fork: org_eip (%x), org_esp (%x)", org_eip, org_esp); //pido un directorio para la nueva tarea void* new_cr3 = mm_dir_fork((mm_page*) old_cr3); if (new_cr3 == NULL) { //No pudo hacerse fork de la estrucutra de paginación printf("! >sys_fork: no se pudo crear el directorio de la nueva tarea"); return -1; } printf(" >sys_fork: new_cr3 = %x", new_cr3); //stacks de anillo 3 y 0 para la tarea void* task_stack3 = mm_mem_alloc(); void* task_stack0 = mm_mem_alloc(); printf(" >sys_fork: paginas stack_ kernel %x | usr %x", task_stack0, task_stack3); //ver esto donde van mapeados los stacks mm_page_map(STACK_3_VIRTUAL, new_cr3, (uint_32) task_stack3, 0, USR_STD_ATTR); mm_page_map(STACK_0_VIRTUAL, new_cr3, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //TODO ver estas direcciones temporales donde ponerlas mm_page_map(KERNEL_TEMP_PAGE,(mm_page *) old_cr3, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //inicializamos la pila de nivel 0 para que tenga el contexto para //poder volver del switchto uint_32* stack0 = (uint_32*) (KERNEL_TEMP_PAGE + 0xffC); *stack0-- = 0x23; *stack0-- = org_esp; *stack0-- = 0x202; *stack0-- = 0x1B; *stack0-- = org_eip; *stack0-- = (uint_32) &fork_ret; *stack0-- = resp(); *stack0-- = 0x0; *stack0-- = 0x0; *stack0-- = 0x0; //Copio la pila de usuario como está //Innecesario, ya lo hace el fork mm_copy_vf((uint_32*)STACK_3_VIRTUAL, (uint_32)task_stack3, PAGE_SIZE); mm_page_free(KERNEL_TEMP_PAGE, (mm_page*) old_cr3); tlbflush(); //tengo que armar la estructura de proceso uint_32 requested_pid = get_new_pid(); task_table[requested_pid].cr3 = (uint_32) new_cr3; task_table[requested_pid].esp0 = STACK_0_VIRTUAL + 0xFD8; //Duplico los file descriptor actualizando referencias device_fork_descriptors(cur_pid, requested_pid); // esto esta mal.. tiene q decidir q numero devolver creo q necesitamos un semaforo! sched_load(requested_pid); tasks_running++; printf(" >sys_fork: forkeo finalizado en pid %d", requested_pid); mm_dump(); return requested_pid; }
void *initialize_user_process(void *arg){ PCB *user_process; Jval jval_pcb; Jval user_process_child_node; char **filename; int base; int arg_count; int errno; int i; arg_count = 0; errno = 0; i = 0; /* Unmarshalling */ filename = (char **) arg; /* Create the global init process */ init = (PCB *)malloc(sizeof(PCB)); init->registers = (int *)malloc(sizeof(int) * NumTotalRegs); // Initialize init's registers */ for (i = 0; i < NumTotalRegs; i++) { init->registers[i] = 0; } // Initialize init's other variables init->pid = (int *)0; init->waiter = make_kt_sem(0); init->waiters = new_dllist(); init->children = make_jrb(); /* Allocate new PCB and initialize registers */ user_process = (PCB *)malloc(sizeof(PCB)); user_process->registers = (int *)malloc(NumTotalRegs * sizeof(int)); for (i = 0; i < NumTotalRegs; i++) { user_process->registers[i] = 0; } // Obtain pid and partiton memory for new process user_process->pid = (int *)get_new_pid(); base = partition_memory(user_process->pid); // Initialize first process' other variables user_process->waiter = make_kt_sem(0); user_process->waiters = new_dllist(); user_process->children = make_jrb(); // Set base and limit for new process user_process->base = 0; user_process->limit = MemorySize/8; // Set User global vars User_Base = base; User_Limit = user_process->limit; // Set process' PCRegs user_process->registers[PCReg] = 0; user_process->registers[NextPCReg] = 4; // Set first process' parent as init and add to init's children user_process->parent = (struct PCB *)init; user_process_child_node.v = user_process; jrb_insert_int(init->children, (int)user_process->pid, user_process_child_node); // Get number of args and turn off exec flag. while (filename[arg_count] != NULL) { arg_count++; } totalArgs = arg_count; is_exec = 0; /* Call perform_execve */ errno = perform_execve(user_process, filename[0], filename); // If errors, returns proper errno if (errno != 1) { syscall_return(user_process, errno); } else { // Puts new job onto readyQ and calls kt_exit() jval_pcb.v = user_process; dll_append(readyQ, jval_pcb); kt_exit(); } }