diff --git a/sys/src/kern/port/awake.c b/sys/src/kern/port/awake.c index e6f211d..f9bee72 100644 --- a/sys/src/kern/port/awake.c +++ b/sys/src/kern/port/awake.c @@ -54,6 +54,10 @@ static AlarmPool awkpool; static AwakeAlarm *registry; static Lock rl; +enum +{ + AwakeDisabled = 64, /* must be greater than all syscalls */ +}; typedef enum ElapsedAlarmFate { @@ -146,6 +150,8 @@ awake_can_interrupt(Syscalls scall) { if(scall == 0) panic("awake_can_interrupts on page fault"); + if(scall == (Syscalls)AwakeDisabled) + return 0; if(scall >= nelem(awakeable_syscalls) - 1) panic("awake_can_interrupts: unknown syscall %d", scall); return awakeable_syscalls[scall]; @@ -153,7 +159,7 @@ awake_can_interrupt(Syscalls scall) #else # define awake_detect_loop(h) -# define awake_can_interrupt(scall) (awakeable_syscalls[scall]) +# define awake_can_interrupt(scall) (scall != (Syscalls)AwakeDisabled && awakeable_syscalls[scall]) //# undef assert //# define assert(a) #endif @@ -230,6 +236,8 @@ void awake_fell_asleep(Proc *p) { Syscalls cs = p->cursyscall; + if(p->wakeups[p->notified].blockingsc == (Syscalls)AwakeDisabled) + return; if(cs != 0 && cs != SysAwake){ /* awake_register might sleep() on alarm_new and we * don't want this sleep to be interrupted. @@ -243,7 +251,7 @@ Syscalls awake_disable(void) { Syscalls blockingsc = up->wakeups[up->notified].blockingsc; - up->wakeups[up->notified].blockingsc = 0; + up->wakeups[up->notified].blockingsc = AwakeDisabled; return blockingsc; } void diff --git a/sys/src/kern/port/dev9p.c b/sys/src/kern/port/dev9p.c index 8765057..e3410eb 100644 --- a/sys/src/kern/port/dev9p.c +++ b/sys/src/kern/port/dev9p.c @@ -1,3 +1,20 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2015-2017 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ #include "u.h" #include "../port/lib.h" #include "mem.h" @@ -807,6 +824,7 @@ mountio(Mnt *mnt, Mntrpc *r) int n; Syscalls awksysc; + awksysc = 0; while(waserror()) { if(mnt->rip == up) mntgate(mnt); @@ -847,6 +865,23 @@ mountio(Mnt *mnt, Mntrpc *r) } b->wp += n; poperror(); + + if(r->request.type == Tflush){ + /* Tflush must not be interrupted by awake. + * + * The following code might call sleep() but it must + * since the syscall has already been interrupted + * (or we would not have to send a Tflush) awake must + * not interrupt such sleep. + * + * Thus we disable awake otherwise we will consume all + * tags trying to flush the flush. + * + * TODO: verify we do not have to do the same + * with notes + */ + awksysc = awake_disable(); + } mnt->c->dev->bwrite(mnt->c, b, 0); /* Gate readers onto the mount point one at a time */ @@ -855,29 +890,10 @@ mountio(Mnt *mnt, Mntrpc *r) if(mnt->rip == nil) break; unlock(&mnt->l); - if(r->request.type == Tflush){ - /* Tflush must not be interrupted by awake - * or we will consume all tags trying: since - * awake cannot know that it's not worth to - * flush an interrupted flush it will interrupt - * them all and each interrupt will cause - * a new flush to be sent. - * - * TODO: verify we do not have to do the same - * with notes - */ - awksysc = awake_disable(); - if(waserror()){ - awake_enable(awksysc); - nexterror(); - } - } sleep(r->z, rpcattn, r); - if(r->request.type == Tflush){ - awake_enable(awksysc); - poperror(); - } if(r->done){ + if(r->request.type == Tflush) + awake_enable(awksysc); poperror(); mntflushfree(mnt, r); return; @@ -890,6 +906,9 @@ mountio(Mnt *mnt, Mntrpc *r) error(Emountrpc); mountmux(mnt, r); } + if(r->request.type == Tflush) + awake_enable(awksysc); + mntgate(mnt); poperror(); mntflushfree(mnt, r);