|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: ! 8: Page *lkpage(Segment*, ulong); ! 9: void lkpgfree(Page*); ! 10: void imagereclaim(void); ! 11: ! 12: /* System specific segattach devices */ ! 13: #include "io.h" ! 14: #include "segment.h" ! 15: ! 16: #define IHASHSIZE 64 ! 17: #define ihash(s) imagealloc.hash[s%IHASHSIZE] ! 18: struct ! 19: { ! 20: Lock; ! 21: Image *free; ! 22: Image *hash[IHASHSIZE]; ! 23: QLock ireclaim; ! 24: }imagealloc; ! 25: ! 26: void ! 27: initseg(void) ! 28: { ! 29: Image *i, *ie; ! 30: ! 31: imagealloc.free = xalloc(conf.nimage*sizeof(Image)); ! 32: ie = &imagealloc.free[conf.nimage-1]; ! 33: for(i = imagealloc.free; i < ie; i++) ! 34: i->next = i+1; ! 35: i->next = 0; ! 36: } ! 37: ! 38: Segment * ! 39: newseg(int type, ulong base, ulong size) ! 40: { ! 41: Segment *s; ! 42: ! 43: if(size > (SEGMAPSIZE*PTEPERTAB)) ! 44: error(Enovmem); ! 45: ! 46: s = smalloc(sizeof(Segment)); ! 47: s->ref = 1; ! 48: s->type = type; ! 49: s->base = base; ! 50: s->top = base+(size*BY2PG); ! 51: s->size = size; ! 52: return s; ! 53: } ! 54: ! 55: void ! 56: putseg(Segment *s) ! 57: { ! 58: Pte **pp, **emap; ! 59: Image *i; ! 60: ! 61: if(s == 0) ! 62: return; ! 63: ! 64: i = s->image; ! 65: if(i != 0) { ! 66: lock(i); ! 67: lock(s); ! 68: if(i->s == s && s->ref == 1) ! 69: i->s = 0; ! 70: unlock(i); ! 71: } ! 72: else ! 73: lock(s); ! 74: ! 75: s->ref--; ! 76: if(s->ref != 0) { ! 77: unlock(s); ! 78: return; ! 79: } ! 80: ! 81: qlock(&s->lk); ! 82: if(i) ! 83: putimage(i); ! 84: ! 85: emap = &s->map[SEGMAPSIZE]; ! 86: for(pp = s->map; pp < emap; pp++) ! 87: if(*pp) ! 88: freepte(s, *pp); ! 89: ! 90: qunlock(&s->lk); ! 91: free(s); ! 92: } ! 93: ! 94: void ! 95: relocateseg(Segment *s, ulong offset) ! 96: { ! 97: Pte **p, **endpte; ! 98: Page **pg, **endpages; ! 99: ! 100: endpte = &s->map[SEGMAPSIZE]; ! 101: for(p = s->map; p < endpte; p++) { ! 102: if(*p) { ! 103: endpages = &((*p)->pages[PTEPERTAB]); ! 104: for(pg = (*p)->pages; pg < endpages; pg++) ! 105: if(*pg) ! 106: (*pg)->va += offset; ! 107: } ! 108: } ! 109: } ! 110: ! 111: Segment* ! 112: dupseg(Segment **seg, int segno, int share) ! 113: { ! 114: int i; ! 115: Pte *pte; ! 116: Segment *n, *s; ! 117: ! 118: SET(n); ! 119: s = seg[segno]; ! 120: ! 121: switch(s->type&SG_TYPE) { ! 122: case SG_TEXT: /* New segment shares pte set */ ! 123: case SG_SHARED: ! 124: case SG_PHYSICAL: ! 125: case SG_SHDATA: ! 126: incref(s); ! 127: return s; ! 128: ! 129: case SG_STACK: ! 130: qlock(&s->lk); ! 131: n = newseg(s->type, s->base, s->size); ! 132: break; ! 133: ! 134: case SG_BSS: /* Just copy on write */ ! 135: qlock(&s->lk); ! 136: if(share && s->ref == 1) { ! 137: s->type = (s->type&~SG_TYPE)|SG_SHARED; ! 138: incref(s); ! 139: qunlock(&s->lk); ! 140: return s; ! 141: } ! 142: n = newseg(s->type, s->base, s->size); ! 143: break; ! 144: ! 145: case SG_DATA: /* Copy on write plus demand load info */ ! 146: if(segno == TSEG) ! 147: return data2txt(s); ! 148: ! 149: qlock(&s->lk); ! 150: if(share && s->ref == 1) { ! 151: s->type = (s->type&~SG_TYPE)|SG_SHDATA; ! 152: incref(s); ! 153: qunlock(&s->lk); ! 154: return s; ! 155: } ! 156: n = newseg(s->type, s->base, s->size); ! 157: ! 158: incref(s->image); ! 159: n->image = s->image; ! 160: n->fstart = s->fstart; ! 161: n->flen = s->flen; ! 162: break; ! 163: } ! 164: for(i = 0; i < SEGMAPSIZE; i++) ! 165: if(pte = s->map[i]) ! 166: n->map[i] = ptecpy(pte); ! 167: ! 168: n->flushme = s->flushme; ! 169: qunlock(&s->lk); ! 170: return n; ! 171: } ! 172: ! 173: void ! 174: segpage(Segment *s, Page *p) ! 175: { ! 176: Pte **pte; ! 177: ulong off; ! 178: Page **pg; ! 179: ! 180: if(p->va < s->base || p->va >= s->top) ! 181: panic("segpage"); ! 182: ! 183: off = p->va - s->base; ! 184: pte = &s->map[off/PTEMAPMEM]; ! 185: if(*pte == 0) ! 186: *pte = ptealloc(); ! 187: ! 188: pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG]; ! 189: *pg = p; ! 190: if(pg < (*pte)->first) ! 191: (*pte)->first = pg; ! 192: if(pg > (*pte)->last) ! 193: (*pte)->last = pg; ! 194: } ! 195: ! 196: Image* ! 197: attachimage(int type, Chan *c, ulong base, ulong len) ! 198: { ! 199: Image *i, **l; ! 200: ! 201: lock(&imagealloc); ! 202: ! 203: /* ! 204: * Search the image cache for remains of the text from a previous ! 205: * or currently running incarnation ! 206: */ ! 207: for(i = ihash(c->qid.path); i; i = i->hash) { ! 208: if(c->qid.path == i->qid.path) { ! 209: lock(i); ! 210: if(eqqid(c->qid, i->qid) && ! 211: eqqid(c->mqid, i->mqid) && ! 212: c->mchan == i->mchan && ! 213: c->type == i->type) { ! 214: i->ref++; ! 215: goto found; ! 216: } ! 217: unlock(i); ! 218: } ! 219: } ! 220: ! 221: /* ! 222: * imagereclaim dumps pages from the free list which are cached by image ! 223: * structures. This should free some image structures. ! 224: */ ! 225: while(!(i = imagealloc.free)) { ! 226: unlock(&imagealloc); ! 227: imagereclaim(); ! 228: resrcwait(0); ! 229: lock(&imagealloc); ! 230: } ! 231: ! 232: imagealloc.free = i->next; ! 233: ! 234: lock(i); ! 235: incref(c); ! 236: i->c = c; ! 237: i->type = c->type; ! 238: i->qid = c->qid; ! 239: i->mqid = c->mqid; ! 240: i->mchan = c->mchan; ! 241: i->ref = 1; ! 242: l = &ihash(c->qid.path); ! 243: i->hash = *l; ! 244: *l = i; ! 245: found: ! 246: unlock(&imagealloc); ! 247: ! 248: if(i->s == 0) { ! 249: /* Disaster after commit in exec */ ! 250: if(waserror()) { ! 251: unlock(i); ! 252: pexit(Enovmem, 1); ! 253: } ! 254: i->s = newseg(type, base, len); ! 255: i->s->image = i; ! 256: poperror(); ! 257: } ! 258: else ! 259: incref(i->s); ! 260: ! 261: return i; ! 262: } ! 263: ! 264: void ! 265: imagereclaim(void) ! 266: { ! 267: Page *p; ! 268: ! 269: /* Somebody is already cleaning the page cache */ ! 270: if(!canqlock(&imagealloc.ireclaim)) ! 271: return; ! 272: ! 273: lock(&palloc); ! 274: for(p = palloc.head; p; p = p->next) { ! 275: if(p->image && p->ref == 0 && p->image != &swapimage && canlock(p)) { ! 276: if(p->ref == 0) ! 277: uncachepage(p); ! 278: unlock(p); ! 279: } ! 280: } ! 281: unlock(&palloc); ! 282: qunlock(&imagealloc.ireclaim); ! 283: } ! 284: ! 285: void ! 286: putimage(Image *i) ! 287: { ! 288: Chan *c; ! 289: Image *f, **l; ! 290: ! 291: if(i == &swapimage) ! 292: return; ! 293: ! 294: lock(i); ! 295: if(--i->ref == 0) { ! 296: l = &ihash(i->qid.path); ! 297: i->qid = (Qid){~0, ~0}; ! 298: unlock(i); ! 299: c = i->c; ! 300: ! 301: lock(&imagealloc); ! 302: for(f = *l; f; f = f->hash) { ! 303: if(f == i) { ! 304: *l = i->hash; ! 305: break; ! 306: } ! 307: l = &f->hash; ! 308: } ! 309: ! 310: i->next = imagealloc.free; ! 311: imagealloc.free = i; ! 312: unlock(&imagealloc); ! 313: ! 314: close(c); ! 315: return; ! 316: } ! 317: unlock(i); ! 318: } ! 319: ! 320: long ! 321: ibrk(ulong addr, int seg) ! 322: { ! 323: Segment *s, *ns; ! 324: ulong newtop, newsize; ! 325: int i; ! 326: ! 327: s = u->p->seg[seg]; ! 328: if(s == 0) ! 329: error(Ebadarg); ! 330: ! 331: if(addr == 0) ! 332: return s->base; ! 333: ! 334: qlock(&s->lk); ! 335: ! 336: /* We may start with the bss overlapping the data */ ! 337: if(addr < s->base) { ! 338: if(seg != BSEG || u->p->seg[DSEG] == 0 || addr < u->p->seg[DSEG]->base) { ! 339: qunlock(&s->lk); ! 340: error(Enovmem); ! 341: } ! 342: addr = s->base; ! 343: } ! 344: ! 345: newtop = PGROUND(addr); ! 346: newsize = (newtop-s->base)/BY2PG; ! 347: if(newtop < s->top) { ! 348: mfreeseg(s, newtop, (s->top-newtop)/BY2PG); ! 349: qunlock(&s->lk); ! 350: flushmmu(); ! 351: return 0; ! 352: } ! 353: ! 354: for(i = 0; i < NSEG; i++) { ! 355: ns = u->p->seg[i]; ! 356: if(ns == 0 || ns == s) ! 357: continue; ! 358: if(newtop >= ns->base && newtop < ns->top) { ! 359: qunlock(&s->lk); ! 360: error(Esoverlap); ! 361: } ! 362: } ! 363: ! 364: if(newsize > (PTEMAPMEM*SEGMAPSIZE)/BY2PG) { ! 365: qunlock(&s->lk); ! 366: error(Enovmem); ! 367: } ! 368: ! 369: s->top = newtop; ! 370: s->size = newsize; ! 371: qunlock(&s->lk); ! 372: return 0; ! 373: } ! 374: ! 375: void ! 376: mfreeseg(Segment *s, ulong start, int pages) ! 377: { ! 378: int i, j; ! 379: ulong soff; ! 380: Page *pg; ! 381: ! 382: soff = start-s->base; ! 383: j = (soff&(PTEMAPMEM-1))/BY2PG; ! 384: ! 385: for(i = soff/PTEMAPMEM; i < SEGMAPSIZE; i++) { ! 386: if(pages <= 0) ! 387: break; ! 388: if(s->map[i] == 0) { ! 389: pages -= PTEPERTAB-j; ! 390: j = 0; ! 391: continue; ! 392: } ! 393: while(j < PTEPERTAB) { ! 394: pg = s->map[i]->pages[j]; ! 395: if(pg) { ! 396: putpage(pg); ! 397: s->map[i]->pages[j] = 0; ! 398: } ! 399: if(--pages == 0) ! 400: return; ! 401: j++; ! 402: } ! 403: j = 0; ! 404: } ! 405: } ! 406: ! 407: int ! 408: isoverlap(ulong va, int len) ! 409: { ! 410: int i; ! 411: Segment *ns; ! 412: ulong newtop; ! 413: ! 414: newtop = va+len; ! 415: for(i = 0; i < NSEG; i++) { ! 416: ns = u->p->seg[i]; ! 417: if(ns == 0) ! 418: continue; ! 419: if((newtop > ns->base && newtop <= ns->top) || ! 420: (va >= ns->base && va < ns->top)) ! 421: return 1; ! 422: } ! 423: return 0; ! 424: } ! 425: ! 426: ulong ! 427: segattach(Proc *p, ulong attr, char *name, ulong va, ulong len) ! 428: { ! 429: int i, sno; ! 430: Segment *s; ! 431: Physseg *ps; ! 432: ! 433: USED(p); ! 434: if(va != 0 && (va&KZERO) == KZERO) /* BUG: Only ok for now */ ! 435: error(Ebadarg); ! 436: ! 437: validaddr((ulong)name, 1, 0); ! 438: vmemchr(name, 0, ~0); ! 439: ! 440: for(sno = 0; sno < NSEG; sno++) ! 441: if(u->p->seg[sno] == 0 && sno != ESEG) ! 442: break; ! 443: ! 444: if(sno == NSEG) ! 445: error(Enovmem); ! 446: ! 447: len = PGROUND(len); ! 448: ! 449: /* Find a hole in the address space */ ! 450: if(va == 0) { ! 451: va = p->seg[SSEG]->base - len; ! 452: for(i = 0; i < 20; i++) { ! 453: if(isoverlap(va, len) == 0) ! 454: break; ! 455: va -= len; ! 456: } ! 457: } ! 458: ! 459: va = va&~(BY2PG-1); ! 460: if(isoverlap(va, len)) ! 461: error(Esoverlap); ! 462: ! 463: for(ps = physseg; ps->name; ps++) ! 464: if(strcmp(name, ps->name) == 0) ! 465: goto found; ! 466: ! 467: error(Ebadarg); ! 468: found: ! 469: if(len > ps->size) ! 470: error(Enovmem); ! 471: ! 472: attr &= ~SG_TYPE; /* Turn off what we are not allowed */ ! 473: attr |= ps->attr; /* Copy in defaults */ ! 474: ! 475: s = newseg(attr, va, len/BY2PG); ! 476: s->pseg = ps; ! 477: u->p->seg[sno] = s; ! 478: ! 479: return va; ! 480: } ! 481: ! 482: void ! 483: pteflush(Pte *pte, int s, int e) ! 484: { ! 485: int i; ! 486: Page *p; ! 487: ! 488: for(i = s; i < e; i++) { ! 489: p = pte->pages[i]; ! 490: if(pagedout(p) == 0) ! 491: memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl)); ! 492: } ! 493: } ! 494: ! 495: ! 496: long ! 497: syssegflush(ulong *arg) ! 498: { Segment *s; ! 499: ulong addr, l; ! 500: Pte *pte; ! 501: int chunk, ps, pe, len; ! 502: ! 503: addr = arg[0]; ! 504: len = arg[1]; ! 505: ! 506: while(len > 0) { ! 507: s = seg(u->p, addr, 1); ! 508: if(s == 0) ! 509: error(Ebadarg); ! 510: ! 511: s->flushme = 1; ! 512: more: ! 513: l = len; ! 514: if(addr+l > s->top) ! 515: l = s->top - addr; ! 516: ! 517: ps = addr-s->base; ! 518: pte = s->map[ps/PTEMAPMEM]; ! 519: ps &= PTEMAPMEM-1; ! 520: pe = PTEMAPMEM; ! 521: if(pe-ps > l){ ! 522: pe = ps + l; ! 523: pe = (pe+BY2PG-1)&~(BY2PG-1); ! 524: } ! 525: if(pe == ps) { ! 526: qunlock(&s->lk); ! 527: error(Ebadarg); ! 528: } ! 529: ! 530: if(pte) ! 531: pteflush(pte, ps/BY2PG, pe/BY2PG); ! 532: ! 533: chunk = pe-ps; ! 534: len -= chunk; ! 535: addr += chunk; ! 536: ! 537: if(len > 0 && addr < s->top) ! 538: goto more; ! 539: ! 540: qunlock(&s->lk); ! 541: } ! 542: flushmmu(); ! 543: return 0; ! 544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.