int sys_close(int fd) { struct sys_filemapping *mpg; struct process *proc; proc_filemapping *pmpg; int sys_index; mpg = resolvefd(fd); if (mpg==NULL) return -EBADF; lock_acquire(filetable_lock); mpg->refcnt--; proc = getcurprocess(); /* should never fail seeing how we just resolved it */ pmpg = (proc_filemapping *) array_getguy(proc->filetable, fd); sys_index = *pmpg; kfree(pmpg); array_setguy(proc->filetable, fd, NULL); if(mpg->refcnt>0) { lock_release(filetable_lock); return 0; } /* no more references to mapping */ vfs_close(mpg->vn); kfree(mpg); if (sys_index < array_getnum(proc->filetable)) array_setguy(proc->filetable, sys_index, NULL); lock_release(filetable_lock); return 0; }
int ft_set(struct filetable* ft, struct filedescriptor* fd, int fti) { if (fti >= ft_array_size(ft)) { return 1; } array_setguy(ft->filedescriptor, fti, fd); if (ft_get(ft, fti) == fd) { return 1; } return 0; }
/* * ft_remove() * This removes the file descriptor from the file table, it will add the file * descriptor id to the queue of availiable ids to use. */ int ft_remove(struct filetable* ft, int fti) { struct filedescriptor * fd = ft_get(ft, fti); if (fd != NULL) { // q_addtail(ft->nextfiledescriptor, (void *) fd->fdn); int spl = splhigh(); fd->numOwners--; if (fd->numOwners == 0) { vfs_close(fd->fdvnode); kfree(fd); } splx(spl); array_setguy(ft->filedescriptor, fti, NULL); } return 1; }
/* * ft_add() * This adds the file descriptor to the file table, it does by checking if there * is a free file descriptor in the queue, if not, it will add to the end of the * array. This will recover and reuse closed file descriptor ids. */ int ft_add(struct filetable* ft, struct filedescriptor* fd) { int fdn = 0; for (fdn = 0; fdn < ft_array_size(ft) && fdn < OPEN_MAX; fdn++) { if (ft_get(ft, fdn) == NULL) { array_setguy(ft->filedescriptor, fdn, fd); return fdn; } } if (fdn == OPEN_MAX) { return -1; } if (array_add(ft->filedescriptor, fd) != 0) { //if error (ENOMEM) return -1; } fd->numOwners++; assert(fdn != 0); return fdn; }
/* * as_fault: fault handling. Handle a fault on an address space, of * specified type, at specified address. * * Synchronization: none. We assume the address space is not shared, * so we don't lock it. */ int as_fault(struct addrspace *as, int faulttype, vaddr_t va) { struct vm_object *faultobj = NULL; struct lpage *lp; vaddr_t bot=0, top; int i, index, result; /* Find the vm_object concerned */ for (i=0; i<array_getnum(as->as_objects); i++) { struct vm_object *vmo; vmo = array_getguy(as->as_objects, i); bot = vmo->vmo_base; top = bot + PAGE_SIZE*array_getnum(vmo->vmo_lpages); if (va >= bot && va < top) { faultobj = vmo; break; } } if (faultobj==NULL) { DEBUG(DB_VM, "vm_fault: EFAULT: va=0x%x\n", va); return EFAULT; } /* Now get the logical page */ index = (va - bot) / PAGE_SIZE; lp = array_getguy(faultobj->vmo_lpages, index); if (lp == NULL) { /* zerofill page */ result = lpage_zerofill(&lp); if (result) { kprintf("vm: zerofill fault at 0x%x failed\n", va); return result; } array_setguy(faultobj->vmo_lpages, index, lp); } return lpage_fault(lp, as, faulttype, va); }