git: 9front

Download patch

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);
 	}
--