|
|
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.