diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2010-07-21 20:12:09 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2010-07-21 20:12:09 -0700 |
commit | b24c0f1a1eafa6fe18164d0df81512d3ff42bc1f (patch) | |
tree | c05b70f43b22f2dd649ae2fa3cba7bc45acbc93d | |
parent | 263c2ff7d8ae261fc2ee2dbf740ba048df9c956d (diff) | |
download | pk-b24c0f1a1eafa6fe18164d0df81512d3ff42bc1f.zip pk-b24c0f1a1eafa6fe18164d0df81512d3ff42bc1f.tar.gz pk-b24c0f1a1eafa6fe18164d0df81512d3ff42bc1f.tar.bz2 |
[pk,sim] first cut of appserver communication link
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | atomic.h | 43 | ||||
-rw-r--r-- | cop0.h | 11 | ||||
-rw-r--r-- | file.c | 52 | ||||
-rw-r--r-- | file.h | 5 | ||||
-rw-r--r-- | frontend.c | 26 | ||||
-rw-r--r-- | frontend.h | 8 |
7 files changed, 133 insertions, 16 deletions
@@ -5,8 +5,8 @@ TARGETS := pk all: $(TARGETS) -pk: boot.o entry.o pk.o syscall.o file.o pk.ld - $(CC) -o pk entry.o pk.o syscall.o file.o -T pk.ld +pk: boot.o entry.o pk.o syscall.o file.o frontend.o pk.ld + $(CC) -o pk entry.o pk.o syscall.o file.o frontend.o -T pk.ld %.o: %.c *.h $(CC) -c $< diff --git a/atomic.h b/atomic.h new file mode 100644 index 0000000..3294b6c --- /dev/null +++ b/atomic.h @@ -0,0 +1,43 @@ +#ifndef _RISCV_ATOMIC_H +#define _RISCV_ATOMIC_H + +typedef struct { long val; } atomic_t; +typedef struct { atomic_t lock; } spinlock_t; +#define SPINLOCK_INIT {{0}} + +static inline long atomic_add(atomic_t* a, long inc) +{ + long old = a->val; + a->val += inc; + return old; +} + +static inline long atomic_swap(atomic_t* a, long val) +{ + long old = a->val; + a->val = val; + return old; +} + +static inline void atomic_set(atomic_t* a, long val) +{ + a->val = val; +} + +static inline long atomic_read(atomic_t* a) +{ + return a->val; +} + +static inline void spinlock_lock(spinlock_t* lock) +{ + while(atomic_read(&lock->lock)) + while(atomic_swap(&lock->lock,-1)); +} + +static inline void spinlock_unlock(spinlock_t* lock) +{ + atomic_set(&lock->lock,0); +} + +#endif @@ -0,0 +1,11 @@ +#ifndef _RISCV_COP0_H +#define _RISCV_COP0_H + +#define dmtc0(val,reg) ({ long __tmp = (long)(val); \ + asm volatile ("dmtc0 %0,$%1"::"r"(__tmp),"i"(reg)); }) + +#define dmfc0(reg) ({ long __tmp; \ + asm volatile ("dmfc0 %0,$%1" : "=r"(__tmp) : "i"(reg)); \ + __tmp; }) + +#endif @@ -1,31 +1,45 @@ #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]; +file_t files[MAX_FILES] = {[0 ... MAX_FILES-1] = {-1,{0}}}; file_t *stdout, *stdin, *stderr; static void file_incref(file_t* f) { - f->refcnt++; + atomic_add(&f->refcnt,1); } static void file_decref(file_t* f) { - f->refcnt--; + 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(files[i].refcnt == 0) + if(atomic_read(&files[i].refcnt) == 0) { - files[i].refcnt = 1; - return &files[i]; + if(atomic_add(&files[i].refcnt,1) == 0) + { + atomic_add(&files[i].refcnt,1); + return &files[i]; + } + file_decref(&files[i]); } } return NULL; @@ -41,10 +55,10 @@ static int fd_get_free() int file_dup(file_t* f) { - file_incref(f); int fd = fd_get_free(); if(fd == -1) return -1; + file_incref(f); fds[fd] = f; return fd; } @@ -70,9 +84,22 @@ file_t* file_get(int fd) return fd < 0 || fd >= MAX_FDS ? NULL : fds[fd]; } -file_t* file_open(const char* fn) +sysret_t file_open(const char* fn, int mode) { - return NULL; + file_t* f = file_get_free(); + if(!f) + return (sysret_t){-1,ENOMEM}; + + sysret_t ret = frontend_syscall(SYS_open,(long)fn,mode,0,0); + if(ret.result != -1) + { + f->kfd = ret.result; + ret.result = (long)f; + } + else + file_decref(f); + + return ret; } int fd_close(int fd) @@ -93,9 +120,10 @@ static void putch(int c) sysret_t file_write(file_t* f, const void* buf, size_t size) { - for(int i = 0; i < size; i++) - putch(((char*)buf)[i]); - return (sysret_t){0,0}; + return frontend_syscall(SYS_write,f->kfd,(long)buf,size,0); + //for(int i = 0; i < size; i++) + // putch(((char*)buf)[i]); + //return (sysret_t){0,0}; } sysret_t file_stat(file_t* f, struct stat* s) @@ -3,17 +3,18 @@ #include <sys/stat.h> #include <machine/syscall.h> +#include "atomic.h" typedef struct file { int kfd; // file descriptor on the appserver side - int refcnt; + atomic_t refcnt; } file_t; extern file_t *stdin, *stdout, *stderr; file_t* file_get(int fd); -file_t* file_open(const char* fn); +sysret_t file_open(const char* fn, int mode); int file_dup(file_t*); sysret_t file_write(file_t* f, const void* buf, size_t n); diff --git a/frontend.c b/frontend.c new file mode 100644 index 0000000..b57c9a2 --- /dev/null +++ b/frontend.c @@ -0,0 +1,26 @@ +#include "pk.h" +#include "atomic.h" +#include "frontend.h" +#include "cop0.h" + +sysret_t frontend_syscall(long n, long a0, long a1, long a2, long a3) +{ + static volatile long magic_mem[8]; + + static spinlock_t lock = SPINLOCK_INIT; + spinlock_lock(&lock); + + magic_mem[0] = n; + magic_mem[1] = a0; + magic_mem[2] = a1; + magic_mem[3] = a2; + magic_mem[4] = a3; + + dmtc0(magic_mem,16); + while(dmfc0(17)); + + sysret_t ret = {magic_mem[0],magic_mem[1]}; + + spinlock_unlock(&lock); + return ret; +} diff --git a/frontend.h b/frontend.h new file mode 100644 index 0000000..86a8917 --- /dev/null +++ b/frontend.h @@ -0,0 +1,8 @@ +#ifndef _RISCV_FRONTEND_H +#define _RISCV_FRONTEND_H + +#include <machine/syscall.h> + +sysret_t frontend_syscall(long n, long a0, long a1, long a2, long a3); + +#endif |