diff options
-rw-r--r-- | sys/include/sys/syscall.h | 1 | ||||
-rw-r--r-- | sys/include/sys/vfs.h | 1 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 1 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 35 |
4 files changed, 38 insertions, 0 deletions
diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index 9aa96e7..4df3825 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -39,6 +39,7 @@ #define SYS_exit 1 #define SYS_open 2 #define SYS_read 3 +#define SYS_close 4 #if defined(_KERNEL) /* Syscall return value and arg type */ diff --git a/sys/include/sys/vfs.h b/sys/include/sys/vfs.h index 52d35f3..776ee66 100644 --- a/sys/include/sys/vfs.h +++ b/sys/include/sys/vfs.h @@ -36,6 +36,7 @@ #if defined(_KERNEL) scret_t sys_open(struct syscall_args *scargs); +scret_t sys_close(struct syscall_args *args); scret_t sys_read(struct syscall_args *scargs); #endif /* _KERNEL */ diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 416a8ec..b36c6af 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -37,6 +37,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = { sys_exit, /* SYS_exit */ sys_open, /* SYS_open */ sys_read, /* SYS_read */ + sys_close, /* SYS_close */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 937ae87..77070ab 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -34,6 +34,7 @@ #include <sys/errno.h> #include <sys/sio.h> #include <sys/filedesc.h> +#include <sys/atomic.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/limits.h> @@ -141,6 +142,40 @@ sys_open(struct syscall_args *scargs) /* * arg0: fd + */ +scret_t +sys_close(struct syscall_args *args) +{ + struct filedesc *filedes; + struct proc *td; + int fd = args->arg0; + + if ((filedes = fd_get(fd)) == NULL) { + return -EBADF; + } + + /* Return if other threads still hold a ref */ + if (atomic_dec_int(&filedes->refcnt) > 0) { + return 0; + } + + td = this_td(); + + /* + * Each file descriptor structure references a vnode, + * we want to reclaim it or at the very least drop + * one of its references. After we've cleaned up within + * the file descriptor, we can clear it from the fd table + * and free up the memory for it. + */ + vfs_release_vnode(filedes->vp); + td->fds[fd] = NULL; + dynfree(filedes); + return 0; +} + +/* + * arg0: fd * arg1: buf * arg2: count */ |