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.
This commit is contained in:
cinap_lenrek 2024-01-04 04:49:33 +00:00
parent 16c1cc99ec
commit e38d42b4a7
2 changed files with 27 additions and 33 deletions

View file

@ -109,6 +109,9 @@ putseg(Segment *s)
} else if(decref(s) != 0) } else if(decref(s) != 0)
return; return;
assert(s->sema.prev == &s->sema);
assert(s->sema.next = &s->sema);
if(s->mapsize > 0){ if(s->mapsize > 0){
emap = &s->map[s->mapsize]; emap = &s->map[s->mapsize];
for(pte = s->map; pte < emap; pte++) for(pte = s->map; pte < emap; pte++)

View file

@ -236,7 +236,6 @@ sysrfork(va_list list)
wm = up->wired; wm = up->wired;
if(wm != nil) if(wm != nil)
procwired(p, wm->machno); procwired(p, wm->machno);
p->psstate = nil;
ready(p); ready(p);
sched(); sched();
return pid; return pid;
@ -1141,19 +1140,15 @@ semacquire(Segment *s, long *addr, int block)
return 1; return 1;
if(!block) if(!block)
return 0; return 0;
acquired = 0;
semqueue(s, addr, &phore); semqueue(s, addr, &phore);
for(;;){ if(acquired = !waserror()){
phore.waiting = 1; for(;;){
coherence(); phore.waiting = 1;
if(canacquire(addr)){ coherence();
acquired = 1; if(canacquire(addr))
break; break;
sleep(&phore, semawoke, &phore);
} }
if(waserror())
break;
sleep(&phore, semawoke, &phore);
poperror(); poperror();
} }
semdequeue(s, &phore); semdequeue(s, &phore);
@ -1169,7 +1164,7 @@ semacquire(Segment *s, long *addr, int block)
static int static int
tsemacquire(Segment *s, long *addr, ulong ms) tsemacquire(Segment *s, long *addr, ulong ms)
{ {
int acquired, timedout; int timedout, acquired;
ulong t; ulong t;
Sema phore; Sema phore;
@ -1177,36 +1172,32 @@ tsemacquire(Segment *s, long *addr, ulong ms)
return 1; return 1;
if(ms == 0) if(ms == 0)
return 0; return 0;
acquired = timedout = 0; timedout = 0;
semqueue(s, addr, &phore); semqueue(s, addr, &phore);
for(;;){ if(acquired = !waserror()){
phore.waiting = 1; for(;;){
coherence(); phore.waiting = 1;
if(canacquire(addr)){ coherence();
acquired = 1; if(canacquire(addr))
break; 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(); poperror();
if(t >= ms){
timedout = 1;
break;
}
ms -= t;
} }
semdequeue(s, &phore); semdequeue(s, &phore);
coherence(); /* not strictly necessary due to lock in semdequeue */ coherence(); /* not strictly necessary due to lock in semdequeue */
if(!phore.waiting) if(!phore.waiting)
semwakeup(s, addr, 1); semwakeup(s, addr, 1);
if(timedout)
return 0;
if(!acquired) if(!acquired)
nexterror(); nexterror();
return 1; return !timedout;
} }
uintptr uintptr