summaryrefslogtreecommitdiff
path: root/sys/src/9/port/page.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-08-24 14:43:15 +0200
committercinap_lenrek <cinap_lenrek@localhost>2011-08-24 14:43:15 +0200
commitcf974eb852cb316772b2294a80069dd8f99e19e9 (patch)
treeaac0418fb930417426b850bca7a1ace709acce78 /sys/src/9/port/page.c
parent61a0117ea5ddf0a17079faf755b4d51cc045c4ae (diff)
fix kernel: pio()/mfreeseg() race
Diffstat (limited to 'sys/src/9/port/page.c')
-rw-r--r--sys/src/9/port/page.c29
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);
}