## diffname port/segment.c 1991/0705 ## diff -e /dev/null /n/bootesdump/1991/0705/sys/src/9/port/segment.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "errno.h" #define DPRINT Page *lkpage(ulong addr); Page *snewpage(ulong addr); void lkpgfree(Page*); /* System specific segattach devices */ #include "segment.h" #define IHASHSIZE 64 #define ihash(s) imagealloc.hash[s%IHASHSIZE] struct Imagealloc { Lock; Image *free; Image *hash[IHASHSIZE]; }imagealloc; struct segalloc { Lock; Segment *free; }segalloc; void initseg(void) { Segment *s, *se; Image *i, *ie; segalloc.free = ialloc(conf.nseg*sizeof(Segment), 0); imagealloc.free = ialloc(conf.nimage*sizeof(Image), 0); se = &segalloc.free[conf.nseg-1]; for(s = segalloc.free; s < se; s++) s->next = s+1; s->next = 0; ie = &imagealloc.free[conf.nimage-1]; for(i = imagealloc.free; i < ie; i++) i->next = i+1; i->next = 0; } Segment * newseg(int type, ulong base, ulong size) { Segment *s; if(size > (SEGMAPSIZE*PTEPERTAB)) errors("segment too large"); for(;;) { lock(&segalloc); if(s = segalloc.free) { segalloc.free = s->next; unlock(&segalloc); s->ref = 1; s->steal = 0; s->type = type; s->base = base; s->top = base+(size*BY2PG); s->size = size; s->image = 0; s->fstart = 0; s->flen = 0; s->pgalloc = 0; s->pgfree = 0; memset(s->map, 0, sizeof(s->map)); return s; } unlock(&segalloc); resrcwait("no segments"); } } void putseg(Segment *s) { Pte **pp, **emap; Image *i; if(s && decref(s) == 0) { emap = &s->map[SEGMAPSIZE]; for(pp = s->map; pp < emap; pp++) if(*pp) freepte(s, *pp); if(i = s->image) { lock(i); if(i->s == s) i->s = 0; unlock(i); putimage(i); } lock(&segalloc); s->next = segalloc.free; segalloc.free = s; unlock(&segalloc); } } void relocateseg(Segment *s, ulong offset) { Pte **p, **endpte; Page **pg, **endpages; endpte = &s->map[SEGMAPSIZE]; for(p = s->map; p < endpte; p++) if(*p) { endpages = &((*p)->pages[PTEPERTAB]); for(pg = (*p)->pages; pg < endpages; pg++) if(*pg) (*pg)->va += offset; } } Segment* dupseg(Segment *s) { Pte *pte; Segment *n; int i; switch(s->type&SG_TYPE) { case SG_TEXT: /* new segment shares pte set */ case SG_SHARED: case SG_PHYSICAL: incref(s); return s; case SG_DATA: /* copy on write both old and new plus demand load info */ lock(s); n = newseg(s->type, s->base, s->size); incref(s->image); n->image = s->image; n->fstart = s->fstart; n->flen = s->flen; copypte: for(i = 0; i < SEGMAPSIZE; i++) if(pte = s->map[i]) n->map[i] = ptecpy(pte); unlock(s); return n; case SG_BSS: /* Just copy on write */ case SG_STACK: lock(s); n = newseg(s->type, s->base, s->size); goto copypte; } panic("dupseg"); } void segpage(Segment *s, Page *p) { Pte **pte; ulong off; if(p->va < s->base || p->va >= s->top) panic("segpage"); off = p->va - s->base; pte = &s->map[off/PTEMAPMEM]; if(*pte == 0) *pte = ptealloc(); (*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG] = p; } Image* attachimage(int type, Chan *c, ulong base, ulong len) { Image *i, **l; lock(&imagealloc); for(i = ihash(c->qid.path); i; i = i->hash) { if(c->qid.path == i->qid.path) { lock(i); if(eqqid(c->qid, i->qid)) if(eqqid(c->mqid, i->mqid)) if(c->mchan == i->mchan) if(c->type == i->type) { i->ref++; goto found; } unlock(i); } } while(!(i = imagealloc.free)) { unlock(&imagealloc); resrcwait("no images"); lock(&imagealloc); } imagealloc.free = i->next; lock(i); incref(c); i->c = c; i->type = c->type; i->qid = c->qid; i->mqid = c->mqid; i->mchan = c->mchan; i->ref = 1; l = &ihash(c->qid.path); i->hash = *l; *l = i; found: unlock(&imagealloc); if(i->s == 0) { i->s = newseg(type, base, len); i->s->image = i; } else incref(i->s); unlock(i); return i; } void putimage(Image *i) { Image *f, **l; Chan *c; if(i == &swapimage) return; lock(i); if(--i->ref == 0) { l = &ihash(i->qid.path); i->qid = (Qid){~0, ~0}; unlock(i); c = i->c; lock(&imagealloc); for(f = *l; f; f = f->hash) { if(f == i) { *l = i->hash; break; } l = &f->hash; } i->next = imagealloc.free; imagealloc.free = i; unlock(&imagealloc); close(c); /* Delay close because we could error */ return; } unlock(i); } long ibrk(ulong addr, int seg) /* Called with a locked segment */ { Segment *s, *ns; ulong newtop, newsize; int i; s = u->p->seg[seg]; if(s == 0) errors("no segment"); qlock(&s->lk); if(addr == 0) return s->base; if(addr < s->base) { /* We may start with the bss overlapping the data */ if(seg != BSEG || u->p->seg[DSEG] == 0 || addr < u->p->seg[DSEG]->base) { qunlock(&s->lk); pprint("addr below segment\n"); } addr = s->base; } newtop = PGROUND(addr); newsize = (newtop-s->base)/BY2PG; if(newtop < s->top) { print("down brk\n"); mfreeseg(s, newtop, (s->top-newtop)/BY2PG); qunlock(&s->lk); return 0; } if(newsize > (PTEMAPMEM*SEGMAPSIZE)/BY2PG) { qunlock(&s->lk); pprint("exceeded max segment size\n"); pexit("Suicide", 0); error(Esegaddr); } for(i = 0; i < NSEG; i++) { ns = u->p->seg[i]; if(ns == 0 || ns == s) continue; if(newtop >= ns->base && newtop < ns->top) { qunlock(&s->lk); pprint("segments overlap\n"); pexit("Suicide", 0); error(Esegaddr); } } s->top = newtop; s->size = newsize; qunlock(&s->lk); return 0; } void mfreeseg(Segment *s, ulong start, int pages) { int i, j; ulong soff; Page *pg; soff = start-s->base; j = (soff&(PTEMAPMEM-1))/BY2PG; for(i = soff/PTEMAPMEM; i < SEGMAPSIZE; i++) { if(pages <= 0) goto done; if(s->map[i]) { while(j < PTEPERTAB) { if(pg = s->map[i]->pages[j]) { putpage(pg); s->map[i]->pages[j] = 0; } if(--pages == 0) goto done; j++; } j = 0; } else pages -= PTEMAPMEM/BY2PG; } done: flushmmu(); } ulong segattach(Proc *p, ulong attr, char *name, ulong va, ulong len) { Segment *s, *ns, *new; Physseg *ps; ulong newtop; int i, sno; if(va&KZERO) /* BUG: Only ok for now */ errors("bad virtual address"); validaddr((ulong)name, 1, 0); vmemchr(name, 0, ~0); for(sno = 0; sno < NSEG; sno++) if(u->p->seg[sno] == 0 && sno != ESEG) break; if(sno == NSEG) errors("no per process segments"); va = va&~(BY2PG-1); len = PGROUND(len); newtop = va+len; for(i = 0; i < NSEG; i++) { ns = u->p->seg[i]; if(ns == 0) continue; if(newtop >= ns->base && newtop < ns->top) errors("segments overlap"); } for(ps = physseg; *(ps->name); ps++) if(strcmp(name, ps->name) == 0) goto found; errors("bad segment name"); found: if(len > ps->size) errors("segment too long"); attr &= ~SG_TYPE; /* Turn off what we are not allowed */ attr |= ps->attr; /* Copy in defaults */ s = newseg(attr, va, len/BY2PG); s->pgalloc = ps->pgalloc; s->pgfree = ps->pgfree; u->p->seg[sno] = s; /* Need some code build mapped devices here */ return 0; } long syssegflush(ulong *arg) { Segment *s; int i, j, pages; ulong soff; Page *pg; s = seg(u->p, arg[0], 1); if(s == 0) errors("bad segment address"); soff = arg[0]-s->base; j = (soff&(PTEMAPMEM-1))/BY2PG; pages = ((arg[0]+arg[1]+(BY2PG-1))&~(BY2PG-1))-(arg[0]&~(BY2PG-1)); for(i = soff/PTEMAPMEM; i < SEGMAPSIZE; i++) { if(pages <= 0) goto done; if(s->map[i]) { while(j < PTEPERTAB) { if(pg = s->map[i]->pages[j]) memset(pg->cachectl, PG_TXTFLUSH, sizeof pg->cachectl); if(--pages == 0) goto done; j++; } j = 0; } else pages -= PTEMAPMEM/BY2PG; } done: qunlock(&s->lk); flushmmu(); } Page* snewpage(ulong addr) { return newpage(1, 0, addr); } . ## diffname port/segment.c 1991/0706 ## diff -e /n/bootesdump/1991/0705/sys/src/9/port/segment.c /n/bootesdump/1991/0706/sys/src/9/port/segment.c 429a s->flushme = 1; . 274c ibrk(ulong addr, int seg) . 238a imagereclaim(void) { Page *p; if(!canqlock(&ireclaim)) /* Somebody is already cleaning the page cache */ return; lock(&palloc); for(p = palloc.head; p; p = p->next) { if(p->image == 0) continue; unlock(&palloc); lockpage(p); if(p->ref == 0 && p->image != &swapimage) uncachepage(p); unlockpage(p); lock(&palloc); } unlock(&palloc); qunlock(&ireclaim); } void . 206a imagereclaim(); . 190a /* Search the image cache for remains of the text from a previous incarnation */ . 157,161d 155c n->flushme = s->flushme; qunlock(&s->lk); . 146a case SG_DATA: /* Copy on write plus demand load info */ qlock(&s->lk); n = newseg(s->type, s->base, s->size); . 145a goto copypte; . 143,144c case SG_BSS: /* Just copy on write */ case SG_STACK: qlock(&s->lk); . 138c case SG_TEXT: /* New segment shares pte set */ . 77a s->flushme = 0; . 32a static QLock ireclaim; . 13a void imagereclaim(void); . ## diffname port/segment.c 1991/0710 ## diff -e /n/bootesdump/1991/0706/sys/src/9/port/segment.c /n/bootesdump/1991/0710/sys/src/9/port/segment.c 217c resrcwait(0); . ## diffname port/segment.c 1991/0724 ## diff -e /n/bootesdump/1991/0710/sys/src/9/port/segment.c /n/bootesdump/1991/0724/sys/src/9/port/segment.c 244d 213a /* * imagereclaim dumps pages from the free list which are cached by image * structures. This should free some image structures. */ . 199c /* * Search the image cache for remains of the text from a previous * or currently running incarnation */ . ## diffname port/segment.c 1991/0726 ## diff -e /n/bootesdump/1991/0724/sys/src/9/port/segment.c /n/bootesdump/1991/0726/sys/src/9/port/segment.c 401c pages -= PTEPERTAB-j; j = 0; . 398d 103,110d 97c if(s == 0) return; i = s->image; if(i && i->s == s && s->ref == 1){ lock(i); if(s->ref == 1) i->s = 0; unlock(i); } if(decref(s) == 0) { if(i) putimage(i); . ## diffname port/segment.c 1991/0731 ## diff -e /n/bootesdump/1991/0726/sys/src/9/port/segment.c /n/bootesdump/1991/0731/sys/src/9/port/segment.c 445c for(ps = physseg; ps->name; ps++) . ## diffname port/segment.c 1991/0803 ## diff -e /n/bootesdump/1991/0731/sys/src/9/port/segment.c /n/bootesdump/1991/0803/sys/src/9/port/segment.c 441c if((newtop > ns->base && newtop <= ns->top) || (va >= ns->base && va < ns->top)) . ## diffname port/segment.c 1991/0830 ## diff -e /n/bootesdump/1991/0803/sys/src/9/port/segment.c /n/bootesdump/1991/0830/sys/src/9/port/segment.c 357,359c return -1; . ## diffname port/segment.c 1991/1005 ## diff -e /n/bootesdump/1991/0830/sys/src/9/port/segment.c /n/bootesdump/1991/1005/sys/src/9/port/segment.c 349d ## diffname port/segment.c 1991/1024 ## diff -e /n/bootesdump/1991/1005/sys/src/9/port/segment.c /n/bootesdump/1991/1024/sys/src/9/port/segment.c 280,281d 278d 273a if(p == 0) break; . 268,271c for(;;) { lock(&palloc); for(p = palloc.head; p; p = p->next) if(p->image && p->ref == 0 && p->image != &swapimage) break; . ## diffname port/segment.c 1991/1105 ## diff -e /n/bootesdump/1991/1024/sys/src/9/port/segment.c /n/bootesdump/1991/1105/sys/src/9/port/segment.c 367d ## diffname port/segment.c 1991/1109 ## diff -e /n/bootesdump/1991/1105/sys/src/9/port/segment.c /n/bootesdump/1991/1109/sys/src/9/port/segment.c 115a qunlock(&s->lk); . 108a qlock(&s->lk); . ## diffname port/segment.c 1991/1115 ## diff -e /n/bootesdump/1991/1109/sys/src/9/port/segment.c /n/bootesdump/1991/1115/sys/src/9/port/segment.c 420a USED(p); . ## diffname port/segment.c 1991/1122 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/segment.c /n/bootesdump/1991/1122/sys/src/9/port/segment.c 198c pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG]; *pg = p; if(pg < (*pte)->first) (*pte)->first = pg; if(pg > (*pte)->last) (*pte)->last = pg; . 188a Page **pg; . ## diffname port/segment.c 1991/1125 ## diff -e /n/bootesdump/1991/1122/sys/src/9/port/segment.c /n/bootesdump/1991/1125/sys/src/9/port/segment.c 351,352c errors("addr below segment"); } . 346a qlock(&s->lk); . 342,343d ## diffname port/segment.c 1991/1219 ## diff -e /n/bootesdump/1991/1125/sys/src/9/port/segment.c /n/bootesdump/1991/1219/sys/src/9/port/segment.c 9,10d ## diffname port/segment.c 1992/0111 ## diff -e /n/bootesdump/1991/1219/sys/src/9/port/segment.c /n/bootesdump/1992/0111/sys/src/9/port/segment.c 7c #include "../port/error.h" . ## diffname port/segment.c 1992/0114 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/segment.c /n/bootesdump/1992/0114/sys/src/9/port/segment.c 483c error(Ebadarg); . 458c error(Enovmem); . 455c error(Ebadarg); . 448c error(Enovmem); . 437c error(Enovmem); . 427c error(Ebadarg); . 374c error(Enovmem); . 349c error(Enovmem); . 338c error(Ebadarg); . 60c error(Enovmem); . ## diffname port/segment.c 1992/0120 ## diff -e /n/bootesdump/1992/0114/sys/src/9/port/segment.c /n/bootesdump/1992/0120/sys/src/9/port/segment.c 6d ## diffname port/segment.c 1992/0225 ## diff -e /n/bootesdump/1992/0120/sys/src/9/port/segment.c /n/bootesdump/1992/0225/sys/src/9/port/segment.c 285c if(p->ref == 0) . 277c if(p->image) if(p->ref == 0) if(p->image != &swapimage) . ## diffname port/segment.c 1992/0307 ## diff -e /n/bootesdump/1992/0225/sys/src/9/port/segment.c /n/bootesdump/1992/0307/sys/src/9/port/segment.c 434c if(u->p->seg[sno] == 0) if(sno != ESEG) . 372c if(newtop >= ns->base) if(newtop < ns->top) { . 150a case SG_SHDATA: . ## diffname port/segment.c 1992/0310 ## diff -e /n/bootesdump/1992/0307/sys/src/9/port/segment.c /n/bootesdump/1992/0310/sys/src/9/port/segment.c 291a if(conf.cntrlp) print("ireclaim done %lud\n", TK2MS(MACHP(0)->ticks)); . 274a if(conf.cntrlp) print("ireclaim %lud\n", TK2MS(MACHP(0)->ticks)); . ## diffname port/segment.c 1992/0314 ## diff -e /n/bootesdump/1992/0310/sys/src/9/port/segment.c /n/bootesdump/1992/0314/sys/src/9/port/segment.c 295,298d 287,293d 283,285c if(p->image != &swapimage) { lockpage(p); if(p->ref == 0) uncachepage(p); unlockpage(p); } } . 280c for(p = palloc.head; p; p = p->next) { . 275,277d 168a . 98c if(i) if(i->s == s) if(s->ref == 1) { . ## diffname port/segment.c 1992/0321 ## diff -e /n/bootesdump/1992/0314/sys/src/9/port/segment.c /n/bootesdump/1992/0321/sys/src/9/port/segment.c 2c #include "../port/lib.h" . ## diffname port/segment.c 1992/0404 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/segment.c /n/bootesdump/1992/0404/sys/src/9/port/segment.c 291a unlock(&palloc); . 290d 283,288c uncachepage(p); unlockpage(p); . 278,281c lock(&palloc); for(p = palloc.head; p; p = p->next) { if(p->image) if(p->ref == 0) if(p->image != &swapimage) { lockpage(p); . ## diffname port/segment.c 1992/0430 ## diff -e /n/bootesdump/1992/0404/sys/src/9/port/segment.c /n/bootesdump/1992/0430/sys/src/9/port/segment.c 164a if(share && s->ref == 1) { s->type = (s->type&~SG_TYPE)|SG_SHDATA; incref(s); qunlock(&s->lk); return s; } . 162a case SG_BSS: /* Just copy on write */ qlock(&s->lk); if(share && s->ref == 1) { s->type = (s->type&~SG_TYPE)|SG_SHARED; incref(s); qunlock(&s->lk); return s; } n = newseg(s->type, s->base, s->size); goto copypte; . 157d 143c dupseg(Segment *s, int share) . ## diffname port/segment.c 1992/0520 ## diff -e /n/bootesdump/1992/0430/sys/src/9/port/segment.c /n/bootesdump/1992/0520/sys/src/9/port/segment.c 526a return 0; . 198a return 0; /* not reached */ . 85a return 0; /* not reached */ . ## diffname port/segment.c 1992/0619 ## diff -e /n/bootesdump/1992/0520/sys/src/9/port/segment.c /n/bootesdump/1992/0619/sys/src/9/port/segment.c 240,243c if(eqqid(c->qid, i->qid) && eqqid(c->mqid, i->mqid) && c->mchan == i->mchan && c->type == i->type) { . 120,123c free(s); . 61,86c s = smalloc(sizeof(Segment)); s->ref = 1; s->type = type; s->base = base; s->top = base+(size*BY2PG); s->size = size; return s; . 39,46c imagealloc.free = xalloc(conf.nimage*sizeof(Image)); . 25,30d ## diffname port/segment.c 1992/0621 ## diff -e /n/bootesdump/1992/0619/sys/src/9/port/segment.c /n/bootesdump/1992/0621/sys/src/9/port/segment.c 363d 30d ## diffname port/segment.c 1992/0625 ## diff -e /n/bootesdump/1992/0621/sys/src/9/port/segment.c /n/bootesdump/1992/0625/sys/src/9/port/segment.c 304c close(c); . 279a Image *f, **l; . 278d 272c qunlock(&imagealloc.ireclaim); . 268c unlock(p); . 262,265c if(p->image && p->ref == 0 && p->image != &swapimage) { lock(p); . 257c /* Somebody is already cleaning the page cache */ if(!canqlock(&imagealloc.ireclaim)) . 25,26d 22a QLock ireclaim; . 18c struct . ## diffname port/segment.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/port/segment.c /n/bootesdump/1992/0711/sys/src/9/port/segment.c 399c Segment *s, *ns; . ## diffname port/segment.c 1992/0721 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/segment.c /n/bootesdump/1992/0721/sys/src/9/port/segment.c 405c if((va&KZERO) == KZERO) /* BUG: Only ok for now */ . ## diffname port/segment.c 1992/0822 ## diff -e /n/bootesdump/1992/0721/sys/src/9/port/segment.c /n/bootesdump/1992/0822/sys/src/9/port/segment.c 262,263c if(p->image && p->ref == 0 && p->image != &swapimage && canlock(p)) { . ## diffname port/segment.c 1992/0824 ## diff -e /n/bootesdump/1992/0822/sys/src/9/port/segment.c /n/bootesdump/1992/0824/sys/src/9/port/segment.c 427c error(Esoverlap); . 356a if(newsize > (PTEMAPMEM*SEGMAPSIZE)/BY2PG) { qunlock(&s->lk); return -1; } . 352,353c error(Esoverlap); . 349,350c if(newtop >= ns->base && newtop < ns->top) { . 340,344d 324d 322a /* We may start with the bss overlapping the data */ . 162,163c n->flushme = s->flushme; qunlock(&s->lk); return n; . 160a for(i = 0; i < SEGMAPSIZE; i++) if(pte = s->map[i]) n->map[i] = ptecpy(pte); . 151,159c break; . 135c break; . 124c break; . 112a SET(n); . 111d 108a int i; . 103a } . 97c for(p = s->map; p < endpte; p++) { . 65,67c if(i && i->s == s && s->ref == 1) { . ## diffname port/segment.c 1992/0912 ## diff -e /n/bootesdump/1992/0824/sys/src/9/port/segment.c /n/bootesdump/1992/0912/sys/src/9/port/segment.c 348c error(Enovmem); . ## diffname port/segment.c 1992/1104 ## diff -e /n/bootesdump/1992/0912/sys/src/9/port/segment.c /n/bootesdump/1992/1104/sys/src/9/port/segment.c 137a if(segno == TSEG) return data2txt(s); . 112a s = seg[segno]; . 110c Segment *n, *s; . 106c dupseg(Segment **seg, int segno, int share) . ## diffname port/segment.c 1992/1206 ## diff -e /n/bootesdump/1992/1104/sys/src/9/port/segment.c /n/bootesdump/1992/1206/sys/src/9/port/segment.c 410,411c if(u->p->seg[sno] == 0 && sno != ESEG) . 390,391d 386,387d 384a if(--pages == 0) return; j++; . 374,383c break; if(s->map[i] == 0) { pages -= PTEPERTAB-j; j = 0; continue; } while(j < PTEPERTAB) { pg = s->map[i]->pages[j]; if(pg) { putpage(pg); s->map[i]->pages[j] = 0; . 337a flushmmu(); . ## diffname port/segment.c 1993/0120 ## diff -e /n/bootesdump/1992/1206/sys/src/9/port/segment.c /n/bootesdump/1993/0120/sys/src/9/port/segment.c 489,494d 8,9c Page *lkpage(Segment*, ulong); . ## diffname port/segment.c 1993/0210 ## diff -e /n/bootesdump/1993/0120/sys/src/9/port/segment.c /n/bootesdump/1993/0210/sys/src/9/port/segment.c 444,445d 441,442c s->pseg = ps; . 12a #include "io.h" . ## diffname port/segment.c 1993/0501 ## diff -e /n/bootesdump/1993/0210/sys/src/9/port/segment.c /n/fornaxdump/1993/0501/sys/src/brazil/port/segment.c 485a } Page* snewpage(ulong addr) { return newpage(1, 0, addr); . 472c for(i = 0; i < MAXMACH; i++) pg->cachectl[i] |= PG_TXTFLUSH; . 456c s = seg(up, arg[0], 1); . 444a /* Need some code build mapped devices here */ . 443c up->seg[sno] = s; . 421c ns = up->seg[i]; . 411c if(up->seg[sno] == 0 && sno != ESEG) . 343c ns = up->seg[i]; . 326c if(seg != BSEG || up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base) { . 315c s = up->seg[seg]; . 8,9c Page *snewpage(ulong addr); . ## diffname port/segment.c 1993/0507 ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0507/sys/src/brazil/port/segment.c 99a for(i = 0; i < MAXMACH; i++) (*pg)->cachectl[i] |= PG_DATINVALID; } . 98c if(*pg){ . 89a int i; . ## diffname port/segment.c 1993/0725 ## diff -e /n/fornaxdump/1993/0507/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0725/sys/src/brazil/port/segment.c 492,497d 488c . 485,486c while(len > 0 && j < PTEPERTAB) { pg = s->map[i]->pages[j]; if(pg != 0) memset(pg->cachectl, PG_TXTFLUSH, sizeof pg->cachectl); j++; len -= BY2PG; } j = 0; . 471,483c for(i = soff/PTEMAPMEM; len > 0 && i < SEGMAPSIZE; i++) { if(s->map[i] == 0) { len -= PTEMAPMEM; continue; . 469c len = arg[1]+BY2PG; . 457c int i, j, len; . 448,449d 441,442c attr &= ~SG_TYPE; /* Turn off what we are not allowed */ attr |= ps->attr; /* Copy in defaults */ . 407c if((va&KZERO) == KZERO) /* BUG: Only ok for now */ . 247a poperror(); . 245a /* Disaster after commit in exec */ if(waserror()) { unlock(i); pexit(Enovmem, 1); } . 101,103d 99c if(*pg) . 90d 83,84c qunlock(&s->lk); free(s); . 81c emap = &s->map[SEGMAPSIZE]; for(pp = s->map; pp < emap; pp++) if(*pp) freepte(s, *pp); . 76,79c qlock(&s->lk); if(i) putimage(i); . 71,74c s->ref--; if(s->ref != 0) { unlock(s); return; } . 69a else lock(s); . 66c lock(s); if(i->s == s && s->ref == 1) . 64c if(i != 0) { . 8c Page *lkpage(Segment*, ulong); void lkpgfree(Page*); . ## diffname port/segment.c 1993/0810 ## diff -e /n/fornaxdump/1993/0725/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0810/sys/src/brazil/port/segment.c 102,106c if(*p == 0) continue; pte = *p; for(pg = pte->first; pg <= pte->last; pg++) { if(x = *pg) x->va += offset; . 97,98c Page **pg, *x; Pte *pte, **p, **endpte; . ## diffname port/segment.c 1993/0903 ## diff -e /n/fornaxdump/1993/0810/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0903/sys/src/brazil/port/segment.c 478a print("%s segflush 0x%lux %d\n", up->text, arg[0], arg[1]); . ## diffname port/segment.c 1993/0904 ## diff -e /n/fornaxdump/1993/0903/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0904/sys/src/brazil/port/segment.c 479,480d ## diffname port/segment.c 1993/0919 ## diff -e /n/fornaxdump/1993/0904/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0919/sys/src/brazil/port/segment.c 494c chunk = pe-ps; len -= chunk; addr += chunk; qunlock(&s->lk); } . 479,492c l = len; if(addr+l > s->top) l = s->top - addr; ua = addr-s->base; ps = ua&(PTEMAPMEM-1); pe = (ua+l)&(PTEMAPMEM-1); pe = (pe+BY2PG-1)&~(BY2PG-1); if(pe > PTEMAPMEM) pe = PTEMAPMEM; pteflush(s->map[ua/PTEMAPMEM], ps/BY2PG, pe/BY2PG); . 475,477c s->flushme = 1; . 473c while(len > 0) { s = seg(u->p, addr, 1); if(s == 0) error(Ebadarg); . 469,471c addr = arg[0]; len = arg[1]; . 465,467c ulong addr, ua, l; int chunk, ps, pe, len; . 460a void pteflush(Pte *pte, int s, int e) { int i; Page *p; if(pte == 0) return; for(i = s; i < e; i++) { p = pte->pages[i]; if(p != 0) memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl)); } } . ## diffname port/segment.c 1993/0930 ## diff -e /n/fornaxdump/1993/0919/sys/src/brazil/port/segment.c /n/fornaxdump/1993/0930/sys/src/brazil/port/segment.c 488c s = seg(up, addr, 1); . ## diffname port/segment.c 1993/1001 ## diff -e /n/fornaxdump/1993/0930/sys/src/brazil/port/segment.c /n/fornaxdump/1993/1001/sys/src/brazil/port/segment.c 508a if(len > 0 && addr < s->top) goto more; . 505a ps = addr-s->base; pte = s->map[ps/PTEMAPMEM]; ps &= PTEMAPMEM-1; pe = PTEMAPMEM; if(pe-ps > l){ pe = ps + l; pe = (pe+BY2PG-1)&~(BY2PG-1); } if(pe == ps) { qunlock(&s->lk); error(Ebadarg); } if(pte) pteflush(pte, ps/BY2PG, pe/BY2PG); . 497,504d 493c more: . 481c ulong addr, l; Pte *pte; . 472c if(pagedout(p) == 0) . 467,469d ## diffname port/segment.c 1993/1012 ## diff -e /n/fornaxdump/1993/1001/sys/src/brazil/port/segment.c /n/fornaxdump/1993/1012/sys/src/brazil/port/segment.c 8,10c Page* lkpage(Segment*, ulong); void lkpgfree(Page*); void imagereclaim(void); . ## diffname port/segment.c 1994/0514 ## diff -e /n/fornaxdump/1993/1012/sys/src/brazil/port/segment.c /n/fornaxdump/1994/0514/sys/src/brazil/port/segment.c 458c return va; . 456c p->seg[sno] = s; . 441a va = va&~(BY2PG-1); if(isoverlap(p, va, len)) error(Esoverlap); . 432,439c /* Find a hole in the address space */ if(va == 0) { va = p->seg[SSEG]->base - len; for(i = 0; i < 20; i++) { if(isoverlap(p, va, len) == 0) break; va -= len; } . 430d 424c if(p->seg[sno] == 0 && sno != ESEG) . 417c if(va != 0 && (va&KZERO) == KZERO) /* BUG: Only ok for now */ . 414a Segment *s; Physseg *ps; . 411,413d 407a int isoverlap(Proc *p, ulong va, int len) { int i; Segment *ns; ulong newtop; newtop = va+len; for(i = 0; i < NSEG; i++) { ns = p->seg[i]; if(ns == 0) continue; if((newtop > ns->base && newtop <= ns->top) || (va >= ns->base && va < ns->top)) return 1; } return 0; } . ## diffname port/segment.c 1994/0515 ## diff -e /n/fornaxdump/1994/0514/sys/src/brazil/port/segment.c /n/fornaxdump/1994/0515/sys/src/brazil/port/segment.c 146c case SG_DATA: /* Copy on write plus demand load info */ . 135c case SG_BSS: /* Just copy on write */ . 123c case SG_TEXT: /* New segment shares pte set */ . ## diffname port/segment.c 1994/0602 ## diff -e /n/fornaxdump/1994/0515/sys/src/brazil/port/segment.c /n/fornaxdump/1994/0602/sys/src/brazil/port/segment.c 276,277c if(p->ref == 0 && p->image && canlock(p)) { if(p->ref == 0 && p->image != &swapimage) . ## diffname port/segment.c 1994/0817 ## diff -e /n/fornaxdump/1994/0602/sys/src/brazil/port/segment.c /n/fornaxdump/1994/0817/sys/src/brazil/port/segment.c 292c if(i->notext) . 277c if(p->ref == 0) . ## diffname port/segment.c 1995/0804 ## diff -e /n/fornaxdump/1994/0817/sys/src/brazil/port/segment.c /n/fornaxdump/1995/0804/sys/src/brazil/port/segment.c 434d ## diffname port/segment.c 1996/0207 ## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/segment.c /n/fornaxdump/1996/0207/sys/src/brazil/port/segment.c 229c sched(); . ## diffname port/segment.c 1996/0303 ## diff -e /n/fornaxdump/1996/0207/sys/src/brazil/port/segment.c /n/fornaxdump/1996/0303/sys/src/brazil/port/segment.c 543a } void segclock(ulong pc) { Segment *s; s = up->seg[TSEG]; if(s == 0 || s->profile == 0) return; s->profile[0] += TK2MS(1); if(pc >= s->base && pc < s->top) { pc -= s->base; s->profile[pc>>LRESPROF] += TK2MS(1); } . 90a if(s->profile != 0) free(s->profile); . ## diffname port/segment.c 1996/0528 ## diff -e /n/fornaxdump/1996/0303/sys/src/brazil/port/segment.c /n/fornaxdump/1996/0528/sys/src/brazil/port/segment.c 317d 314a /* defer freeing channel till we're out of spin lock's */ if(imagealloc.nfreechan == imagealloc.szfreechan){ imagealloc.szfreechan += NFREECHAN; cp = malloc(imagealloc.szfreechan*sizeof(Chan*)); if(cp == nil) panic("putimage"); memmove(cp, imagealloc.freechan, imagealloc.nfreechan*sizeof(Chan*)); free(imagealloc.freechan); imagealloc.freechan = cp; } imagealloc.freechan[imagealloc.nfreechan++] = c; . 291a /* Somebody is already cleaning the image chans */ if(!canqlock(&imagealloc.fcreclaim)) return; while(imagealloc.nfreechan > 0){ lock(&imagealloc); imagealloc.nfreechan--; c = imagealloc.freechan[imagealloc.nfreechan]; unlock(&imagealloc); close(c); } qunlock(&imagealloc.fcreclaim); } void putimage(Image *i) { Chan *c, **cp; . 289c imagechanreclaim(void) . 287a /* * since close can block, this has to be called outside of * spin locks. */ . 203a /* reclaim any free channels from reclaimed segments */ if(imagealloc.nfreechan) imagechanreclaim(); . 35a imagealloc.freechan = malloc(NFREECHAN * sizeof(Chan*)); imagealloc.szfreechan = NFREECHAN; . 23c QLock ireclaim; /* mutex on reclaiming free images */ Chan **freechan; /* free image channels */ int nfreechan; /* number of free channels */ int szfreechan; /* size of freechan array */ QLock fcreclaim; /* mutex on reclaiming free channels */ . 15a #define NFREECHAN 64 . 10a void imagechanreclaim(void); . ## diffname port/segment.c 1997/0327 ## diff -e /n/fornaxdump/1996/0528/sys/src/brazil/port/segment.c /n/emeliedump/1997/0327/sys/src/brazil/port/segment.c 319c cclose(c); . ## diffname port/segment.c 1997/0516 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/segment.c /n/emeliedump/1997/0516/sys/src/brazil/port/segment.c 146a case SG_MAP: . ## diffname port/segment.c 1998/0326 ## diff -e /n/emeliedump/1997/0516/sys/src/brazil/port/segment.c /n/emeliedump/1998/0326/sys/src/brazil/port/segment.c 474a return 0; } int addphysseg(Physseg* new) { Physseg *ps; /* * Check not already entered and there is room * for a new entry and the terminating null entry. */ lock(&physseglock); for(ps = physseg; ps->name; ps++){ if(strcmp(ps->name, new->name) == 0){ unlock(&physseglock); return -1; } } if(ps-physseg >= nelem(physseg)-2){ unlock(&physseglock); return -1; } *ps = *new; unlock(&physseglock); . 306c static void . 281c static void . 20c static struct . 16a static Lock physseglock; . 8,11c static void imagereclaim(void); static void imagechanreclaim(void); . ## diffname port/segment.c 1998/0512 ## diff -e /n/emeliedump/1998/0326/sys/src/brazil/port/segment.c /n/emeliedump/1998/0512/sys/src/brazil/port/segment.c 470c continue; . 449c s->map[i]->pages[j] = 0; . 438c if(pages <= 0) . 396c . 341c . 338c i->qid = (Qid){~0, ~0}; . 237c . 221,222c * Search the image cache for remains of the text from a previous * or currently running incarnation . 183c return n; . ## diffname port/segment.c 1998/0724 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/segment.c /n/emeliedump/1998/0724/sys/src/brazil/port/segment.c 455a } out: /* wait for others to get fix their tlb's and then free the pages */ if((s->type&SG_TYPE) == SG_SHARED){ } for(pg = list; pg != nil; pg = list){ list = list->next; putpage(pg); . 452c goto out; . 450c pg->next = list; list = pg; . 447,448c if(pg) . 436a list = nil; . 432a Page *list; . 426a /* * called with s->lk locked */ . ## diffname port/segment.c 1998/0725 ## diff -e /n/emeliedump/1998/0724/sys/src/brazil/port/segment.c /n/emeliedump/1998/0725/sys/src/brazil/port/segment.c 465a /* free the pages */ . 463,464c /* flush this seg in all other processes */ i = s->type&SG_TYPE; switch(i){ case SG_SHARED: case SG_SHDATA: procflushseg(s); break; . ## diffname port/segment.c 1998/0823 ## diff -e /n/emeliedump/1998/0725/sys/src/brazil/port/segment.c /n/emeliedump/1998/0823/sys/src/brazil/port/segment.c 454,455c pg->next = list; list = pg; } . 452c if(pg){ . ## diffname port/segment.c 1998/0916 ## diff -e /n/emeliedump/1998/0823/sys/src/brazil/port/segment.c /n/emeliedump/1998/0916/sys/src/brazil/port/segment.c 571c attr &= ~SG_TYPE; /* Turn off what is not allowed */ . 559c if(isoverlap(p, va, len) != nil) . 553a va = os->base; if(len > va) error(Enovmem); . 551,552c for(;;) { os = isoverlap(p, va, len); if(os == nil) . 548c /* * Find a hole in the address space. * Starting at the lowest possible stack address - len, * check for an overlapping segment, and repeat at the * base of that segment - len until either a hole is found * or the address space is exhausted. */ . 540c if(p->seg[sno] == nil && sno != ESEG) . 529,530c int sno; Segment *s, *os; . 496c return nil; . 494c return ns; . 480c Segment* . 442c for(i = soff/PTEMAPMEM; i < size; i++) { . 440a size = s->mapsize; . 433c int i, j, size; . 419a mapsize = ROUND(newsize, PTEPERTAB)/PTEPERTAB; if(mapsize > s->mapsize){ map = smalloc(mapsize*sizeof(Pte*)); memmove(map, s->map, s->mapsize); if(s->map != s->ssegmap) free(s->map); s->map = map; s->mapsize = mapsize; } . 416c if(newsize > (SEGMAPSIZE*PTEPERTAB)) { . 377c int i, mapsize; Pte **map; . 177c size = s->mapsize; for(i = 0; i < size; i++) . 126c int i, size; . 111c endpte = &s->map[s->mapsize]; . 99a if(s->map != s->ssegmap) free(s->map); . 94c emap = &s->map[s->mapsize]; . 60a mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB; if(mapsize > nelem(s->ssegmap)){ s->map = smalloc(mapsize*sizeof(Pte*)); s->mapsize = mapsize; } else{ s->map = s->ssegmap; s->mapsize = nelem(s->ssegmap); } . 50a int mapsize; . ## diffname port/segment.c 1998/0919 ## diff -e /n/emeliedump/1998/0916/sys/src/brazil/port/segment.c /n/emeliedump/1998/0919/sys/src/brazil/port/segment.c 439c memmove(map, s->map, s->mapsize*sizeof(Pte*)); . 64a mapsize *= 2; if(mapsize > (SEGMAPSIZE*PTEPERTAB)) mapsize = (SEGMAPSIZE*PTEPERTAB); . ## diffname port/segment.c 1998/1107 ## diff -e /n/emeliedump/1998/0919/sys/src/brazil/port/segment.c /n/emeliedump/1998/1107/sys/src/brazil/port/segment.c 316a irstats.loops++; irstats.ticks += ticks; if(ticks > irstats.maxt) irstats.maxt = ticks; //print("T%llud+", ticks); . 315a ticks = fastticks(nil) - ticks; . 308a ticks = fastticks(nil); . 303a irstats.calls++; . 302a uvlong ticks; . 298a static struct { int calls; /* times imagereclaim was called */ int loops; /* times the main loop was run */ uvlong ticks; /* total time in the main loop */ uvlong maxt; /* longest time in main loop */ } irstats; . ## diffname port/segment.c 1999/0120 ## diff -e /n/emeliedump/1998/1107/sys/src/brazil/port/segment.c /n/emeliedump/1999/0120/sys/src/brazil/port/segment.c 438a } if(swapfull()){ qunlock(&s->lk); error(Enoswap); . 186a poperror(); . 185a if(waserror()){ qunlock(&s->lk); nexterror(); } . 172a poperror(); . 171a if(waserror()){ qunlock(&s->lk); nexterror(); } . 160a poperror(); . 159a if(waserror()){ qunlock(&s->lk); nexterror(); } . 55a if(swapfull()) error(Enoswap); . ## diffname port/segment.c 1999/1007 ## diff -e /n/emeliedump/1999/0120/sys/src/brazil/port/segment.c /n/emeliedump/1999/1007/sys/src/brazil/port/segment.c 614a if(len == 0) error(Ebadarg); . ## diffname port/segment.c 2000/0229 ## diff -e /n/emeliedump/1999/1007/sys/src/brazil/port/segment.c /n/emeliedump/2000/0229/sys/src/9/port/segment.c 366a /* * We don't have to recheck that nfreechan > 0 after we * acquire the lock, because we're the only ones who decrement * it (the other lock contender increments it), and there's only * one of us thanks to the qlock above. */ . ## diffname port/segment.c 2000/0714 ## diff -e /n/emeliedump/2000/0229/sys/src/9/port/segment.c /n/emeliedump/2000/0714/sys/src/9/port/segment.c 20c static struct Imagealloc . ## diffname port/segment.c 2000/1012 ## diff -e /n/emeliedump/2000/0714/sys/src/9/port/segment.c /n/emeliedump/2000/1012/sys/src/9/port/segment.c 58d ## diffname port/segment.c 2001/0314 ## diff -e /n/emeliedump/2000/1012/sys/src/9/port/segment.c /n/emeliedump/2001/0314/sys/src/9/port/segment.c 218a sameseg: incref(s); poperror(); qunlock(&s->lk); return s; . 216a poperror(); . 203d 198,201d 194,196c goto sameseg; . 191,192c if(share) { if(s->ref != 1) print("Fuckin A again cap'n!\n"); . 189a } . 188c if(segno == TSEG){ poperror(); qunlock(&s->lk); . 184d 179,182d 175,177c goto sameseg; . 172,173c if(share) { if(s->ref != 1) print("Fuckin A cap'n!\n"); . 167d 161,165d 157,158c goto sameseg; . 151a qlock(&s->lk); if(waserror()){ qunlock(&s->lk); nexterror(); } . ## diffname port/segment.c 2001/0424 ## diff -e /n/emeliedump/2001/0314/sys/src/9/port/segment.c /n/emeliedump/2001/0424/sys/src/9/port/segment.c 539,540d 534,537c if(s->ref > 1) . 205a if(s->ref > 1) procflushseg(s); . 191d 186,189c if(share) . 175d 169,173c if(share) . 161d ## diffname port/segment.c 2001/0503 ## diff -e /n/emeliedump/2001/0424/sys/src/9/port/segment.c /n/emeliedump/2001/0503/sys/src/9/port/segment.c 13c /* * Attachable segment types */ static Physseg physseg[10] = { { SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 }, { SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, }; . 11d ## diffname port/segment.c 2001/0507 ## diff -e /n/emeliedump/2001/0503/sys/src/9/port/segment.c /n/emeliedump/2001/0507/sys/src/9/port/segment.c 607a /* * first look for a global segment with the * same name */ if(_globalsegattach != nil){ s = (*_globalsegattach)(p, name); if(s != nil){ p->seg[sno] = s; return s->base; } } . 588a int isphysseg(char *name) { Physseg *ps; int rv = 0; lock(&physseglock); for(ps = physseg; ps->name; ps++){ if(strcmp(ps->name, name) == 0){ rv = 1; break; } } unlock(&physseglock); return rv; } Segment* (*_globalsegattach)(Proc*, char*); . ## diffname port/segment.c 2001/0508 ## diff -e /n/emeliedump/2001/0507/sys/src/9/port/segment.c /n/emeliedump/2001/0508/sys/src/9/port/segment.c 706c int chunk, len; . 704c ulong addr, l, ps, pe; . 665c len = top - va; if(isoverlap(p, va, top) != nil) . 663a top = PGROUND(va + len); . 654c os = isoverlap(p, va, va+len); . 651a len = PGROUND(len); . 640d 629c * first look for a global segment with the . 611a ulong top; . 550d 548d 544c isoverlap(Proc *p, ulong va, int newtop) . ## diffname port/segment.c 2001/0527 ## diff -e /n/emeliedump/2001/0508/sys/src/9/port/segment.c /n/emeliedump/2001/0527/sys/src/9/port/segment.c 707c int chunk, ps, pe, len; . 705c ulong addr, l; . 665,666c if(isoverlap(p, va, len) != nil) . 663d 653c os = isoverlap(p, va, len); . 650d 627,638c len = PGROUND(len); . 610d 587,605d 548a newtop = va+len; . 547a ulong newtop; . 544c isoverlap(Proc *p, ulong va, int len) . 390c mkqid(&i->qid, ~0, ~0, QTFILE); . ## diffname port/segment.c 2002/0329 ## diff -e /n/emeliedump/2001/0527/sys/src/9/port/segment.c /n/emeliedump/2002/0329/sys/src/9/port/segment.c 127a unlock(s); /* keep lock/unlocks balanced */ . ## diffname port/segment.c 2002/0330 ## diff -e /n/emeliedump/2002/0329/sys/src/9/port/segment.c /n/emeliedump/2002/0330/sys/src/9/port/segment.c 608a /* * first look for a global segment with the * same name */ if(_globalsegattach != nil){ s = (*_globalsegattach)(p, name); if(s != nil){ p->seg[sno] = s; return s->base; } } . 589a int isphysseg(char *name) { Physseg *ps; int rv = 0; lock(&physseglock); for(ps = physseg; ps->name; ps++){ if(strcmp(ps->name, name) == 0){ rv = 1; break; } } unlock(&physseglock); return rv; } . 39a Segment* (*_globalsegattach)(Proc*, char*); . ## diffname port/segment.c 2002/0420 ## diff -e /n/emeliedump/2002/0330/sys/src/9/port/segment.c /n/emeliedump/2002/0420/sys/src/9/port/segment.c 130d 114a unlock(s); . ## diffname port/segment.c 2002/0924 ## diff -e /n/emeliedump/2002/0420/sys/src/9/port/segment.c /n/emeliedump/2002/0924/sys/src/9/port/segment.c 525,526d 523a if(onswap(pg)) putswap(pg); else{ pg->next = list; list = pg; } . 522a /* * We want to zero s->map[i]->page[j] and putpage(pg), * but we have to make sure other processors flush the entry * entry from their TLBs before the page is freed. * We construct a list of the pages to be freed, zero * the entries, then (below) call procflushseg, and call * putpage on the whole list. * * Swapped-out pages don't appear in TLBs, so it's okay * to putswap those pages before procflushseg. */ .