diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c index da5f41aec..9da07b071 100644 --- a/sys/src/9/port/page.c +++ b/sys/src/9/port/page.c @@ -78,9 +78,12 @@ freepages(Page *head, Page *tail, int n) tail->next = palloc.head; palloc.head = head; palloc.freecount += n; - if(palloc.r.p != nil) - wakeup(&palloc.r); unlock(&palloc); + + if(palloc.pwait[0].p != nil && wakeup(&palloc.pwait[0]) != nil) + return; + if(palloc.pwait[1].p != nil) + wakeup(&palloc.pwait[1]); } int @@ -135,10 +138,10 @@ pagereclaim(Image *i, int min) return n; } -int +static int ispages(void*) { - return palloc.freecount >= swapalloc.highwater; + return palloc.freecount > swapalloc.highwater || up->noswap && palloc.freecount > 0; } Page* @@ -149,26 +152,22 @@ newpage(int clear, Segment **s, uintptr va) int color; lock(&palloc); - for(;;) { - if(palloc.freecount > swapalloc.highwater) - break; - if(up->kp && palloc.freecount > 0) - break; + while(!ispages(nil)){ unlock(&palloc); if(s != nil) qunlock(*s); if(!waserror()){ - eqlock(&palloc.pwait); /* Hold memory requesters here */ + Rendezq *q; + q = &palloc.pwait[!up->noswap]; + eqlock(q); if(!waserror()){ kickpager(); - tsleep(&palloc.r, ispages, 0, 1000); + sleep(q, ispages, nil); poperror(); } - - qunlock(&palloc.pwait); - + qunlock(q); poperror(); } @@ -182,7 +181,6 @@ newpage(int clear, Segment **s, uintptr va) *s = nil; return nil; } - lock(&palloc); } diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 81bafa4f8..f7501fedc 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -34,6 +34,7 @@ typedef struct QLock QLock; typedef struct Queue Queue; typedef struct Ref Ref; typedef struct Rendez Rendez; +typedef struct Rendezq Rendezq; typedef struct Rgrp Rgrp; typedef struct RWlock RWlock; typedef struct Sargs Sargs; @@ -77,6 +78,12 @@ struct QLock int locked; /* flag */ }; +struct Rendezq +{ + QLock; + Rendez; +}; + struct RWlock { Lock use; @@ -506,8 +513,7 @@ struct Palloc ulong freecount; /* how many pages on free list now */ Page *pages; /* array of all pages */ ulong user; /* how many user pages */ - Rendez r; /* Sleep for free mem */ - QLock pwait; /* Queue of procs waiting for memory */ + Rendezq pwait[2]; /* Queues of procs waiting for memory */ Pallocmem mem[16]; /* physical user page banks */ }; diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 12032e174..e3b379e00 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -138,7 +138,6 @@ void isdir(Chan*); int iseve(void); int islo(void); Segment* isoverlap(Proc*, uintptr, uintptr); -int ispages(void*); int isphysseg(char*); void ixsummary(void); void kickpager(void); diff --git a/sys/src/9/port/swap.c b/sys/src/9/port/swap.c index bc763acf1..73d12345a 100644 --- a/sys/src/9/port/swap.c +++ b/sys/src/9/port/swap.c @@ -159,7 +159,8 @@ pager(void*) up->psstate = "Reclaim"; if(reclaim()){ up->psstate = "Idle"; - wakeup(&palloc.r); + wakeup(&palloc.pwait[0]); + wakeup(&palloc.pwait[1]); sleep(&swapalloc.r, needpages, nil); continue; }