diff options
author | aiju <aiju@phicode.de> | 2011-06-16 17:49:24 +0200 |
---|---|---|
committer | aiju <aiju@phicode.de> | 2011-06-16 17:49:24 +0200 |
commit | 2acb5433d8008012d7208a7bfcb9c6a1544f218f (patch) | |
tree | 19f0c7afc013113c5f8b3de005b2245e33ce2f5e /sys/src/cmd/5e/seg.c | |
parent | fcf30f314b4c4157b536647a09a214576711ad16 (diff) |
added 5e (not finished)
Diffstat (limited to 'sys/src/cmd/5e/seg.c')
-rw-r--r-- | sys/src/cmd/5e/seg.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/sys/src/cmd/5e/seg.c b/sys/src/cmd/5e/seg.c new file mode 100644 index 000000000..caa4002ac --- /dev/null +++ b/sys/src/cmd/5e/seg.c @@ -0,0 +1,129 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include "dat.h" +#include "fns.h" + +Segment * +newseg(u32int start, u32int size, int idx) +{ + Segment *s; + + s = emallocz(sizeof *s); + incref(s); + s->start = start; + s->size = size; + s->ref = emalloc(size + sizeof(Ref)); + memset(s->ref, 0, sizeof(Ref)); + incref(s->ref); + s->data = s->ref + 1; + if(idx == SEGBSS) + s->flags = SEGFLLOCK; + P->S[idx] = s; + return s; +} + +void +freesegs(void) +{ + Segment **s; + + for(s = P->S; s < P->S + SEGNUM; s++) { + if(*s == nil) + continue; + if(decref((*s)->ref) == 0) + free((*s)->ref); + if(decref(*s) == 0) + free(*s); + *s = nil; + } +} + +void * +vaddr(u32int addr, Segment **seg) +{ + Segment **ss, *s; + + for(ss = P->S; ss < P->S + SEGNUM; ss++) { + if(*ss == nil) + continue; + s = *ss; + if(addr >= s->start && addr < s->start + s->size) { + if(s->flags & SEGFLLOCK) + rlock(&s->rw); + *seg = s; + return (char *)s->data + (addr - s->start); + } + } + sysfatal("fault %.8ux @ %.8ux", addr, P->R[15]); + return nil; +} + +void * +vaddrnol(u32int addr) +{ + Segment *seg; + void *ret; + + ret = vaddr(addr, &seg); + segunlock(seg); + return ret; +} + +/* might be made a macro for hurr durr performance */ +void +segunlock(Segment *s) +{ + if(s->flags & SEGFLLOCK) + runlock(&s->rw); +} + +void * +copyifnec(u32int addr, int len, int *copied) +{ + void *targ, *ret; + Segment *seg; + + targ = vaddr(addr, &seg); + if((seg->flags & SEGFLLOCK) == 0) { + *copied = 0; + return targ; + } + if(len < 0) + len = strlen(targ) + 1; + ret = emalloc(len); + memcpy(ret, targ, len); + segunlock(seg); + *copied = 1; + return ret; +} + +void * +bufifnec(u32int addr, int len, int *buffered) +{ + void *targ; + Segment *seg; + + targ = vaddr(addr, &seg); + if((seg->flags & SEGFLLOCK) == 0) { + *buffered = 0; + return targ; + } + segunlock(seg); + *buffered = 1; + return emalloc(len); +} + +void +copyback(u32int addr, int len, void *data) +{ + void *targ; + Segment *seg; + + if(len <= 0) + return; + targ = vaddr(addr, &seg); + memmove(targ, data, len); + segunlock(seg); + free(data); +} |