code: plan9front

Download patch

ref: e38d42b4a7f278a7f7835e07983115e4ee1b0db4
parent: 16c1cc99ec6db23f8d7b056127c77a4dcf14f2b5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Jan 3 23:49:33 EST 2024

kernel: handle errors in semacquire

Move waserror()/poperror() out of the loop,
so we can also catch errors from canacquire().

This is theoretically possible if memory has
been paged out and we get I/O errors when
trying to page it back in.

--- a/sys/src/9/port/segment.c
+++ b/sys/src/9/port/segment.c
@@ -109,6 +109,9 @@
 	} else if(decref(s) != 0)
 		return;
 
+	assert(s->sema.prev == &s->sema);
+	assert(s->sema.next = &s->sema);
+
 	if(s->mapsize > 0){
 		emap = &s->map[s->mapsize];
 		for(pte = s->map; pte < emap; pte++)
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -236,7 +236,6 @@
 	wm = up->wired;
 	if(wm != nil)
 		procwired(p, wm->machno);
-	p->psstate = nil;
 	ready(p);
 	sched();
 	return pid;
@@ -1141,19 +1140,15 @@
 		return 1;
 	if(!block)
 		return 0;
-
-	acquired = 0;
 	semqueue(s, addr, &phore);
-	for(;;){
-		phore.waiting = 1;
-		coherence();
-		if(canacquire(addr)){
-			acquired = 1;
-			break;
+	if(acquired = !waserror()){
+		for(;;){
+			phore.waiting = 1;
+			coherence();
+			if(canacquire(addr))
+				break;
+			sleep(&phore, semawoke, &phore);
 		}
-		if(waserror())
-			break;
-		sleep(&phore, semawoke, &phore);
 		poperror();
 	}
 	semdequeue(s, &phore);
@@ -1169,7 +1164,7 @@
 static int
 tsemacquire(Segment *s, long *addr, ulong ms)
 {
-	int acquired, timedout;
+	int timedout, acquired;
 	ulong t;
 	Sema phore;
 
@@ -1177,36 +1172,32 @@
 		return 1;
 	if(ms == 0)
 		return 0;
-	acquired = timedout = 0;
+	timedout = 0;
 	semqueue(s, addr, &phore);
-	for(;;){
-		phore.waiting = 1;
-		coherence();
-		if(canacquire(addr)){
-			acquired = 1;
-			break;
+	if(acquired = !waserror()){
+		for(;;){
+			phore.waiting = 1;
+			coherence();
+			if(canacquire(addr))
+				break;
+			t = MACHP(0)->ticks;
+			tsleep(&phore, semawoke, &phore, ms);
+			t = TK2MS(MACHP(0)->ticks - t);
+			if(t >= ms){
+				timedout = 1;
+				break;
+			}
+			ms -= t;
 		}
-		if(waserror())
-			break;
-		t = MACHP(0)->ticks;
-		tsleep(&phore, semawoke, &phore, ms);
-		t = TK2MS(MACHP(0)->ticks - t);
 		poperror();
-		if(t >= ms){
-			timedout = 1;
-			break;
-		}
-		ms -= t;
 	}
 	semdequeue(s, &phore);
 	coherence();	/* not strictly necessary due to lock in semdequeue */
 	if(!phore.waiting)
 		semwakeup(s, addr, 1);
-	if(timedout)
-		return 0;
 	if(!acquired)
 		nexterror();
-	return 1;
+	return !timedout;
 }
 
 uintptr