|
|
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: #define pghash(daddr) palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]
9:
10: static Lock pglock;
11: struct Palloc palloc;
12:
13: void
14: pageinit(void)
15: {
16: Page *p;
17: ulong np, hw, hr, vmem, pmem;
18:
19: np = palloc.np0+palloc.np1;
20: palloc.head = xalloc(np*sizeof(Page));
21: if(palloc.head == 0)
22: panic("pageinit");
23:
24: p = palloc.head;
25: while(palloc.np0 > 0) {
26: p->prev = p-1;
27: p->next = p+1;
28: p->pa = palloc.p0;
29: palloc.p0 += BY2PG;
30: palloc.np0--;
31: p++;
32: }
33: while(palloc.np1 > 0) {
34: p->prev = p-1;
35: p->next = p+1;
36: p->pa = palloc.p1;
37: palloc.p1 += BY2PG;
38: palloc.np1--;
39: p++;
40: }
41: palloc.tail = p - 1;
42: palloc.head->prev = 0;
43: palloc.tail->next = 0;
44:
45: palloc.user = p - palloc.head;
46: palloc.freecount = palloc.user;
47: pmem = palloc.user*BY2PG/1024;
48: vmem = pmem + (conf.nswap*BY2PG)/1024;
49:
50: /* Pageing numbers */
51: swapalloc.highwater = (palloc.freecount*5)/100;
52: swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
53:
54: hw = swapalloc.highwater*BY2PG;
55: hr = swapalloc.headroom*BY2PG;
56:
57: print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n",
58: palloc.user, pmem, vmem, hw/1024, hr/1024);/**/
59: }
60:
61: Page*
62: newpage(int clear, Segment **s, ulong va)
63: {
64: Page *p;
65: KMap *k;
66: int hw, i, dontalloc;
67:
68: retry:
69: lock(&palloc);
70:
71: hw = swapalloc.highwater;
72: while((palloc.freecount < hw && u->p->kp == 0) || palloc.freecount == 0) {
73: palloc.wanted++;
74: unlock(&palloc);
75: dontalloc = 0;
76: if(s && *s) {
77: qunlock(&((*s)->lk));
78: *s = 0;
79: dontalloc = 1;
80: }
81: qlock(&palloc.pwait); /* Hold memory requesters here */
82:
83: while(waserror()) /* Ignore interrupts */
84: ;
85:
86: kickpager();
87: tsleep(&palloc.r, ispages, 0, 1000);
88:
89: poperror();
90:
91: qunlock(&palloc.pwait);
92:
93: /*
94: * If called from fault and we lost the segment from underneath
95: * don't waste time allocating and freeing a page. Fault will call
96: * newpage again when it has reacquired the segment locks
97: */
98: if(dontalloc)
99: return 0;
100:
101: lock(&palloc);
102: palloc.wanted--;
103: }
104:
105: p = palloc.head;
106: if(palloc.head = p->next) /* = Assign */
107: palloc.head->prev = 0;
108: else
109: palloc.tail = 0;
110:
111: palloc.freecount--;
112: unlock(&palloc);
113:
114: lock(p);
115: if(p->ref != 0) { /* lookpage has priority on steal */
116: unlock(p);
117: goto retry;
118: }
119: uncachepage(p);
120: p->ref++;
121: p->va = va;
122: p->modref = 0;
123: for(i = 0; i < MAXMACH; i++)
124: p->cachectl[i] = PG_NOFLUSH;
125: mmunewpage(p);
126: unlock(p);
127:
128: if(clear){
129: k = kmap(p);
130: memset((void*)VA(k), 0, BY2PG);
131: kunmap(k);
132: }
133:
134: return p;
135: }
136:
137: int
138: ispages(void *p)
139: {
140: USED(p);
141: return palloc.freecount >= swapalloc.highwater;
142: }
143:
144: void
145: putpage(Page *p)
146: {
147: if(onswap(p)) {
148: putswap(p);
149: return;
150: }
151:
152: lock(p);
153: if(--p->ref == 0) {
154: lock(&palloc);
155: if(p->image && p->image != &swapimage) {
156: if(palloc.tail) {
157: p->prev = palloc.tail;
158: palloc.tail->next = p;
159: }
160: else {
161: palloc.head = p;
162: p->prev = 0;
163: }
164: palloc.tail = p;
165: p->next = 0;
166: }
167: else {
168: if(palloc.head) {
169: p->next = palloc.head;
170: palloc.head->prev = p;
171: }
172: else {
173: palloc.tail = p;
174: p->next = 0;
175: }
176: palloc.head = p;
177: p->prev = 0;
178: }
179:
180: palloc.freecount++; /* Release people waiting for memory */
181: if(palloc.r.p != 0)
182: wakeup(&palloc.r);
183: unlock(&palloc);
184: }
185: unlock(p);
186: }
187:
188: void
189: simpleputpage(Page *pg) /* Always call with palloc locked */
190: {
191: if(pg->ref != 1)
192: panic("simpleputpage");
193: pg->ref = 0;
194: palloc.freecount++;
195: if(palloc.head == 0) {
196: palloc.head = palloc.tail = pg;
197: pg->prev = pg->next = 0;
198: return;
199: }
200: pg->next = palloc.head;
201: palloc.head->prev = pg;
202: pg->prev = 0;
203: palloc.head = pg;
204: }
205:
206: void
207: duppage(Page *p) /* Always call with p locked */
208: {
209: Page *np;
210:
211: /* No dup for swap pages */
212: if(p->image == &swapimage) {
213: uncachepage(p);
214: return;
215: }
216:
217: lock(&palloc);
218: /* No freelist cache when memory is very low */
219: if(palloc.freecount < swapalloc.highwater) {
220: unlock(&palloc);
221: uncachepage(p);
222: return;
223: }
224:
225: np = palloc.head; /* Allocate a new page from freelist */
226: if(palloc.head = np->next) /* = Assign */
227: palloc.head->prev = 0;
228: else
229: palloc.tail = 0;
230:
231: if(palloc.tail) { /* Link back onto tail to give us lru */
232: np->prev = palloc.tail;
233: palloc.tail->next = np;
234: np->next = 0;
235: palloc.tail = np;
236: }
237: else {
238: palloc.head = palloc.tail = np;
239: np->prev = np->next = 0;
240: }
241:
242: unlock(&palloc);
243:
244: lock(np); /* Cache the new version */
245: if(np->ref != 0) { /* Stolen by lookpage */
246: uncachepage(p);
247: unlock(np);
248: return;
249: }
250:
251: uncachepage(np);
252: np->va = p->va;
253: np->daddr = p->daddr;
254: mmunewpage(np);
255: copypage(p, np);
256: cachepage(np, p->image);
257: unlock(np);
258: uncachepage(p);
259: }
260:
261: void
262: copypage(Page *f, Page *t)
263: {
264: KMap *ks, *kd;
265:
266: ks = kmap(f);
267: kd = kmap(t);
268: memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
269: kunmap(ks);
270: kunmap(kd);
271: }
272:
273: void
274: uncachepage(Page *p) /* Always called with a locked page */
275: {
276: Page **l, *f;
277:
278: if(p->image == 0)
279: return;
280:
281: lock(&palloc.hashlock);
282: l = &pghash(p->daddr);
283: for(f = *l; f; f = f->hash) {
284: if(f == p) {
285: *l = p->hash;
286: break;
287: }
288: l = &f->hash;
289: }
290: unlock(&palloc.hashlock);
291: putimage(p->image);
292: p->image = 0;
293: }
294:
295: void
296: cachepage(Page *p, Image *i)
297: {
298: Page **l;
299:
300: /* If this ever happens it should be fixed by calling
301: * uncachepage instead of panic. I think there is a race
302: * with pio in which this can happen. Calling uncachepage is
303: * correct - I just wanted to see if we got here.
304: */
305: if(p->image)
306: panic("cachepage");
307:
308: incref(i);
309: lock(&palloc.hashlock);
310: p->image = i;
311: l = &pghash(p->daddr);
312: p->hash = *l;
313: *l = p;
314: unlock(&palloc.hashlock);
315: }
316:
317: void
318: cachedel(Image *i, ulong daddr)
319: {
320: Page *f, **l;
321:
322: lock(&palloc.hashlock);
323: l = &pghash(daddr);
324: for(f = *l; f; f = f->hash) {
325: if(f->image == i && f->daddr == daddr) {
326: *l = f->hash;
327: break;
328: }
329: l = &f->hash;
330: }
331: unlock(&palloc.hashlock);
332: }
333:
334: Page *
335: lookpage(Image *i, ulong daddr)
336: {
337: Page *f;
338:
339: lock(&palloc.hashlock);
340: for(f = pghash(daddr); f; f = f->hash) {
341: if(f->image == i && f->daddr == daddr) {
342: unlock(&palloc.hashlock);
343:
344: lock(f);
345: if(f->image != i || f->daddr != daddr) {
346: unlock(f);
347: return 0;
348: }
349:
350: lock(&palloc);
351: if(++f->ref == 1) {
352: if(f->prev)
353: f->prev->next = f->next;
354: else
355: palloc.head = f->next;
356:
357: if(f->next)
358: f->next->prev = f->prev;
359: else
360: palloc.tail = f->prev;
361: palloc.freecount--;
362: }
363: unlock(&palloc);
364:
365: unlock(f);
366: return f;
367: }
368: }
369: unlock(&palloc.hashlock);
370: return 0;
371: }
372:
373: Pte*
374: ptecpy(Pte *old)
375: {
376: Pte *new;
377: Page **src, **dst;
378:
379: new = ptealloc();
380: dst = &new->pages[old->first-old->pages];
381: new->first = dst;
382: for(src = old->first; src <= old->last; src++, dst++)
383: if(*src) {
384: if(onswap(*src))
385: dupswap(*src);
386: else {
387: lock(*src);
388: (*src)->ref++;
389: unlock(*src);
390: }
391: new->last = dst;
392: *dst = *src;
393: }
394:
395: return new;
396: }
397:
398: Pte*
399: ptealloc(void)
400: {
401: Pte *new;
402:
403: new = smalloc(sizeof(Pte));
404: new->first = &new->pages[PTEPERTAB];
405: new->last = new->pages;
406: return new;
407: }
408:
409: void
410: freepte(Segment *s, Pte *p)
411: {
412: int ref;
413: Page *pt, **pg, **ptop;
414: void (*fn)(Page*);
415:
416: switch(s->type&SG_TYPE) {
417: case SG_PHYSICAL:
418: fn = s->pseg->pgfree;
419: ptop = &p->pages[PTEPERTAB];
420: if(fn) {
421: for(pg = p->pages; pg < ptop; pg++) {
422: if(*pg == 0)
423: continue;
424: (*fn)(*pg);
425: *pg = 0;
426: }
427: break;
428: }
429: for(pg = p->pages; pg < ptop; pg++) {
430: pt = *pg;
431: if(pt == 0)
432: continue;
433: lock(pt);
434: ref = --pt->ref;
435: unlock(pt);
436: if(ref == 0)
437: free(pt);
438: }
439: break;
440: default:
441: for(pg = p->first; pg <= p->last; pg++)
442: if(*pg) {
443: putpage(*pg);
444: *pg = 0;
445: }
446: }
447: free(p);
448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.