// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; sz = proc->sz; if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->sz = sz; switchuvm(proc); return 0; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; // cprintf("Before acquire\n"); acquire(&locksbrk); // cprintf("After acquire\n"); sz = proc->sz; if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) { release(&locksbrk); return -1; } } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) { release(&locksbrk); return -1; } } proc->sz = sz; struct proc *p; acquire(&ptable.lock); for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(/*p->parent == proc &&*/ p->pgdir == proc->pgdir) p->sz=proc->sz; } release(&ptable.lock); // cprintf("Before release\n"); release(&locksbrk); // cprintf("After release\n"); switchuvm(proc); //release(&locksbrk); return 0; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; struct proc *curproc = myproc(); sz = curproc->sz; if(n > 0){ if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0) return -1; } curproc->sz = sz; switchuvm(curproc); return 0; }
// Allocate memory to the process to bring its size from oldsz to // newsz. Allocates physical memory and page table entries. oldsz and // newsz need not be page-aligned, nor does newsz have to be larger // than oldsz. Returns the new process size or 0 on error. int allocuvm(pde_t *pgdir, uint oldsz, uint newsz) { if(newsz > USERTOP) return 0; char *a = (char *)PGROUNDUP(oldsz); char *last = PGROUNDDOWN(newsz - 1); for (; a <= last; a += PGSIZE){ char *mem = kalloc(); if(mem == 0){ cprintf("allocuvm out of memory\n"); deallocuvm(pgdir, newsz, oldsz); return 0; } memset(mem, 0, PGSIZE); mappages(pgdir, a, PGSIZE, PADDR(mem), PTE_W|PTE_U); } return newsz > oldsz ? newsz : oldsz; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; if (proc->isThread == 1) { sz = proc->parent->sz; } else { sz = proc->sz; } if(n > 0) { if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0) { if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->sz = sz; switchuvm(proc); return 0; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; sz = proc->sz; // CHANGED if(n > 0){ if(sz + n > proc->s_sz - PGSIZE){ // CHANGED return -1; } if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->sz = sz; switchuvm(proc); return 0; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; sz = proc->heap_size; if ((sz + n) > (proc->stack_size - PGSIZE)) { return -1; } if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->heap_size = sz; switchuvm(proc); return 0; }
// Allocate page tables and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. int allocuvm(pde_t *pgdir, uint oldsz, uint newsz) { char *mem; uint a; if (newsz >= KERNBASE) return 0; if (newsz < oldsz) return oldsz; a = PGROUNDUP(oldsz); for (; a < newsz; a += PGSIZE) { mem = kalloc(); if (mem == 0) { deallocuvm(pgdir, newsz, oldsz); return 0; } memset(mem, 0, PGSIZE); mappages(pgdir, (char*) a, PGSIZE, v2p(mem), PTE_W | PTE_U); #ifndef NONE /* a&k start */ if (isNotInitShell(proc)) { int ans = 0; if ((proc->swapData).nPhysicalPages >= MAX_PSYC_PAGES) ans = swapOut(pgdir); if (ans < 0) panic("Can't swap out!"); #if defined(FIFO) || defined(SCFIFO) int index = addMemAddr(PGROUNDDOWN(a)); (proc->swapData).creationTime[index] = ticks; #endif #ifdef NFU addMemAddr(PGROUNDDOWN(a)); #endif } /* a&k end */ #endif } return newsz; }
//takes the pid of the process because using proc would end up in the process id of parent and not the child void freevmChild(pde_t *pgdir,struct proc* p) { uint i; if(pgdir == 0) panic("freevm: no pgdir"); cprintf("shared pages in freevm%d",p->procShmemCount); deallocuvm(pgdir, USERTOP-4096*p->procShmemCount, 0); int k; for(k=0;k<4;k++) { if(proc->bitmap) { dec_shmem_proc_count(k); } } for(i = 0; i < NPDENTRIES; i++){ if(pgdir[i] & PTE_P) kfree((char*)PTE_ADDR(pgdir[i])); } kfree((char*)pgdir); }
void swapOut(struct proc* p){ //create flie char id_as_str[3]; // need to pre determine number of digits in p->pid itoa(p->pid,id_as_str); char path[strlen(id_as_str) + 5]; strcat(path,0,id_as_str,".swap"); p->swapped_file = kernel_open(path,O_CREATE | O_WRONLY); pte_t *pte; int i; uint pa; for(i = 0; i < p->sz; i += PGSIZE){ if((pte = walkpgdir(p->pgdir, (void *) i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); //cprintf("p->swapped_file %d\n",p->swapped_file); if(filewrite(p->swapped_file,p2v(pa),PGSIZE) < 0) panic("filewrite: error in swapOut"); } int fd; for(fd = 0; fd < NOFILE; fd++){ if(p->ofile[fd] && p->ofile[fd] == p->swapped_file){ fileclose(p->ofile[fd]); p->ofile[fd] = 0; break; } } p->swapped_file = 0; p->swapped = 1; deallocuvm(p->pgdir,p->sz,0); p->state = SLEEPING_SUSPENDED; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; acquire(&ptable.lock); sz = proc->sz; if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0){ release(&ptable.lock); return -1; } } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) { release(&ptable.lock); return -1; } } proc->sz = sz; struct proc *p; //looping thru ptable to change szs -KC for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ //calling process is a thread, change parent and siblings if ( (proc->isThread == 1) && (p == proc->parent || p->parent == proc->parent) ) { p->sz = sz; } //calling process is a process, change child threads else if (proc->isThread == 0 && p->parent == proc) { p->sz = sz; } } release(&ptable.lock); switchuvm(proc); return 0; }
// Allocate page tables and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. int allocuvm(pde_t *pgdir, uint oldsz, uint newsz)//allocates memory from oldsz to newsz { char *mem; uint a; if(newsz > USERTOP) return 0; if(newsz < oldsz) return oldsz; a = PGROUNDUP(oldsz); for(; a < newsz; a += PGSIZE){ mem = kalloc();//gets physical memory to map to the address space if(mem == 0){ cprintf("allocuvm out of memory\n"); deallocuvm(pgdir, newsz, oldsz); return 0; } memset(mem, 0, PGSIZE); mappages(pgdir, (char*)a, PGSIZE, PADDR(mem), PTE_W|PTE_U);//virtual address maps 'a' to the physical memory mem and writable in address space } return newsz; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { acquire(&ptable.lock); uint sz; //struct proc* p; sz = proc->sz; if(n > 0) { if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) { release(&ptable.lock); return -1; } } else if(n < 0) { if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) { release(&ptable.lock); return -1; } } proc->sz = sz; if (proc->is_thread == 1) { proc = proc->parent; proc->sz = sz; } /*for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { if(p->parent == parent) { proc->sz = sz; } }*/ release(&ptable.lock); switchuvm(proc); return 0; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; acquire(&ptable.lock); sz = proc->sz; if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->sz = sz; if(proc->thread) // reflect the changes in the parent as well proc->parent->sz = sz; release(&ptable.lock); switchuvm(proc); return 0; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; //cprintf("Urmish - proc->stack_low = %d proc->sz = %d n = %d value = %d PGSIZE = %d\n", proc->stack_low, proc->sz, n, proc->stack_low - proc->sz -n, PGSIZE); if ((int)(proc->stack_low - proc->sz -n) < PGSIZE) { //cprintf("Urmish - Ee na de payi bhaiya!!\n"); return -1; } //cprintf("Urmish - Diyat hai bhaiya\n"); sz = proc->sz; if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->sz = sz; switchuvm(proc); return 0; }
// Allocate page tables and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. int allocuvm(pde_t *pgdir, uint oldsz, uint newsz) { char *mem; uint a; if(newsz >= USERBOUND) return 0; if(newsz < oldsz) return oldsz; a = PGROUNDUP(oldsz); for(; a < newsz; a += PGSIZE){ mem = kalloc(); if(mem == 0){ cprintf("allocuvm out of memory\n"); deallocuvm(pgdir, newsz, oldsz); return 0; } memset(mem, 0, PGSIZE); mappages(pgdir, (char*)a, PGSIZE, v2p(mem), UVMPDXATTR, UVMPTXATTR); } return newsz; }
// Allocate page tables and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. int allocuvm(pde_t *pgdir, uint oldsz, uint newsz) { char *mem; uint a; if(newsz > USERTOP) return 0; if(newsz < oldsz) return oldsz; a = PGROUNDUP(oldsz); for(; a < newsz; a += PGSIZE){ mem = kalloc(); if(mem == 0){ cprintf("allocuvm out of memory\n"); deallocuvm(pgdir, newsz, oldsz); return 0; } memset(mem, 0, PGSIZE); mappages(pgdir, (char*)a, PGSIZE, PADDR(mem), PTE_W|PTE_U); } return newsz; }
// Allocate page tables and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. int allocuvm(pde_t *pgdir, uint oldsz, uint newsz) { char *mem; uint a; if((newsz >= KERNBASE)||( newsz >= (uint)(p2v(PHYSTOP) - proc->ssm))) return 0; if(newsz < oldsz) return oldsz; a = PGROUNDUP(oldsz); for(; a < newsz; a += PGSIZE){ mem = kalloc(); if(mem == 0){ cprintf("allocuvm out of memory\n"); deallocuvm(pgdir, newsz, oldsz); return 0; } memset(mem, 0, PGSIZE); mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U); } return newsz; }
// Grow current process's memory by n bytes. // Return 0 on success, -1 on failure. int growproc(int n) { uint sz; sz = proc->sz; if(n > 0){ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) return -1; } proc->sz = sz; struct proc *p; acquire(&ptable.lock); for(p=ptable.proc; p<&ptable.proc[NPROC]; p++){ if(p->parent!=proc || 1==p->thread) p->sz = sz; } release(&ptable.lock); switchuvm(proc); return 0; }
//PAGEBREAK: 41 void trap(struct trapframe *tf) { if(tf->trapno == T_SYSCALL){ if(proc->killed) exit(); proc->tf = tf; syscall(); if(proc->killed) exit(); return; } switch(tf->trapno){ case T_IRQ0 + IRQ_TIMER: if(cpu->id == 0){ acquire(&tickslock); ticks++; wakeup(&ticks); // We're in user space if(proc && (tf->cs & 3) == DPL_USER) { //is the alarm set? if(proc->alarmticks != 0 && proc->alarmhandler != 0) { proc->alarmticksleft--; if(proc->alarmticksleft == 0) { proc->tf->esp--; *(uint*)proc->tf->esp = proc->tf->eip; proc->tf->eip = (uint)proc->alarmhandler; proc->alarmticksleft = proc->alarmticks; } } } release(&tickslock); } lapiceoi(); break; case T_IRQ0 + IRQ_IDE: ideintr(); lapiceoi(); break; case T_IRQ0 + IRQ_IDE+1: // Bochs generates spurious IDE1 interrupts. break; case T_IRQ0 + IRQ_KBD: kbdintr(); lapiceoi(); break; case T_IRQ0 + IRQ_COM1: uartintr(); lapiceoi(); break; case T_IRQ0 + 7: case T_IRQ0 + IRQ_SPURIOUS: cprintf("cpu%d: spurious interrupt at %x:%x\n", cpu->id, tf->cs, tf->eip); lapiceoi(); break; //PAGEBREAK: 13 default: if(proc == 0 || (tf->cs&3) == 0){ // In kernel, it must be our mistake. cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", tf->trapno, cpu->id, tf->eip, rcr2()); panic("trap"); } // In user space, check whether it is an access to an lazy allocated address if(tf->trapno == T_PGFLT) { char *mem; uint a; a = PGROUNDDOWN(rcr2()); mem = kalloc(); if(mem == 0){ cprintf("allocuvm out of memory\n"); deallocuvm(proc->pgdir, a+PGSIZE, rcr2()); exit(); } memset(mem, 0, PGSIZE); mappages(proc->pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U); } else { //If not, the user program is misbehaving cprintf("pid %d %s: trap %d err %d on cpu %d " "eip 0x%x addr 0x%x--kill proc\n", proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, rcr2()); proc->killed = 1; } } // Force process exit if it has been killed and is in user space. // (If it is still executing in the kernel, let it keep running // until it gets to the regular system call return.) if(proc && proc->killed && (tf->cs&3) == DPL_USER) exit(); // Force process to give up CPU on clock tick. // If interrupts were on while locks held, would need to check nlock. if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER) yield(); // Check if the process has been killed since we yielded if(proc && proc->killed && (tf->cs&3) == DPL_USER) exit(); }