diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2010-08-18 18:24:55 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2010-08-18 18:24:55 -0700 |
commit | 29cc0dc9854c66f12bd65e12516f68ccd9a741da (patch) | |
tree | 23bd8147007d3d0fbb005f578f395e71f7d7d18d /pk/file.c | |
parent | e97220c9bf519b8e0f0b131a4f868331c4d526fb (diff) | |
download | pk-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.c | 133 |
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); +} |