aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/include/sys/syscall.h1
-rw-r--r--sys/include/sys/vfs.h1
-rw-r--r--sys/kern/kern_syscall.c1
-rw-r--r--sys/kern/vfs_syscalls.c35
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
*/