On Fri, May 08, 2015 at 12:34 +0200, Mike Belopuhov wrote: > > I think tsleep(9) and msleep(9) need to release and re-acquire the > > kernel lock in the "cold || panicstr" case. > > Well, it's not hard to do really, but... > > > We might need this for > > handling interrupts during autoconf as soon as we start distributing > > interrupts over CPUs. > > > > ...cold might mean that interrupts are not ready yet. So then we might > need another flag for shutdown?
This is what I have come up with. Chunks were taken directly from mi_switch and it seems to do the job just fine. Right now I'm not using any additional flags and it seems to work here. I'll resume testing on Monday, but it looks fairly complete. Any comments? diff --git sys/kern/kern_synch.c sys/kern/kern_synch.c index 03308b4..4089adf 100644 --- sys/kern/kern_synch.c +++ sys/kern/kern_synch.c @@ -103,10 +103,13 @@ extern int safepri; int tsleep(const volatile void *ident, int priority, const char *wmesg, int timo) { struct sleep_state sls; int error, error1; +#ifdef MULTIPROCESSOR + int hold_count; +#endif KASSERT((priority & ~(PRIMASK | PCATCH)) == 0); #ifdef MULTIPROCESSOR KASSERT(timo || __mp_lock_held(&kernel_lock)); @@ -120,10 +123,18 @@ tsleep(const volatile void *ident, int priority, const char *wmesg, int timo) * don't run any other procs or panic below, * in case this is the idle process and already asleep. */ s = splhigh(); splx(safepri); +#ifdef MULTIPROCESSOR + if (__mp_lock_held(&kernel_lock)) + hold_count = __mp_release_all(&kernel_lock); + else + hold_count = 0; + if (hold_count) + __mp_acquire_count(&kernel_lock, hold_count); +#endif splx(s); return (0); } sleep_setup(&sls, ident, priority, wmesg); @@ -149,10 +160,13 @@ int msleep(const volatile void *ident, struct mutex *mtx, int priority, const char *wmesg, int timo) { struct sleep_state sls; int error, error1, spl; +#ifdef MULTIPROCESSOR + int hold_count; +#endif KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0); KASSERT(mtx != NULL); if (cold || panicstr) { @@ -163,10 +177,18 @@ msleep(const volatile void *ident, struct mutex *mtx, int priority, * in case this is the idle process and already asleep. */ spl = MUTEX_OLDIPL(mtx); MUTEX_OLDIPL(mtx) = safepri; mtx_leave(mtx); +#ifdef MULTIPROCESSOR + if (__mp_lock_held(&kernel_lock)) + hold_count = __mp_release_all(&kernel_lock); + else + hold_count = 0; + if (hold_count) + __mp_acquire_count(&kernel_lock, hold_count); +#endif if ((priority & PNORELOCK) == 0) { mtx_enter(mtx); MUTEX_OLDIPL(mtx) = spl; } else splx(spl); diff --git sys/kern/vfs_subr.c sys/kern/vfs_subr.c index a26fbe2..a373789 100644 --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -1664,10 +1664,13 @@ int vfs_syncwait(int verbose) { struct buf *bp; int iter, nbusy, dcount, s; struct proc *p; +#ifdef MULTIPROCESSOR + int hold_count; +#endif p = curproc? curproc : &proc0; sys_sync(p, (void *)0, (register_t *)0); /* Wait for sync to finish. */ @@ -1698,11 +1701,21 @@ vfs_syncwait(int verbose) } if (nbusy == 0) break; if (verbose) printf("%d ", nbusy); +#ifdef MULTIPROCESSOR + if (__mp_lock_held(&kernel_lock)) + hold_count = __mp_release_all(&kernel_lock); + else + hold_count = 0; +#endif DELAY(40000 * iter); +#ifdef MULTIPROCESSOR + if (hold_count) + __mp_acquire_count(&kernel_lock, hold_count); +#endif } return nbusy; }