int mon_backtrace(int argc, char **argv, struct Trapframe *tf) { // Your code here. uint32_t eip=read_eip(); uint32_t ebp=read_ebp(); uint32_t esp=ebp; int i; struct Eipdebuginfo info; cprintf("Stack backtrace:\n"); // in Entry.S it sets ebp to 0 at first,so if ebp==0 then we know that there is no more stack. while(ebp!=0) { cprintf("ebp %08x eip %08x args ",ebp,eip); // pop the saved ebp to current ebp. ebp=*(uint32_t *)esp; esp+=4; // pop the saved eip to current eip. eip=*(uint32_t *)esp; esp+=4; for(i=0;i<=4;i++){ cprintf("%08x ",*(uint32_t *)esp); esp+=4; } cprintf("\n"); cprintf(" "); debuginfo_eip(eip,&info); cprintf("%s:%d: ",info.eip_file, info.eip_line); cprintf("%.*s",info.eip_fn_namelen, info.eip_fn_name); cprintf("+%d", eip-info.eip_fn_addr); cprintf("\n"); esp=ebp; } return 0; }
task_t* create_process(char* name, uint32_t eip, bool wants_stack) { Deprecated(); task_t* parent = current_task; //clone address space page_directory_t* cloned = vmm_clone_active_pdir(); //create new process task_t* task = kmalloc(sizeof(task_t)); memset(task, 0, sizeof(task_t)); task->name = strdup(name); task->id = next_pid++; task->page_dir = cloned; task->child_tasks = array_m_create(32); //task->kernel_stack = kmalloc_a(KERNEL_STACK_SIZE); setup_fds(task); uint32_t current_eip = read_eip(); if (current_task == parent) { task->eip = current_eip; return task; } task->state = RUNNABLE; task->wake_timestamp = 0; task->vmem_slide = 0; task->windows = array_m_create(16); return task; }
int do_fork(unsigned flags) { assert(current_task && kernel_task); assert(running_processes < (unsigned)MAX_TASKS || MAX_TASKS == -1); addr_t eip; task_t *task = task_create(); page_dir_t *newspace; if(flags & FORK_SHAREDIR) newspace = vm_copy(current_task->pd); else newspace = vm_clone(current_task->pd, 0); if(!newspace) { kfree((void *)task); return -ENOMEM; } /* set the address space's entry for the current task. * this is a fast and easy way to store the "what task am I" data * that gets automatically updated when the scheduler switches * into a new address space */ arch_specific_set_current_task(newspace, (addr_t)task); /* Create the new task structure */ task->pd = newspace; copy_task_struct(task, current_task, flags & FORK_SHAREDAT); add_atomic(&running_processes, 1); /* Set the state as usleep temporarily, so that it doesn't accidentally run. * And then add it to the queue */ task->state = TASK_USLEEP; tqueue_insert(primary_queue, (void *)task, task->listnode); cpu_t *cpu = (cpu_t *)current_task->cpu; #if CONFIG_SMP cpu = fork_choose_cpu(current_task); #endif /* Copy the stack */ set_int(0); engage_new_stack(task, current_task); /* Here we read the EIP of this exact location. The parent then sets the * eip of the child to this. On the reschedule for the child, it will * start here as well. */ volatile task_t *parent = current_task; store_context_fork(task); eip = read_eip(); if(current_task == parent) { /* These last things allow full execution of the task */ task->eip=eip; task->state = TASK_RUNNING; task->cpu = cpu; add_atomic(&cpu->numtasks, 1); tqueue_insert(cpu->active_queue, (void *)task, task->activenode); __engage_idle(); return task->pid; } return 0; }
static void unwind_stack(void **ebp, void *end) { void *eip = (void *)read_eip(); unsigned int i = 0; while (eip >= (void *)0x10000 && eip <= end && ebp) { symbol_t *sym = get_closest_symbol(eip); if (sym == NULL) { kprintf(" #%d %p in ???\n", i, eip); kprintf("(stack appears to be trashed -- aborting trace)\n"); break; } else { kprintf(" #%d %p in %s ()\n", i++, eip, sym->name); } /* unwind */ eip = ebp[1]; ebp = (void **)ebp[0]; } }
// TODO: fork kurallari duzenlenmeli (neler kopyalanacak, neler kopyalanmayacak?) int do_fork() { CLOBBERED_REGISTERS_ALL(); /* debug only */ uint32_t mem_before_setup_vm = 0; uint32_t mem_before_copy_pages = 0; uint32_t mem_before_kernel_stack = 0; /* */ int r; Task *t; uint32_t eip; int e = 0; // error (bad_fork_* icin) pushcli(); // ASSERT_int_disable(); t = (Task*)kmalloc(sizeof(Task)); if (!t) goto bad_fork_task_alloc; memcpy(t, task_curr, sizeof(Task)); t->init(); t->parent = task_curr; t->state = Task::State_not_runnable; /* -- */ mem_before_setup_vm = mem_free(); r = task_setup_vm(t, &task_curr->pgdir); if (r < 0) goto bad_fork_setup_vm; /* user adres uzayini kopyala */ mem_before_copy_pages = mem_free(); r = t->pgdir.copy_pages(&task_curr->pgdir, MMAP_USER_BASE, MMAP_USER_SHARED_MEM_BASE); if (r < 0) goto bad_fork_copy_vm_user; /* shared memory kismini kopyalama, shm_fork fonksiyonu kopyalayacak */ r = t->pgdir.copy_pages(&task_curr->pgdir, MMAP_USER_SHARED_MEM_TOP, MMAP_USER_TOP); if (r < 0) goto bad_fork_copy_vm_user; t->pgdir.count_program = task_curr->pgdir.count_program; t->pgdir.count_stack = task_curr->pgdir.count_stack; t->pgdir.start_brk = task_curr->pgdir.start_brk; t->pgdir.end_brk = task_curr->pgdir.end_brk; /* */ /* ipc veriyapilari icin, ipc_fork */ r = ipc_fork(t); if (r < 0) goto bad_fork_ipc; r = fs_fork(t); if (r < 0) goto bad_fork_fs; /* kernel stackini kopyala */ mem_before_kernel_stack = mem_free(); r = t->pgdir.copy_pages(&task_curr->pgdir, MMAP_KERNEL_STACK_BASE, MMAP_KERNEL_STACK_TOP); if (r < 0) goto bad_fork_copy_kernel_stack; /* burasi 2 kere calisiyor */ eip = read_eip(); if (eip == 1) /* child process'de popif yapilmamali */ return 0; /* child prosesin register bilgileri */ t->k_eip = eip; read_reg(%esp, t->k_esp); read_reg(%ebp, t->k_ebp); /* child prosesin baslangic zamani */ t->time_start = jiffies; /* child listesine ekle */ ASSERT( task_curr->childs.push_back(&t->childlist_node) ); /* process id ata ve runnable listesine ekle */ set_task_id(t); add_to_runnable_list(t); popif(); return t->id; bad_fork_copy_kernel_stack: if (e++ == 0) print_warning("!! bad_fork_copy_kernel_stack\n"); task_free_kernel_stack(t); ASSERT(mem_free() == mem_before_kernel_stack); bad_fork_fs: // TODO: -- bad_fork_ipc: // TODO: -- bad_fork_copy_vm_user: if (e++ == 0) print_warning("!! bad_fork_copy_vm_user\n"); task_free_vm_user(t); ASSERT(mem_free() == mem_before_copy_pages); bad_fork_setup_vm: if (e++ == 0) print_warning("!! bad_fork_setup_vm\n"); task_delete_vm(t); ASSERT(mem_free() == mem_before_setup_vm); kfree(t); t = NULL; bad_fork_task_alloc: if (e++ == 0) print_warning("!! bad_fork_task_alloc\n"); ASSERT(t == NULL); popif(); return -1; }