diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-08-24 14:43:15 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-08-24 14:43:15 +0200 |
commit | cf974eb852cb316772b2294a80069dd8f99e19e9 (patch) | |
tree | aac0418fb930417426b850bca7a1ace709acce78 /sys/src/9/port/page.c | |
parent | 61a0117ea5ddf0a17079faf755b4d51cc045c4ae (diff) |
fix kernel: pio()/mfreeseg() race
Diffstat (limited to 'sys/src/9/port/page.c')
-rw-r--r-- | sys/src/9/port/page.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c index b99e3588b..fc5906b9e 100644 --- a/sys/src/9/port/page.c +++ b/sys/src/9/port/page.c @@ -123,7 +123,7 @@ newpage(int clear, Segment **s, ulong va) Page *p; KMap *k; uchar ct; - int i, hw, dontalloc, color; + int i, hw, color; lock(&palloc); color = getpgcolor(va); @@ -135,23 +135,22 @@ newpage(int clear, Segment **s, ulong va) break; unlock(&palloc); - dontalloc = 0; - if(s && *s) { + if(s) qunlock(&((*s)->lk)); - *s = 0; - dontalloc = 1; - } - qlock(&palloc.pwait); /* Hold memory requesters here */ - while(waserror()) /* Ignore interrupts */ - ; + if(!waserror()){ + eqlock(&palloc.pwait); /* Hold memory requesters here */ - kickpager(); - tsleep(&palloc.r, ispages, 0, 1000); + if(!waserror()){ + kickpager(); + tsleep(&palloc.r, ispages, 0, 1000); + poperror(); + } - poperror(); + qunlock(&palloc.pwait); - qunlock(&palloc.pwait); + poperror(); + } /* * If called from fault and we lost the segment from @@ -159,8 +158,10 @@ newpage(int clear, Segment **s, ulong va) * a page. Fault will call newpage again when it has * reacquired the segment locks */ - if(dontalloc) + if(s){ + *s = 0; return 0; + } lock(&palloc); } |