git: 0863dc10354f - main - ithread: Allow some ithreads to sleep
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 24 Jan 2025 15:08:25 UTC
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=0863dc10354ff458a3ddf8ef3b47044d7a615154 commit 0863dc10354ff458a3ddf8ef3b47044d7a615154 Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2025-01-13 05:35:27 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2025-01-24 15:08:09 +0000 ithread: Allow some ithreads to sleep Some ithreads need to hold a sleep mutex, e.g. when calling ACPI methods. Allow ithreads to be marked as sleepable when this is known to be safe. Reviewed by: markj, jhb Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D48283 --- share/man/man9/intr_event.9 | 10 +++++++++- sys/kern/kern_intr.c | 18 +++++++++++++----- sys/sys/bus.h | 1 + sys/sys/interrupt.h | 1 + 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/share/man/man9/intr_event.9 b/share/man/man9/intr_event.9 index d1964ce289a5..ba8faf877e6a 100644 --- a/share/man/man9/intr_event.9 +++ b/share/man/man9/intr_event.9 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 30, 2022 +.Dd January 24, 2025 .Dt INTR_EVENT 9 .Os .Sh NAME @@ -295,6 +295,14 @@ from the handler's source triggers. Presently, the .Dv INTR_ENTROPY flag is not valid for software interrupt handlers. +The +.Dv INTR_SLEEPABLE +flag specifies that the interrupt ithread may sleep. +Presently, the +.Dv INTR_SLEEPABLE +flag requires the +.Dv INTR_EXCL +flag to be set. .Ss Handler Callbacks Each .Vt struct intr_event diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index ad0cc135167e..4ef37ac829b3 100644 --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -610,6 +610,12 @@ intr_event_add_handler(struct intr_event *ie, const char *name, if (ie == NULL || name == NULL || (handler == NULL && filter == NULL)) return (EINVAL); + if ((flags & INTR_SLEEPABLE) != 0 && (flags & INTR_EXCL) == 0) { + printf("%s: INTR_SLEEPABLE requires INTR_EXCL to be set\n", + __func__); + return (EINVAL); + } + /* Allocate and populate an interrupt handler structure. */ ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO); ih->ih_filter = filter; @@ -627,16 +633,18 @@ intr_event_add_handler(struct intr_event *ie, const char *name, if (flags & INTR_TYPE_NET) ih->ih_flags |= IH_NET; - /* We can only have one exclusive handler in a event. */ + /* We can only have one exclusive or sleepable handler in a event. */ mtx_lock(&ie->ie_lock); if (!CK_SLIST_EMPTY(&ie->ie_handlers)) { - if ((flags & INTR_EXCL) || + if ((flags & (INTR_EXCL | INTR_SLEEPABLE)) || (CK_SLIST_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) { 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) { @@ -1190,11 +1198,11 @@ static void ithread_execute_handlers(struct proc *p, struct intr_event *ie) { - /* Interrupt handlers should not sleep. */ - if (!(ie->ie_flags & IE_SOFT)) + /* Only specifically marked sleepable interrupt handlers can sleep. */ + 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 index 8b32e10f1285..84df9e6956d3 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -277,6 +277,7 @@ enum intr_type { INTR_EXCL = 256, /* exclusive interrupt */ INTR_MPSAFE = 512, /* this interrupt is SMP safe */ INTR_ENTROPY = 1024, /* this interrupt provides entropy */ + INTR_SLEEPABLE = 2048, /* this interrupt handler can sleep */ INTR_MD1 = 4096, /* flag reserved for MD use */ INTR_MD2 = 8192, /* flag reserved for MD use */ INTR_MD3 = 16384, /* flag reserved for MD use */ diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h index 899d65e386e0..2e84faa78e38 100644 --- a/sys/sys/interrupt.h +++ b/sys/sys/interrupt.h @@ -129,6 +129,7 @@ struct intr_event { /* 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. */