ref: 26dd49399614ec9544f66aa95809af437247322e
dir: /seg.c/
#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->dref = emalloc(size + sizeof(Ref)); memset(s->dref, 0, sizeof(Ref)); incref(s->dref); s->data = s->dref + 1; if(check) s->shadow = emallocz((size+3)/4); 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)->dref) == 0) free((*s)->dref); if(decref(*s) == 0) free(*s); *s = nil; } } void * vaddr(u32int addr, u32int len, int op, Segment **seg) { Segment **ss, *s; u32int off; int bits; 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(addr + len > s->start + s->size) break; if(s->flags & SEGFLLOCK) rlock(&s->rw); *seg = s; off = (addr - s->start); if(check && op != 0){ bits = MARKALLOC; if(op & ARD) bits |= MARKINIT; checkaccess(s, off, len, bits); if(op & AWR) markvalid(s, off, len, MARKINIT); } return (char *)s->data + off; } } abort(); suicide("fault %.8ux (%d) @ %.8ux", addr, len, P->R[15]); return nil; } void * vaddrnol(u32int addr, u32int len, int op) { Segment *seg; void *ret; ret = vaddr(addr, len, op, &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, len > 0 ? len : 0, 0, &seg); if((seg->flags & SEGFLLOCK) == 0) { *copied = 0; return targ; } if(len < 0) len = strlen(targ) + 1; ret = emalloc(len); setmalloctag(ret, getcallerpc(&addr)); memcpy(ret, targ, len); segunlock(seg); *copied = 1; return ret; } void * bufifnec(u32int addr, int len, int *buffered) { void *targ, *v; Segment *seg; targ = vaddr(addr, len, 0, &seg); if((seg->flags & SEGFLLOCK) == 0) { *buffered = 0; return targ; } segunlock(seg); *buffered = 1; v = emalloc(len); setmalloctag(v, getcallerpc(&addr)); return v; } void copyback(u32int addr, int len, void *data) { void *targ; Segment *seg; if(len <= 0) { free(data); return; } targ = vaddr(addr, len, 0, &seg); memmove(targ, data, len); segunlock(seg); free(data); }