From 8c137149bd54a9bba8026ddf4bc4f49f7ccbb404 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-01-20 --- port/error.h | 1 + port/fault.c | 21 ++++++++++++++------- port/portfns.h | 1 + port/segment.c | 23 +++++++++++++++++++++++ port/swap.c | 15 +++++++++++++-- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/port/error.h b/port/error.h index 6f123a2ea6f36214654a0c496b5a01753272e3b3..6cc752c0d9e1e7e0525c754cc252081b324000fb 100644 --- a/port/error.h +++ b/port/error.h @@ -46,6 +46,7 @@ extern char Enetunreach[]; /* network unreachable */ extern char Eintr[]; /* interrupted */ extern char Eneedservice[]; /* service required for tcp/udp/il calls */ extern char Enomem[]; /* kernel allocate failed */ +extern char Enoswap[]; /* swap space full */ extern char Esfnotcached[]; /* subfont not cached */ extern char Esoverlap[]; /* segments overlap */ extern char Emouseset[]; /* mouse type already set */ diff --git a/port/fault.c b/port/fault.c index 9b8b342ff29e3b43d70b3753bae2b52f4864b86e..131b65f462b0b3a12fbae4ec92cb03eeb938b42d 100644 --- a/port/fault.c +++ b/port/fault.c @@ -38,13 +38,13 @@ fault(ulong addr, int read) } static void -faulterror(char *s) +faulterror(char *s, int freemem) { if(up->nerrlab) { postnote(up, 1, s, NDebug); error(s); } - pexit(s, 0); + pexit(s, freemem); } int @@ -125,6 +125,13 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) ref = lkp->ref; if(ref > 1) { unlock(lkp); + + if(swapfull()){ + qunlock(&s->lk); + pprint("swap space full\n"); + faulterror(Enoswap, 1); + } + new = newpage(0, &s, addr); if(s == 0) return -1; @@ -134,7 +141,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) } else { /* save a copy of the original for the image cache */ - if(lkp->image) + if(lkp->image && !swapfull()) duppage(lkp); unlock(lkp); @@ -214,7 +221,7 @@ retry: continue; kunmap(k); putpage(new); - faulterror("sys: demand load I/O error"); + faulterror("sys: demand load I/O error", 0); } ask = s->flen-soff; @@ -223,7 +230,7 @@ retry: n = devtab[c->type]->read(c, kaddr, ask, daddr); if(n != ask) - faulterror(Eioload); + faulterror(Eioload, 0); if(ask < BY2PG) memset(kaddr+ask, 0, BY2PG-ask); @@ -250,12 +257,12 @@ retry: putpage(new); qlock(&s->lk); qunlock(&s->lk); - faulterror("sys: page in I/O error"); + faulterror("sys: page in I/O error", 0); } n = devtab[c->type]->read(c, kaddr, BY2PG, daddr); if(n != BY2PG) - faulterror(Eioload); + faulterror(Eioload, 0); poperror(); kunmap(k); diff --git a/port/portfns.h b/port/portfns.h index 8de2eeb0bf5560b13530e7881425f03debf1ff55..b700fe2098f7369c8c027e1a8ae91947054ec4ef 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -295,6 +295,7 @@ void splx(int); void splxpc(int); void srvrecover(Chan*, Chan*); int swapcount(ulong); +int swapfull(void); void swapinit(void); Block* trimblock(Block*, int, int); void tsleep(Rendez*, int (*)(void*), void*, int); diff --git a/port/segment.c b/port/segment.c index a6a65178290177b0eddce50019d5b7f67c48c168..66ef6bce2870c9ebc604c2bebe30281723990355 100644 --- a/port/segment.c +++ b/port/segment.c @@ -53,6 +53,9 @@ newseg(int type, ulong base, ulong size) if(size > (SEGMAPSIZE*PTEPERTAB)) error(Enovmem); + if(swapfull()) + error(Enoswap); + s = smalloc(sizeof(Segment)); s->ref = 1; s->type = type; @@ -157,7 +160,12 @@ dupseg(Segment **seg, int segno, int share) case SG_STACK: qlock(&s->lk); + if(waserror()){ + qunlock(&s->lk); + nexterror(); + } n = newseg(s->type, s->base, s->size); + poperror(); break; case SG_BSS: /* Just copy on write */ @@ -169,7 +177,12 @@ dupseg(Segment **seg, int segno, int share) qunlock(&s->lk); return s; } + if(waserror()){ + qunlock(&s->lk); + nexterror(); + } n = newseg(s->type, s->base, s->size); + poperror(); break; case SG_DATA: /* Copy on write plus demand load info */ @@ -183,7 +196,12 @@ dupseg(Segment **seg, int segno, int share) qunlock(&s->lk); return s; } + if(waserror()){ + qunlock(&s->lk); + nexterror(); + } n = newseg(s->type, s->base, s->size); + poperror(); incref(s->image); n->image = s->image; @@ -438,6 +456,11 @@ ibrk(ulong addr, int seg) return 0; } + if(swapfull()){ + qunlock(&s->lk); + error(Enoswap); + } + for(i = 0; i < NSEG; i++) { ns = up->seg[i]; if(ns == 0 || ns == s) diff --git a/port/swap.c b/port/swap.c index 6ee65b0d1e0db595002d60eee5bcb64e82445e15..81f5a13f36b539c7e681f6b62f388ce50a9800b7 100644 --- a/port/swap.c +++ b/port/swap.c @@ -38,8 +38,11 @@ newswap(void) uchar *look; lock(&swapalloc); - if(swapalloc.free == 0) - panic("out of swap space"); + + if(swapalloc.free == 0){ + unlock(&swapalloc); + return ~0; + } look = memchr(swapalloc.last, 0, swapalloc.top-swapalloc.last); if(look == 0) @@ -285,6 +288,8 @@ pagepte(int type, Page **pg) * referring to it from the cache */ daddr = newswap(); + if(daddr == ~0) + break; cachedel(&swapimage, daddr); lock(outp); @@ -396,3 +401,9 @@ setswapchan(Chan *c) swapimage.c = c; } + +int +swapfull(void) +{ + return swapalloc.free < conf.nswap/10; +}