mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
fix kernel: pio()/mfreeseg() race
This commit is contained in:
parent
61a0117ea5
commit
cf974eb852
2 changed files with 39 additions and 19 deletions
|
@ -10,18 +10,21 @@ fault(ulong addr, int read)
|
|||
{
|
||||
Segment *s;
|
||||
char *sps;
|
||||
int pnd;
|
||||
|
||||
if(up == nil)
|
||||
panic("fault: nil up");
|
||||
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 @@ fault(ulong addr, int read)
|
|||
|
||||
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 @@ retry:
|
|||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
if(!waserror()){
|
||||
eqlock(&palloc.pwait); /* Hold memory requesters here */
|
||||
|
||||
if(!waserror()){
|
||||
kickpager();
|
||||
tsleep(&palloc.r, ispages, 0, 1000);
|
||||
poperror();
|
||||
}
|
||||
|
||||
qunlock(&palloc.pwait);
|
||||
|
||||
poperror();
|
||||
}
|
||||
qlock(&palloc.pwait); /* Hold memory requesters here */
|
||||
|
||||
while(waserror()) /* Ignore interrupts */
|
||||
;
|
||||
|
||||
kickpager();
|
||||
tsleep(&palloc.r, ispages, 0, 1000);
|
||||
|
||||
poperror();
|
||||
|
||||
qunlock(&palloc.pwait);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue