ref: 4449d25bd744662c115162c9fda50560a8b931b1
parent: aa5b72a65e85e8e73313ebce1b52c8806edd5a9b
author: cinap_lenrek <cinap_lenrek@localhost>
date: Wed Aug 24 10:43:15 EDT 2011
fix kernel: pio()/mfreeseg() race
--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -10,6 +10,7 @@
{Segment *s;
char *sps;
+ int pnd;
if(up == nil)
panic("fault: nil up");@@ -16,12 +17,14 @@
if(up->nlocks.ref)
print("fault: nlocks %ld\n", up->nlocks.ref);+ pnd = up->notepending;
sps = up->psstate;
up->psstate = "Fault";
- spllo();
m->pfault++;
for(;;) {+ spllo();
+
s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */
if(s == 0) {up->psstate = sps;
@@ -36,9 +39,18 @@
if(fixfault(s, addr, read, 1) == 0)
break;
+
+ splhi();
+ switch(up->procctl){+ case Proc_exitme:
+ case Proc_exitbig:
+ procctl(up);
+ }
}
up->psstate = sps;
+ up->notepending |= pnd;
+
return 0;
}
@@ -267,10 +279,17 @@
/* another process did it for me */
putpage(new);
goto done;
- } else {+ } else if(*p) {/* another process and the pager got in */
putpage(new);
goto retry;
+ } else {+ /* another process segfreed the page */
+ k = kmap(new);
+ memset((void*)VA(k), 0, ask);
+ kunmap(k);
+ *p = new;
+ goto done;
}
}
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -123,7 +123,7 @@
Page *p;
KMap *k;
uchar ct;
- int i, hw, dontalloc, color;
+ int i, hw, color;
lock(&palloc);
color = getpgcolor(va);
@@ -135,23 +135,22 @@
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 @@
* a page. Fault will call newpage again when it has
* reacquired the segment locks
*/
- if(dontalloc)
+ if(s){+ *s = 0;
return 0;
+ }
lock(&palloc);
}
--
⑨