// Make file descriptor 'newfdnum' a duplicate of file descriptor 'oldfdnum'. // For instance, writing onto either file descriptor will affect the // file and the file offset of the other. // Closes any previously open file descriptor at 'newfdnum'. // This is implemented using virtual memory tricks (of course!). int dup(int oldfdnum, int newfdnum) { int r; char *ova, *nva; pte_t pte; struct Fd *oldfd, *newfd; if ((r = fd_lookup(oldfdnum, &oldfd)) < 0) return r; close(newfdnum); newfd = INDEX2FD(newfdnum); ova = fd2data(oldfd); nva = fd2data(newfd); if ((vpd[VPD(ova)] & PTE_P) && (vpt[VPN(ova)] & PTE_P)) if ((r = sys_page_map(0, ova, 0, nva, vpt[VPN(ova)] & PTE_SYSCALL)) < 0) goto err; if ((r = sys_page_map(0, oldfd, 0, newfd, vpt[VPN(oldfd)] & PTE_SYSCALL)) < 0) goto err; return newfdnum; err: sys_page_unmap(0, newfd); sys_page_unmap(0, nva); return r; }
int fd_alloc(struct Fd **fd) { // Find the smallest i from 0 to MAXFD-1 that doesn't have // its fd page mapped. Set *fd to the fd page virtual address. // (Do not allocate a page. It is up to the caller to allocate // the page. This means that if someone calls fd_alloc twice // in a row without allocating the first page we return, we'll // return the same page the second time.) // Return 0 on success, or an error code on error. u_int va; u_int fdno; for (fdno = 0; fdno < MAXFD - 1; fdno++) { va = INDEX2FD(fdno); if (((* vpd)[va / PDMAP] & PTE_V) == 0) { *fd = (struct Fd *)va; return 0; } if (((* vpt)[va / BY2PG] & PTE_V) == 0) { //the fd is not used *fd = (struct Fd *)va; return 0; } } return -E_MAX_OPEN; }
// Finds the smallest i from 0 to MAXFD-1 that doesn't have // its fd page mapped. // Sets *fd_store to the corresponding fd page virtual address. // // fd_alloc does NOT actually allocate an fd page. // It is up to the caller to allocate the page somehow. // This means that if someone calls fd_alloc twice in a row // without allocating the first page we return, we'll return the same // page the second time. // // Hint: Use INDEX2FD. // // Returns 0 on success, < 0 on error. Errors are: // -E_MAX_FD: no more file descriptors // On error, *fd_store is set to 0. int fd_alloc(struct Fd **fd_store) { int i; assert(fd_store != 0); *fd_store = 0; // LAB 5: Your code here. for (i = 0; i < MAXFD; i++) { if (!va_is_mapped(INDEX2FD(i))) { *fd_store = INDEX2FD(i); return 0; } } return -E_MAX_OPEN; }
// Check that fdnum is in range and mapped. // If it is, set *fd_store to the fd page virtual address. // // Returns 0 on success (the page is in range and mapped), < 0 on error. // Errors are: // -E_INVAL: fdnum was either not in range or not mapped. int fd_lookup(int fdnum, struct Fd **fd_store) { // LAB 5: Your code here. if(fdnum < 0 || fdnum > MAXFD) return -E_INVAL; else *fd_store = INDEX2FD(fdnum); if((vpd[PDX(*fd_store)] & PTE_P) == 0 || (vpd[VPN(*fd_store)] & PTE_P) == 0 ) return -E_INVAL; else return 0; return -E_INVAL; }
// Check that fdnum is in range and mapped. // If it is, set *fd_store to the fd page virtual address. // // Returns 0 on success (the page is in range and mapped), < 0 on error. // Errors are: // -E_INVAL: fdnum was either not in range or not mapped. int fd_lookup(int fdnum, struct Fd **fd_store) { struct Fd *fd; if (fdnum >= 0 && fdnum < MAXFD) { fd = INDEX2FD(fdnum); if (pageref(fd) > 0) { *fd_store = fd; return 0; } } *fd_store = 0; return -E_INVAL; }
// Finds the smallest i from 0 to MAXFD-1 that doesn't have // its fd page mapped. // Sets *fd_store to the corresponding fd page virtual address. // // fd_alloc does NOT actually allocate an fd page. // It is up to the caller to allocate the page somehow. // This means that if someone calls fd_alloc twice in a row // without allocating the first page we return, we'll return the same // page the second time. // // Hint: Use INDEX2FD. // // Returns 0 on success, < 0 on error. Errors are: // -E_MAX_FD: no more file descriptors // On error, *fd_store is set to 0. int fd_alloc(struct Fd **fd_store) { // LAB 5: Your code here. int i; for(i=0;i<MAXFD;i++){ *fd_store = INDEX2FD(i); if((vpd[PDX(*fd_store)] & PTE_P) == 0 || (vpd[VPN(*fd_store)] & PTE_P) == 0 ){ cprintf("fdnum:%d\n",i); return 0; } } *fd_store = 0; return -E_MAX_OPEN; }
// Finds the smallest i from 0 to MAXFD-1 that doesn't have // its fd page mapped. // Sets *fd_store to the corresponding fd page virtual address. // // fd_alloc does NOT actually allocate an fd page. // It is up to the caller to allocate the page somehow. // This means that if someone calls fd_alloc twice in a row // without allocating the first page we return, we'll return the same // page the second time. // // Hint: Use INDEX2FD. // // Returns 0 on success, < 0 on error. Errors are: // -E_MAX_FD: no more file descriptors // On error, *fd_store is set to 0. int fd_alloc(struct Fd **fd_store) { int i; struct Fd *fd; for (i = 0; i < MAXFD; i++) { fd = INDEX2FD(i); if ((vpd[VPD(fd)] & PTE_P) == 0 || (vpt[VPN(fd)] & PTE_P) == 0) { *fd_store = fd; return 0; } } *fd_store = 0; return -E_MAX_OPEN; }
// Finds the smallest i from 0 to MAXFD-1 that doesn't have // its fd page mapped. // Sets *fd_store to the corresponding fd page virtual address. // // fd_alloc does NOT actually allocate an fd page. // It is up to the caller to allocate the page somehow. // This means that if someone calls fd_alloc twice in a row // without allocating the first page we return, we'll return the same // page the second time. // // Hint: Use INDEX2FD. // // Returns 0 on success, < 0 on error. Errors are: // -E_MAX_FD: no more file descriptors // On error, *fd_store is set to 0. int fd_alloc(struct Fd **fd_store) { struct Fd *fd; int i; for (i = 0; i < MAXFD; i++) { fd = INDEX2FD(i); if (pageref(fd) == 0) { *fd_store = fd; return 0; } } *fd_store = 0; return -E_MAX_OPEN; }
int dup(int oldfdnum, int newfdnum) { int i, r; u_int ova, nva, pte; struct Fd *oldfd, *newfd; if ((r = fd_lookup(oldfdnum, &oldfd)) < 0) { return r; } close(newfdnum); newfd = (struct Fd *)INDEX2FD(newfdnum); ova = fd2data(oldfd); nva = fd2data(newfd); if ((r = syscall_mem_map(0, (u_int)oldfd, 0, (u_int)newfd, ((*vpt)[VPN(oldfd)]) & (PTE_V | PTE_R | PTE_LIBRARY))) < 0) { goto err; } if ((* vpd)[PDX(ova)]) { for (i = 0; i < PDMAP; i += BY2PG) { pte = (* vpt)[VPN(ova + i)]; if (pte & PTE_V) { // should be no error here -- pd is already allocated if ((r = syscall_mem_map(0, ova + i, 0, nva + i, pte & (PTE_V | PTE_R | PTE_LIBRARY))) < 0) { goto err; } } } } return newfdnum; err: syscall_mem_unmap(0, (u_int)newfd); for (i = 0; i < PDMAP; i += BY2PG) { syscall_mem_unmap(0, nva + i); } return r; }
// Check that fdnum is in range and mapped. // If it is, set *fd_store to the fd page virtual address. // // Returns 0 on success (the page is in range and mapped), < 0 on error. // Errors are: // -E_INVAL: fdnum was either not in range or not mapped. int fd_lookup(int fdnum, struct Fd **fd_store) { struct Fd *fd; if (fdnum < 0 || fdnum >= MAXFD) { if (debug) cprintf("[%08x] bad fd %d\n", thisenv->env_id, fdnum); return -E_INVAL; } fd = INDEX2FD(fdnum); if (!(vpd[VPD(fd)] & PTE_P) || !(vpt[VPN(fd)] & PTE_P)) { if (debug) cprintf("[%08x] closed fd %d\n", thisenv->env_id, fdnum); return -E_INVAL; } *fd_store = fd; return 0; }
int fd_lookup(int fdnum, struct Fd **fd) { // Check that fdnum is in range and mapped. If not, return -E_INVAL. // Set *fd to the fd page virtual address. Return 0. u_int va; if (fdnum >= MAXFD) { return -E_INVAL; } va = INDEX2FD(fdnum); if (((* vpt)[va / BY2PG] & PTE_V) != 0) { //the fd is used *fd = (struct Fd *)va; return 0; } return -E_INVAL; }
// Check that fdnum is in range and mapped. // If it is, set *fd_store to the fd page virtual address. // // Returns 0 on success (the page is in range and mapped), < 0 on error. // Errors are: // -E_INVAL: fdnum was either not in range or not mapped. int fd_lookup(int fdnum, struct Fd **fd_store) { struct Fd *fd; // LAB 5: Your code here. *fd_store = 0; if (fdnum < 0 || fdnum > MAXFD) return -E_INVAL; fd = INDEX2FD(fdnum); if ((uintptr_t) fd < FDTABLE || (uintptr_t) fd >= FILEBASE) return -E_INVAL; if (!va_is_mapped(fd)) return -E_INVAL; *fd_store = fd; return 0; }
// Make file descriptor 'newfdnum' a duplicate of file descriptor 'oldfdnum'. // For instance, writing onto either file descriptor will affect the // file and the file offset of the other. // Closes any previously open file descriptor at 'newfdnum'. // This is implemented using virtual memory tricks (of course!). int dup(int oldfdnum, int newfdnum) { int i, r; char *ova, *nva; pte_t pte; struct Fd *oldfd, *newfd; if ((r = fd_lookup(oldfdnum, &oldfd)) < 0) return r; close(newfdnum); newfd = INDEX2FD(newfdnum); ova = fd2data(oldfd); nva = fd2data(newfd); // if ((r = sys_page_map(0, oldfd, 0, newfd, vpt[VPN(oldfd)] & PTE_USER)) < 0) // goto err; if (vpd[PDX(ova)]) { for (i = 0; i < PTSIZE; i += PGSIZE) { pte = vpt[VPN(ova + i)]; if (pte&PTE_P) { // should be no error here -- pd is already allocated if ((r = sys_page_map(0, ova + i, 0, nva + i, pte & PTE_USER)) < 0) goto err; } } } if ((r = sys_page_map(0, oldfd, 0, newfd, vpt[VPN(oldfd)] & PTE_USER)) < 0) goto err; return newfdnum; err: sys_page_unmap(0, newfd); for (i = 0; i < PTSIZE; i += PGSIZE) sys_page_unmap(0, nva + i); return r; }