// Given a parent process's page table, create a copy // of it for a child. // CHANGE: copy on write pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i, flags; if((d = setupkvm()) == 0) return 0; // CHANGE TREINHART TO 4096 for(i = 4096; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); *pte = *pte & (~PTE_W); *pte = *pte | PTE_COW; pa = PTE_ADDR(*pte); flags = PTE_FLAGS(*pte); //CHANGE: update reference counts if(mappages(d, (void*)i, PGSIZE, pa, flags) < 0) goto bad; r_c.ref_count[pa/ 4096] ++; } flushtlb(); return d; bad: freevm(d); return 0; }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int asynwait(void) { struct proc *p; int pid; acquire(&ptable.lock); // Scan through table looking for zombie children. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != proc) continue; if(p->state == ZOMBIE){ // Found one. pid = p->pid; kfree(p->kstack); p->kstack = 0; freevm(p->pgdir); p->state = UNUSED; p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } release(&ptable.lock); return -1; }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; for(i = PGSIZE; i < sz; i += PGSIZE) { if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } return d; bad: freevm(d); return 0; }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i, flags; char *mem; if((d = setupkvm()) == 0) return 0; for(i = 0; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) continue; // panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); flags = PTE_FLAGS(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)p2v(pa), PGSIZE); if(mappages(d, (void*)i, PGSIZE, v2p(mem), flags) < 0) goto bad; } return d; bad: freevm(d); return 0; }
static int restore(struct checkpoint_t *ch) { pde_t *d; uint i; char *mem; if((d = setupkvm()) == 0) return -1; for(i = 0; i < ch->p.sz; i += PGSIZE){ if((mem = kalloc()) == 0) goto bad; memmove(mem, (ch->pages) + i, PGSIZE); if(mappages(d, (char*)i, PGSIZE, v2p(mem), (ch->flags)[i / PGSIZE]) < 0) goto bad; } struct proc np; struct trapframe tf; np.pgdir = d; tf = ch->tf; *np.tf = tf; return procload(&np); bad: freevm(d); return -1; }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; int found_p = 0, first_p = 0; acquire(&ptable.lock); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != proc) continue; havekids = 1; if(p->state == ZOMBIE && !p->is_thread && p->num_of_thread_child == 0){ found_p = p->pid; break; } } if(found_p){ // we found it a zombie procces with zombi kids (adams family) for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->pid != found_p){ continue; } if(!first_p) { freevm(p->pgdir); first_p = 1; } pid = p->pid; kfree(p->kstack); p->kstack = 0; p->state = UNUSED; p->pid = 0; p->parent = 0; p->killed = 0; } } if(found_p){ release(&ptable.lock); return pid; } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; //<(- //CHANGED i = 0, < sz for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 1)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)){ panic("copyuvm: page not present"); } else{ pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } } cprintf("Last addr copied from code: %x\n", i-PGSIZE); //copy stack for(i = USERTOP-proc->stacksz; i < USERTOP; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 1)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)){ panic("copyuvm: page not present"); } else{ pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } } cprintf("Last addr copied from code: %x\n", i-PGSIZE); return d; bad: freevm(d); return 0; }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; acquire(&ptable.lock); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if((p->parent != proc) || (p->parentind > 0)) continue; havekids = 1; if((p->state == ZOMBIE)){ // Found one. pid = p->pid; cprintf("in wait by %s\n",p->name); kfree(p->kstack); p->kstack = 0; if(!(ptable.proc[p->parentind]).children) { //only free if p is the last reference to shared memory cprintf("proc is %s\n",proc->name); cprintf("freeing %s's pgdir\n",p->name); freevm(p->pgdir); }else{ (ptable.proc[p->parentind]).children--; cprintf("%s children decremented to %d\n",ptable.proc[p->parentind].name,ptable.proc[p->parentind].children); } p->state = UNUSED; p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; acquire(&ptable.lock); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != proc) continue; havekids = 1; if(p->state == ZOMBIE){ cprintf("my pid is %d\n", proc->pid); cprintf("killing my child, process %d\n", p->pid); // Found one. pid = p->pid; kfree(p->kstack); p->kstack = 0; int j; for(j = 0; j < 4; j++) { proc->child_shmems[j] = p->shmems[j]; } freevm(p->pgdir); p->state = UNUSED; p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } }
// TODO(byan23): Copy the stack at the end of addr space. // Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; // Copy code + heap. if (proc->pid == 1) i = 0; else i = PGSIZE; for(; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } //cprintf("before coping stack from pid %d.\n", proc->pid); // TODO(byan23): Copy more stack as it grows. // Copy stack. i = USERTOP - proc->ssz; //i = USERTOP - PGSIZE; if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; return d; bad: freevm(d); return 0; }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz, uint s_sz) { pde_t *d; pte_t *pte; uint pa, i, stack_size; char *mem; if((d = setupkvm()) == 0) return 0; // Start at PGSIZE to make the first page invalid for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } // We need to loop again to copy the stack over stack_size = s_sz; for(i = stack_size; i < USERTOP; i+= PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } return d; bad: freevm(d); return 0; }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; acquire(&ptable.lock); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != proc) continue; havekids = 1; if(p->state == ZOMBIE){ // Found one. pid = p->pid; // free VM and stack only if child is not a thread if(p->isthread == 0){ kfree(p->kstack); freevm(p->pgdir); } p->kstack = 0; p->pgdir = 0; p->state = UNUSED; p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } return 0; }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; acquire(&ptable.lock); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != proc) continue; havekids = 1; if(p->state == ZOMBIE){ // Found one. pid = p->pid; kfree(p->kstack); p->kstack = 0; freevm(p->pgdir); p->state = UNUSED; #ifdef USE_CS333_SCHEDULER addToFreeList(p); #endif p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; acquire(&ptable.lock); //cprintf("Urmish in wait proc %s\n",proc->name); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != proc) continue; havekids = 1; if(p->state == ZOMBIE){ // Found one. pid = p->pid; kfree(p->kstack); p->kstack = 0; freevm(p->pgdir); p->state = UNUSED; p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); //cprintf("Urmish in wait bitiya nahi milat \n"); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; acquire(&ptable.lock); for(;;){ // Scan through table looking for zombie children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ //going through the process table if(p->parent != proc || p->clonecalled == 1) //if it is not the parent continue; havekids = 1;//means proc has kids if(p->state == ZOMBIE){//zombie means that it is done running but //has not terminated // Found one. pid = p->pid; kfree(p->kstack); p->kstack = 0; freevm(p->pgdir);//frees addr space p->state = UNUSED; p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || proc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(proc, &ptable.lock); //DOC: wait-sleep } }
// Given a parent process's page table, create a copy // of it for a child. pgd_t* copyuvm (pgd_t *pgdir, uint sz) { pgd_t *d; pte_t *pte; uint64 pa, i, ap; char *mem; // allocate a new first level page directory d = kpt_alloc(); if (d == NULL ) { return NULL ; } // copy the whole address space over (no COW) for (i = 0; i < sz; i += PTE_SZ) { if ((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) { panic("copyuvm: pte should exist"); } if (!(*pte & (ENTRY_PAGE | ENTRY_VALID))) { panic("copyuvm: page not present"); } pa = PTE_ADDR (*pte); ap = PTE_AP (*pte); if ((mem = alloc_page()) == 0) { goto bad; } memmove(mem, (char*) p2v(pa), PTE_SZ); if (mappages(d, (void*) i, PTE_SZ, v2p(mem), ap) < 0) { goto bad; } } return d; bad: freevm(d); return 0; }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz, uint stack_addr) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } // Copy the last page which is the new stack if((pte = walkpgdir(pgdir, (void*)(USERTOP-PGSIZE), 1)) == 0)//undestand what pgdir does panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); //cprintf(" last page is %d\n",pte); pa = PTE_ADDR(*pte);// what pa are they getting from pte if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); // copying some stuff.. figure out what 1 page is and copying it if(mappages(d, (void*)USERTOP-PGSIZE, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0)//mapping into new address space and making it valid goto bad; return d; bad: freevm(d); return 0; }
// Wait for a child process to exit and return its pid. // Return -1 if this process has no children. int wait(void) { struct proc *p; int havekids, pid; struct proc *curproc = myproc(); acquire(&ptable.lock); for(;;){ // Scan through table looking for exited children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent != curproc) continue; havekids = 1; if(p->state == ZOMBIE){ // Found one. pid = p->pid; kfree(p->kstack); p->kstack = 0; freevm(p->pgdir); p->pid = 0; p->parent = 0; p->name[0] = 0; p->killed = 0; p->state = UNUSED; release(&ptable.lock); return pid; } } // No point waiting if we don't have any children. if(!havekids || curproc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) sleep(curproc, &ptable.lock); //DOC: wait-sleep } }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz,s_sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack one page away from USERTOP (at bottom // grow upwards) s_sz = (USERTOP - PGSIZE); if((s_sz = allocuvm(pgdir, s_sz, s_sz + PGSIZE)) == 0) goto bad; // Push argument strings, prepare rest of stack in ustack. sp = s_sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); s_sz = USERTOP - PGSIZE; // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->s_sz =s_sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); // cprintf("finish exec%d\t%d\n",sz,s_sz); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { cprintf("-(%d)exec...\n",proc->pid); char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // sx: passed Part 1 sz = PGSIZE;//PGSIZW = 4K for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; //no need to modify above///////////////////////// // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); /* if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) goto bad; sp = sz; */ // Push argument strings, prepare rest of stack in ustack. // sx:tst1///////////////// int sz_stack= 0; if((sz_stack = allocuvm(pgdir, USERTOP-PGSIZE, USERTOP))==0) panic("allocuvm sz_stack failed\n"); sp = sz_stack; ///////////////////////// cprintf("-exec: sp(%d)\n",sp); for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); cprintf("-exec:sz(%d)sp(%d)sz-sp(%d)elf.entry(%d)\n",sz,sp,USERTOP-sp,elf.entry); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz_stack;//current stack bottom proc->sz_stack = sz_stack-PGSIZE;//current stack top proc->sz_heap = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); cprintf("-exec end***\n"); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; char tmp_path[MAX_LNK_NAME]; /* A&T */ /* A&T use readlink to de-reference symbolic links */ if (k_readlink(path, tmp_path, MAX_LNK_NAME) != -1) { if((ip = namei(tmp_path)) == 0) return -1; } else { if((ip = namei(path)) == 0) return -1; } ilock(ip); //A&T checks if symlink /* for (i=0;i < 16 ; i++) { //prevents loops ,up to 16 chain links */ /* if (ip->flags & I_SYMLNK) { */ /* if((sym_ip = namei((char*)ip->addrs)) == 0) { */ /* iunlock(ip); */ /* return -1; */ /* } */ /* iunlock(ip); */ /* ip = sym_ip; */ /* ilock(ip); */ /* } else */ /* break; */ /* } */ /* if (i == 16) { */ /* panic("symbolic link exceeds 16 links "); */ /* } */ //A&T - end pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // Skip first page sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) goto bad; // Push argument strings, prepare rest of stack in ustack. sp = sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; // Set end of shared pages address to USERTOP proc->endSP = USERTOP; proc->sz = sz; // For each shared page set the shared page count to the memory count for (i = 0; i < SHMEM_PAGES; i++) { proc->shared_count[i] = mem_count[i]; } proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; // namei converts given path into inode begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header // if the file is smaller than the size of an elf header, // then it doesn't hold an elf header. (ERROR) if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // do this for each section of the elf file (chunk size dlineated // by sizeof program header) // allocate user virtual memory // load program into user virtual memory // in linux, run readelf -a /bin/ls and see the the offset and size // column program section header being loaded sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); // This is macro function that jumps to the next page boundary if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; // this makes the inaccessible page clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. // This code is building the stack frame of the application. // since argc is not passed into this function, to find the max // num of args, we need to step through the argv string until the // item returned is NULL or the end of the string. // This means that we have found all of the arguments. // Next, we need to copy each argument into the stack and keep // references to it in a local stack. Once this is done, we can // set the stack pointer to point to the first argument on the stack. // now, we can put the return value and the total number of args onto our // local stack. Then, we must prepare local stack for the copy into the // real stack. Next, we adjust the real stack pointer to make // room for our local stack and then we copy our stack that contains // pointers to each argument onto the stack. // We need this for quick lookup of each argument -- without the poitners // we can't efficiently get the args back. we also need the // the total number of arguments to make sure that we are growing the // stack properly. // think about this: int main(int argc, char **argv); // this code defends why we need a double pointer to a char. // we are giving an array of char *. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; // explain of ~3 in following line: // to make memory align with 4 bits, we the two lower order bit // which are the oly two bits that aren't divisibile by 4. // this is to keep the compiler aligned with the system sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; // This is getting the real stack ready for the copy // of the local stack, ustack[] ustack[2] = sp - (argc+1)*4; // argv pointer // this is moving the stack pointer to the location of first argument. sp -= (3+argc+1) * 4; // This is copying the ustack[] into the real stack if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // done buildng the stack frame // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. // leave first page inaccessible (to make NULL ref fail) sz = PGSIZE-1; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // hook up the old shared memory to the new addr space // (no need to change refcount, because the old ref goes away with // this exec, so it's +1 then -1 => 0 change if (proc->shared) { extern void mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm); mappages(pgdir, (char *)SHARED_V, PGSIZE, v2p(proc->shared->page), PTE_W|PTE_U); } // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; //// section check (either exist interp section) //// needed libsample.so.1 if (strcmp("share_main", path) == 0) { // share loader process (dummy of load ld-linux.so.2) //// mmap share library (libsample.so). sz = 0; /////// alloc physical memory cprintf("start %d \n", sz); ph.vaddr = 0x08048000; ph.memsz = 0x031a4 + 0x00130; sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz); cprintf("start4 %d \n", sz); /////// map pages to physical memory ph.off = 0x0; ph.filesz = 0x21a4 + 0x00124; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; cprintf("start3 %d \n", sz); iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = 0x80486d4; //.text proc->tf->esp = sp; cprintf("start2 %d \n", sz); switchuvm(proc); freevm(oldpgdir); return 0; //// rewrite bss valiable. //// stay loader program for delayed load. } // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sz_stk, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; sz = PGROUNDUP(sz); // CHANGE: Allocates the first page of the stack at the end of the user programs address space if((allocuvm(pgdir, USERTOP - PGSIZE, USERTOP)) == 0) goto bad; /* CHANGE: sets the sz_stk field equal to the top address of the stack */ sz_stk = USERTOP - PGSIZE; // Push argument strings, prepare rest of stack in ustack. sp = USERTOP; /* CHANGE: sets the stack pointer to the botom of the user space. */ for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->sz_stk = sz_stk; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; //cprintf("exec: size: %d, phva: %d phvamem:%d \n", sz, ph.va , ph.memsz); if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); //if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) // goto bad; uint stkptr = allocuvm(pgdir, USERTOP - PGSIZE, USERTOP); if(stkptr == 0) panic("dont know wht to do"); //proc->stkptr = USERTOP-PGSIZE; //cprintf("stkptr is : %d\n", stkptr); // Push argument strings, prepare rest of stack in ustack. sp = stkptr; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; //cprintf("sp value: %d\n",sp); } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // remzi video change //uint newstk = allocuvm(pgdir, USERTOP - PGSIZE, USERTOP); //if(newstk == 0) panic("dont know wht to do"); // Commit to the user image. proc->stkptr = USERTOP - PGSIZE; //proc->grdptr = USERTOP - PGSIZE - PGSIZE; oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }