diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -636,7 +636,15 @@ free(ih, M_ITHREAD); return (EINVAL); } + /* We can't mix sleepable and non-sleepable handlers and events */ + if (((flags & INTR_SLEEPABLE) == 0) != ((ie->ie_flags & IE_SLEEPABLE) == 0)) { + mtx_unlock(&ie->ie_lock); + free(ih, M_ITHREAD); + return (EINVAL); + } } + if (flags & INTR_SLEEPABLE) + ie->ie_flags |= IE_SLEEPABLE; /* Create a thread if we need one. */ while (ie->ie_thread == NULL && handler != NULL) { @@ -1191,10 +1199,10 @@ { /* Interrupt handlers should not sleep. */ - if (!(ie->ie_flags & IE_SOFT)) + if (!(ie->ie_flags & (IE_SOFT | IE_SLEEPABLE))) THREAD_NO_SLEEPING(); intr_event_execute_handlers(p, ie); - if (!(ie->ie_flags & IE_SOFT)) + if (!(ie->ie_flags & (IE_SOFT | IE_SLEEPABLE))) THREAD_SLEEPING_OK(); /* diff --git a/sys/sys/bus.h b/sys/sys/bus.h --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -280,7 +280,8 @@ INTR_MD1 = 4096, /* flag reserved for MD use */ INTR_MD2 = 8192, /* flag reserved for MD use */ INTR_MD3 = 16384, /* flag reserved for MD use */ - INTR_MD4 = 32768 /* flag reserved for MD use */ + INTR_MD4 = 32768, /* flag reserved for MD use */ + INTR_SLEEPABLE = 65536 }; enum intr_trigger { diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h --- a/sys/sys/interrupt.h +++ b/sys/sys/interrupt.h @@ -129,6 +129,7 @@ /* Interrupt event flags kept in ie_flags. */ #define IE_SOFT 0x000001 /* Software interrupt. */ +#define IE_SLEEPABLE 0x000002 /* Sleepable ithread */ #define IE_ADDING_THREAD 0x000004 /* Currently building an ithread. */ /* Flags to pass to swi_sched. */