aboutsummaryrefslogtreecommitdiff
path: root/pk/file.c
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2010-08-18 18:24:55 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2010-08-18 18:24:55 -0700
commit29cc0dc9854c66f12bd65e12516f68ccd9a741da (patch)
tree23bd8147007d3d0fbb005f578f395e71f7d7d18d /pk/file.c
parente97220c9bf519b8e0f0b131a4f868331c4d526fb (diff)
downloadpk-29cc0dc9854c66f12bd65e12516f68ccd9a741da.zip
pk-29cc0dc9854c66f12bd65e12516f68ccd9a741da.tar.gz
pk-29cc0dc9854c66f12bd65e12516f68ccd9a741da.tar.bz2
[pk,fesvr] improved proxykernel build system
Now uses a modified MCPPBS. Add --host=riscv to configure path. Front-end server now just searches PATH for riscv-pk, so just install the pk to somewhere in your path.
Diffstat (limited to 'pk/file.c')
-rw-r--r--pk/file.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/pk/file.c b/pk/file.c
new file mode 100644
index 0000000..fd063d9
--- /dev/null
+++ b/pk/file.c
@@ -0,0 +1,133 @@
+#include <string.h>
+#include <errno.h>
+#include "file.h"
+#include "pk.h"
+#include "frontend.h"
+
+#define MAX_FDS 1000
+file_t* fds[MAX_FDS];
+#define MAX_FILES 1000
+file_t files[MAX_FILES] = {[0 ... MAX_FILES-1] = {-1,{0}}};
+file_t *stdout, *stdin, *stderr;
+
+static void file_incref(file_t* f)
+{
+ atomic_add(&f->refcnt,1);
+}
+
+static void file_decref(file_t* f)
+{
+ if(atomic_add(&f->refcnt,-1) == 2)
+ {
+ if(f->kfd != -1)
+ {
+ frontend_syscall(SYS_close,f->kfd,0,0,0);
+ f->kfd = -1;
+ }
+ atomic_add(&f->refcnt,-1); // I think this could just be atomic_set(..,0)
+ }
+}
+
+static file_t* file_get_free()
+{
+ for(int i = 0; i < MAX_FILES; i++)
+ {
+ if(atomic_read(&files[i].refcnt) == 0)
+ {
+ if(atomic_add(&files[i].refcnt,1) == 0)
+ {
+ atomic_add(&files[i].refcnt,1);
+ return &files[i];
+ }
+ file_decref(&files[i]);
+ }
+ }
+ return NULL;
+}
+
+static int fd_get_free()
+{
+ for(int i = 0; i < MAX_FDS; i++)
+ if(fds[i] == NULL)
+ return i;
+ return -1;
+}
+
+int file_dup(file_t* f)
+{
+ int fd = fd_get_free();
+ if(fd == -1)
+ return -1;
+ file_incref(f);
+ fds[fd] = f;
+ return fd;
+}
+
+void file_init()
+{
+ stdin = file_get_free();
+ stdout = file_get_free();
+ stderr = file_get_free();
+ kassert(stdin && stdout && stderr);
+
+ stdin->kfd = 0;
+ stdout->kfd = 1;
+ stderr->kfd = 2;
+
+ kassert(file_dup(stdin) == 0);
+ kassert(file_dup(stdout) == 1);
+ kassert(file_dup(stderr) == 2);
+}
+
+file_t* file_get(int fd)
+{
+ return fd < 0 || fd >= MAX_FDS ? NULL : fds[fd];
+}
+
+sysret_t file_open(const char* fn, size_t len, int flags, int mode)
+{
+ file_t* f = file_get_free();
+ if(!f)
+ return (sysret_t){-1,ENOMEM};
+
+ sysret_t ret = frontend_syscall(SYS_open,(long)fn,len,flags,mode);
+ if(ret.result != -1)
+ {
+ f->kfd = ret.result;
+ ret.result = (long)f;
+ }
+ else
+ file_decref(f);
+
+ return ret;
+}
+
+int fd_close(int fd)
+{
+ file_t* f = file_get(fd);
+ if(!f)
+ return -1;
+ fds[fd] = NULL;
+ file_decref(f);
+ return 0;
+}
+
+sysret_t file_read(file_t* f, void* buf, size_t size)
+{
+ return frontend_syscall(SYS_read,f->kfd,(long)buf,size,0);
+}
+
+sysret_t file_write(file_t* f, const void* buf, size_t size)
+{
+ return frontend_syscall(SYS_write,f->kfd,(long)buf,size,0);
+}
+
+sysret_t file_stat(file_t* f, struct stat* s)
+{
+ return frontend_syscall(SYS_fstat,f->kfd,(long)s,0,0);
+}
+
+sysret_t file_lseek(file_t* f, size_t ptr, int dir)
+{
+ return frontend_syscall(SYS_fstat,f->kfd,ptr,dir,0);
+}