diff --git a/sys/src/kern/amd64/syscall.c b/sys/src/kern/amd64/syscall.c index 33a2b9e..a44453a 100644 --- a/sys/src/kern/amd64/syscall.c +++ b/sys/src/kern/amd64/syscall.c @@ -238,6 +238,7 @@ syscall(Syscalls scallnr, Ureg* ureg) m->syscall++; up->inkernel = 1; up->cursyscall = (Syscalls)scallnr; + up->blockingsc = 0; up->pc = ureg->ip; up->dbgreg = ureg; if(up->trace && (pt = proctrace) != nil) @@ -354,8 +355,13 @@ syscall(Syscalls scallnr, Ureg* ureg) splhi(); if(scallnr != SysRfork && (up->procctl || up->nnote)) notify(ureg); - else if(canwakeup(scallnr)) - awokeproc(up); + else if(up->blockingsc){ + if(up->blockingsc != scallnr) + panic("syscall: up->blockingsc dirty"); + if(canwakeup(scallnr)) + awokeproc(up); + up->blockingsc = 0; + } /* if we delayed sched because we held a lock, sched now */ if(up->delaysched){ diff --git a/sys/src/kern/port/awake.c b/sys/src/kern/port/awake.c index 96e7bc7..7a09356 100644 --- a/sys/src/kern/port/awake.c +++ b/sys/src/kern/port/awake.c @@ -43,10 +43,9 @@ static Rendez awaker; int canwakeup(Syscalls scall) { - if(scall == 0){ - /* on page fault */ - return 0; - } + if(scall == 0) + panic("canwakeup on page fault"); + switch(scall){ default: panic("canwakeup: unknown scall %d\n", scall); diff --git a/sys/src/kern/port/portdat.h b/sys/src/kern/port/portdat.h index dcd5316..729a24d 100644 --- a/sys/src/kern/port/portdat.h +++ b/sys/src/kern/port/portdat.h @@ -610,6 +610,9 @@ struct Proc int inkernel; /* either on syscall or fault */ Syscalls cursyscall; /* zero on fault */ + Syscalls blockingsc; /* set to cursyscall on sleep() and sysrendevouz + * reset by syscall + */ int32_t blockingfd; /* fd currenly read/written */ diff --git a/sys/src/kern/port/portfns.h b/sys/src/kern/port/portfns.h index 6a421f0..a4312aa 100644 --- a/sys/src/kern/port/portfns.h +++ b/sys/src/kern/port/portfns.h @@ -33,7 +33,7 @@ int anyhigher(void); int anyready(void); void awakekproc(void*); #define awokeproc(p) (p->lastWakeup = p->pendingWakeup) -#define awakeOnBlock(p) (p->lastWakeup < p->pendingWakeup) +#define awakeOnBlock(p) (p->blockingsc && p->lastWakeup < p->pendingWakeup) Block* bl2mem(uint8_t*, Block*, int); int blocklen(Block*); void bootlinks(void); diff --git a/sys/src/kern/port/proc.c b/sys/src/kern/port/proc.c index b3e3b29..6ea1542 100644 --- a/sys/src/kern/port/proc.c +++ b/sys/src/kern/port/proc.c @@ -712,6 +712,7 @@ sleep(Rendez *r, int (*f)(void*), void *arg) */ r->p = up; + up->blockingsc = up->cursyscall; if((*f)(arg) || (up->notepending && !up->notedeferred) || (up->inkernel && awakeOnBlock(up) && canwakeup(up->cursyscall))){ diff --git a/sys/src/kern/port/sysproc.c b/sys/src/kern/port/sysproc.c index 94c2679..e742a9d 100644 --- a/sys/src/kern/port/sysproc.c +++ b/sys/src/kern/port/sysproc.c @@ -839,6 +839,7 @@ sysrendezvous(void* tagp, void* rendvalp) l = &p->rendhash; } + up->blockingsc = up->cursyscall; if(awakeOnBlock(up)){ unlock(&up->rgrp->l); result = UINT2PTR(up->rendval);