Index: alpha/alpha/interrupt.c =================================================================== RCS file: /usr/cvs/src/sys/alpha/alpha/interrupt.c,v retrieving revision 1.86.2.1 diff -u -r1.86.2.1 interrupt.c --- alpha/alpha/interrupt.c 6 Oct 2005 20:18:20 -0000 1.86.2.1 +++ alpha/alpha/interrupt.c 2 Mar 2006 15:51:07 -0000 @@ -325,8 +325,9 @@ struct alpha_intr { LIST_ENTRY(alpha_intr) list; /* chain handlers in this hash bucket */ uintptr_t vector; /* vector to match */ - struct ithd *ithd; /* interrupt thread */ + struct intr_event *ie; /* interrupt event structure */ volatile long *cntp; /* interrupt counter */ + void (*disable)(uintptr_t); }; static struct mtx alpha_intr_hash_lock; @@ -338,7 +339,7 @@ ithds_init(void *dummy) { - mtx_init(&alpha_intr_hash_lock, "ithread table lock", NULL, MTX_SPIN); + mtx_init(&alpha_intr_hash_lock, "intr table", NULL, MTX_SPIN); } SYSINIT(ithds_init, SI_SUB_INTR, SI_ORDER_SECOND, ithds_init, NULL); @@ -371,8 +372,9 @@ return ENOMEM; i->vector = vector; i->cntp = cntp; - errcode = ithread_create(&i->ithd, vector, 0, disable, enable, - "intr:"); + i->disable = disable; + errcode = intr_event_create(&i->ie, (void *)vector, 0, + (void (*)(void *))enable, "intr:"); if (errcode) { free(i, M_DEVBUF); return errcode; @@ -384,44 +386,49 @@ } /* Second, add this handler. */ - return (ithread_add_handler(i->ithd, name, handler, arg, - ithread_priority(flags), flags, cookiep)); + return (intr_event_add_handler(i->ie, name, handler, arg, + intr_priority(flags), flags, cookiep)); } int alpha_teardown_intr(void *cookie) { - return (ithread_remove_handler(cookie)); + return (intr_event_remove_handler(cookie)); } +/* + * XXX: Alpha doesn't count stray interrupts like some of the other archs. + */ void alpha_dispatch_intr(void *frame, unsigned long vector) { int h = HASHVEC(vector); struct alpha_intr *i; - struct ithd *ithd; /* our interrupt thread */ - struct intrhand *ih; - int error; + struct intr_event *ie; + struct intr_handler *ih; + int error, thread; /* * Walk the hash bucket for this vector looking for this vector's - * interrupt thread. + * interrupt structure. */ for (i = LIST_FIRST(&alpha_intr_hash[h]); i && i->vector != vector; i = LIST_NEXT(i, list)) ; /* nothing */ + + /* No interrupt structure for this vector. */ if (i == NULL) - return; /* no ithread for this vector */ + return; - ithd = i->ithd; - KASSERT(ithd != NULL, ("interrupt vector without a thread")); + ie = i->ie; + KASSERT(ie != NULL, ("interrupt structure without an event")); /* - * As an optimization, if an ithread has no handlers, don't + * As an optimization, if an event has no handlers, don't * schedule it to run. */ - if (TAILQ_EMPTY(&ithd->it_handlers)) + if (TAILQ_EMPTY(&ie->ie_handlers)) return; atomic_add_long(i->cntp, 1); @@ -433,25 +440,32 @@ */ sched_pin(); + /* Execute all fast interrupt handlers directly. */ + thread = 0; + critical_enter(); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) { + thread = 1; + continue; + } + CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, + ih->ih_handler, ih->ih_argument, ih->ih_name); + ih->ih_handler(ih->ih_argument); + } + critical_exit(); + /* - * Handle a fast interrupt if there is no actual thread for this - * interrupt by calling the handler directly without Giant. Note - * that this means that any fast interrupt handler must be MP safe. + * If the ithread needs to run, disable the source and schedule the + * thread. */ - ih = TAILQ_FIRST(&ithd->it_handlers); - if ((ih->ih_flags & IH_FAST) != 0) { - critical_enter(); - ih->ih_handler(ih->ih_argument); - critical_exit(); - } else { - if (ithd->it_disable) { + if (thread) { + if (i->disable) { CTR1(KTR_INTR, "alpha_dispatch_intr: disabling vector 0x%x", i->vector); - ithd->it_disable(ithd->it_vector); + i->disable(i->vector); } - - error = ithread_schedule(ithd); + error = intr_event_schedule_thread(ie); KASSERT(error == 0, ("got an impossible stray interrupt")); } sched_unpin(); Index: alpha/isa/isa.c =================================================================== RCS file: /usr/cvs/src/sys/alpha/isa/isa.c,v retrieving revision 1.36 diff -u -r1.36 isa.c --- alpha/isa/isa.c 1 Jul 2004 15:07:26 -0000 1.36 +++ alpha/isa/isa.c 2 Mar 2006 15:51:07 -0000 @@ -390,14 +390,14 @@ struct resource *irq, void *cookie) { struct isa_intr *ii = cookie; - struct intrhand *ih, *handler = (struct intrhand *)ii->ih; - struct ithd *ithread = handler->ih_ithread; + struct intr_handler *ih, *handler = (struct intr_handler *)ii->ih; + struct intr_event *ie = handler->ih_event; int num_handlers = 0; - mtx_lock(&ithread->it_lock); - TAILQ_FOREACH(ih, &ithread->it_handlers, ih_next) + mtx_lock(&ie->ie_lock); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) num_handlers++; - mtx_unlock(&ithread->it_lock); + mtx_unlock(&ie->ie_lock); /* * Only disable the interrupt in hardware if there are no Index: amd64/amd64/intr_machdep.c =================================================================== RCS file: /usr/cvs/src/sys/amd64/amd64/intr_machdep.c,v retrieving revision 1.15.2.1 diff -u -r1.15.2.1 intr_machdep.c --- amd64/amd64/intr_machdep.c 7 Mar 2006 18:33:20 -0000 1.15.2.1 +++ amd64/amd64/intr_machdep.c 7 Mar 2006 19:52:05 -0000 @@ -57,7 +57,7 @@ #define MAX_STRAY_LOG 5 -typedef void (*mask_fn)(uintptr_t vector); +typedef void (*mask_fn)(void *); static int intrcnt_index; static struct intsrc *interrupt_sources[NUM_IO_INTS]; @@ -87,15 +87,14 @@ vector = isrc->is_pic->pic_vector(isrc); if (interrupt_sources[vector] != NULL) return (EEXIST); - error = ithread_create(&isrc->is_ithread, (uintptr_t)isrc, 0, - (mask_fn)isrc->is_pic->pic_disable_source, + error = intr_event_create(&isrc->is_event, isrc, 0, (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector); if (error) return (error); mtx_lock_spin(&intr_table_lock); if (interrupt_sources[vector] != NULL) { mtx_unlock_spin(&intr_table_lock); - ithread_destroy(isrc->is_ithread); + intr_event_destroy(isrc->is_event); return (EEXIST); } intrcnt_register(isrc); @@ -122,8 +121,8 @@ isrc = intr_lookup_source(vector); if (isrc == NULL) return (EINVAL); - error = ithread_add_handler(isrc->is_ithread, name, handler, arg, - ithread_priority(flags), flags, cookiep); + error = intr_event_add_handler(isrc->is_event, name, handler, arg, + intr_priority(flags), flags, cookiep); if (error == 0) { intrcnt_updatename(isrc); mtx_lock_spin(&intr_table_lock); @@ -147,7 +146,7 @@ { int error; - error = ithread_remove_handler(cookie); + error = intr_event_remove_handler(cookie); #ifdef XXX if (error == 0) intrcnt_updatename(/* XXX */); @@ -170,12 +169,11 @@ intr_execute_handlers(struct intsrc *isrc, struct intrframe *iframe) { struct thread *td; - struct ithd *it; - struct intrhand *ih; - int error, vector; + struct intr_event *ie; + struct intr_handler *ih; + int error, vector, thread; td = curthread; - td->td_intr_nesting_level++; /* * We count software interrupts when we process them. The @@ -186,11 +184,7 @@ (*isrc->is_count)++; PCPU_LAZY_INC(cnt.v_intr); - it = isrc->is_ithread; - if (it == NULL) - ih = NULL; - else - ih = TAILQ_FIRST(&it->it_handlers); + ie = isrc->is_event; /* * XXX: We assume that IRQ 0 is only used for the ISA timer @@ -200,40 +194,12 @@ if (vector == 0) clkintr_pending = 1; - if (ih != NULL && ih->ih_flags & IH_FAST) { - /* - * Execute fast interrupt handlers directly. - * To support clock handlers, if a handler registers - * with a NULL argument, then we pass it a pointer to - * a trapframe as its argument. - */ - critical_enter(); - TAILQ_FOREACH(ih, &it->it_handlers, ih_next) { - MPASS(ih->ih_flags & IH_FAST); - CTR3(KTR_INTR, "%s: executing handler %p(%p)", - __func__, ih->ih_handler, - ih->ih_argument == NULL ? iframe : - ih->ih_argument); - if (ih->ih_argument == NULL) - ih->ih_handler(iframe); - else - ih->ih_handler(ih->ih_argument); - } - isrc->is_pic->pic_eoi_source(isrc); - error = 0; - critical_exit(); - } else { - /* - * For stray and threaded interrupts, we mask and EOI the - * source. - */ + /* + * For stray interrupts, mask and EOI the source, bump the + * stray count, and log the condition. + */ + if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) { isrc->is_pic->pic_disable_source(isrc, PIC_EOI); - if (ih == NULL) - error = EINVAL; - else - error = ithread_schedule(it); - } - if (error == EINVAL) { (*isrc->is_straycount)++; if (*isrc->is_straycount < MAX_STRAY_LOG) log(LOG_ERR, "stray irq%d\n", vector); @@ -241,6 +207,47 @@ log(LOG_CRIT, "too many stray irq %d's: not logging anymore\n", vector); + return; + } + + /* + * Execute fast interrupt handlers directly. + * To support clock handlers, if a handler registers + * with a NULL argument, then we pass it a pointer to + * an intrframe as its argument. + */ + td->td_intr_nesting_level++; + thread = 0; + critical_enter(); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) { + thread = 1; + continue; + } + CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, + ih->ih_handler, ih->ih_argument == NULL ? iframe : + ih->ih_argument, ih->ih_name); + if (ih->ih_argument == NULL) + ih->ih_handler(iframe); + else + ih->ih_handler(ih->ih_argument); + } + + /* + * If there are any threaded handlers that need to run, + * mask the source as well as sending it an EOI. Otherwise, + * just send it an EOI but leave it unmasked. + */ + if (thread) + isrc->is_pic->pic_disable_source(isrc, PIC_EOI); + else + isrc->is_pic->pic_eoi_source(isrc); + critical_exit(); + + /* Schedule the ithread if needed. */ + if (thread) { + error = intr_event_schedule_thread(ie); + KASSERT(error == 0, ("bad stray interrupt")); } td->td_intr_nesting_level--; } @@ -283,7 +290,7 @@ intrcnt_updatename(struct intsrc *is) { - intrcnt_setname(is->is_ithread->it_td->td_proc->p_comm, is->is_index); + intrcnt_setname(is->is_event->ie_fullname, is->is_index); } static void @@ -292,7 +299,7 @@ char straystr[MAXCOMLEN + 1]; /* mtx_assert(&intr_table_lock, MA_OWNED); */ - KASSERT(is->is_ithread != NULL, ("%s: isrc with no ithread", __func__)); + KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__)); is->is_index = intrcnt_index; intrcnt_index += 2; snprintf(straystr, MAXCOMLEN + 1, "stray irq%d", @@ -342,7 +349,7 @@ db_setup_paging(db_simple_pager, &quit, db_lines_per_page); for (i = 0; i < NUM_IO_INTS && !quit; i++, isrc++) if (*isrc != NULL) - db_dump_ithread((*isrc)->is_ithread, verbose); + db_dump_intr_event((*isrc)->is_event, verbose); } #endif Index: amd64/amd64/local_apic.c =================================================================== RCS file: /usr/cvs/src/sys/amd64/amd64/local_apic.c,v retrieving revision 1.17.2.5 diff -u -r1.17.2.5 local_apic.c --- amd64/amd64/local_apic.c 7 Mar 2006 18:33:20 -0000 1.17.2.5 +++ amd64/amd64/local_apic.c 7 Mar 2006 19:52:06 -0000 @@ -773,11 +773,9 @@ isrc = intr_lookup_source(irq); if (isrc == NULL || verbose == 0) db_printf("IRQ %u\n", irq); -#if 0 else db_dump_intr_event(isrc->is_event, verbose == 2); -#endif } else db_printf("IRQ %u ???\n", irq); } Index: amd64/include/intr_machdep.h =================================================================== RCS file: /usr/cvs/src/sys/amd64/include/intr_machdep.h,v retrieving revision 1.5.2.2 diff -u -r1.5.2.2 intr_machdep.h --- amd64/include/intr_machdep.h 7 Mar 2006 18:33:20 -0000 1.5.2.2 +++ amd64/include/intr_machdep.h 7 Mar 2006 19:52:07 -0000 @@ -102,7 +102,7 @@ */ struct intsrc { struct pic *is_pic; - struct ithd *is_ithread; + struct intr_event *is_event; u_long *is_count; u_long *is_straycount; u_int is_index; Index: amd64/isa/atpic.c =================================================================== RCS file: /usr/cvs/src/sys/amd64/isa/atpic.c,v retrieving revision 1.15.2.2 diff -u -r1.15.2.2 atpic.c --- amd64/isa/atpic.c 7 Mar 2006 18:33:21 -0000 1.15.2.2 +++ amd64/isa/atpic.c 7 Mar 2006 19:52:08 -0000 @@ -499,10 +499,10 @@ isrc = &atintrs[vec].at_intsrc; /* - * If we don't have an ithread, see if this is a spurious + * If we don't have an event, see if this is a spurious * interrupt. */ - if (isrc->is_ithread == NULL && (vec == 7 || vec == 15)) { + if (isrc->is_event == NULL && (vec == 7 || vec == 15)) { int port, isr; /* Index: arm/arm/intr.c =================================================================== RCS file: /usr/cvs/src/sys/arm/arm/intr.c,v retrieving revision 1.9 diff -u -r1.9 intr.c --- arm/arm/intr.c 9 Jun 2005 12:26:19 -0000 1.9 +++ arm/arm/intr.c 2 Mar 2006 15:53:19 -0000 @@ -50,7 +50,7 @@ #include #include -static struct ithd *ithreads[NIRQ]; +static struct intr_event *intr_events[NIRQ]; static int intrcnt_tab[NIRQ]; static int intrcnt_index = 0; static int last_printed = 0; @@ -61,18 +61,18 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg, int irq, int flags, void **cookiep) { - struct ithd *cur_ith; + struct intr_event *event; int error; if (irq < 0 || irq >= NIRQ) return; - cur_ith = ithreads[irq]; - if (cur_ith == NULL) { - error = ithread_create(&cur_ith, irq, 0, arm_mask_irq, - arm_unmask_irq, "intr%d:", irq); + event = intr_events[irq]; + if (event == NULL) { + error = intr_event_create(&event, (void *)irq, 0, + (void (*)(void *))arm_unmask_irq, "intr%d:", irq); if (error) return; - ithreads[irq] = cur_ith; + intr_events[irq] = event; last_printed += snprintf(intrnames + last_printed, MAXCOMLEN + 1, @@ -82,14 +82,14 @@ intrcnt_index++; } - ithread_add_handler(cur_ith, name, hand, arg, - ithread_priority(flags), flags, cookiep); + intr_event_add_handler(event, name, hand, arg, + intr_priority(flags), flags, cookiep); } int arm_remove_irqhandler(void *cookie) { - return (ithread_remove_handler(cookie)); + return (intr_event_remove_handler(cookie)); } void dosoftints(void); @@ -101,28 +101,34 @@ void arm_handler_execute(void *frame, int irqnb) { - struct ithd *ithd; - int i; - struct intrhand *ih; + struct intr_event *event; + struct intr_handler *ih; struct thread *td = curthread; + int i, thread; td->td_intr_nesting_level++; while ((i = arm_get_next_irq()) != -1) { + arm_mask_irq(i); intrcnt[intrcnt_tab[i]]++; - ithd = ithreads[i]; - if (!ithd) + event = intr_events[i]; + if (!event || TAILQ_EMPTY(&event->ie_handlers)) continue; - ih = TAILQ_FIRST(&ithd->it_handlers); - if (ih && ih->ih_flags & IH_FAST) { - TAILQ_FOREACH(ih, &ithd->it_handlers, - ih_next) { + + /* Execute fast handlers. */ + thread = 0; + TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) + thread = 1; + else ih->ih_handler(ih->ih_argument ? ih->ih_argument : frame); - } - } else if (ih) { - arm_mask_irq(i); - ithread_schedule(ithd); } + + /* Schedule thread if needed. */ + if (thread) + intr_event_schedule_thread(event); + else + arm_unmask_irq(i); } td->td_intr_nesting_level--; } Index: dev/cx/if_cx.c =================================================================== RCS file: /usr/cvs/src/sys/dev/cx/if_cx.c,v retrieving revision 1.45.2.1 diff -u -r1.45.2.1 if_cx.c --- dev/cx/if_cx.c 25 Aug 2005 05:01:07 -0000 1.45.2.1 +++ dev/cx/if_cx.c 2 Mar 2006 16:08:18 -0000 @@ -2546,7 +2546,7 @@ callout_init (&timeout_handle, cx_mpsafenet?CALLOUT_MPSAFE:0); callout_reset (&timeout_handle, hz*5, cx_timeout, 0); /* Software interrupt. */ - swi_add(&tty_ithd, "cx", cx_softintr, NULL, SWI_TTY, + swi_add(&tty_intr_event, "cx", cx_softintr, NULL, SWI_TTY, (cx_mpsafenet?INTR_MPSAFE:0), &cx_fast_ih); break; case MOD_UNLOAD: @@ -2559,7 +2559,7 @@ /* If we were wait it than it reasserted now, just stop it. */ if (!callout_drain (&timeout_handle)) callout_stop (&timeout_handle); - ithread_remove_handler (cx_fast_ih); + swi_remove (cx_fast_ih); --load_count; break; case MOD_SHUTDOWN: Index: dev/cy/cy.c =================================================================== RCS file: /usr/cvs/src/sys/dev/cy/cy.c,v retrieving revision 1.160 diff -u -r1.160 cy.c --- dev/cy/cy.c 5 Oct 2004 07:42:19 -0000 1.160 +++ dev/cy/cy.c 2 Mar 2006 16:07:37 -0000 @@ -428,9 +428,9 @@ splx(s); if (cy_fast_ih == NULL) { - swi_add(&tty_ithd, "cy", cypoll, NULL, SWI_TTY, 0, + swi_add(&tty_intr_event, "cy", cypoll, NULL, SWI_TTY, 0, &cy_fast_ih); - swi_add(&clk_ithd, "cy", cypoll, NULL, SWI_CLOCK, 0, + swi_add(&clk_intr_event, "cy", cypoll, NULL, SWI_CLOCK, 0, &cy_slow_ih); } ttycreate(tp, NULL, 0, MINOR_CALLOUT, "c%r%r", Index: dev/rc/rc.c =================================================================== RCS file: /usr/cvs/src/sys/dev/rc/rc.c,v retrieving revision 1.99 diff -u -r1.99 rc.c --- dev/rc/rc.c 6 Jan 2005 01:43:09 -0000 1.99 +++ dev/rc/rc.c 2 Mar 2006 16:08:18 -0000 @@ -311,7 +311,7 @@ goto fail; } - swi_add(&tty_ithd, "tty:rc", rc_pollcard, sc, SWI_TTY, 0, + swi_add(&tty_intr_event, "rc", rc_pollcard, sc, SWI_TTY, 0, &sc->sc_swicookie); return (0); @@ -336,7 +336,7 @@ error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie); if (error) device_printf(dev, "failed to deregister interrupt handler\n"); - ithread_remove_handler(sc->sc_swicookie); + swi_remove(sc->sc_swicookie); rc_release_resources(dev); return (0); Index: dev/sab/sab.c =================================================================== RCS file: /usr/cvs/src/sys/dev/sab/sab.c,v retrieving revision 1.39 diff -u -r1.39 sab.c --- dev/sab/sab.c 4 Jun 2005 20:29:28 -0000 1.39 +++ dev/sab/sab.c 2 Mar 2006 16:08:18 -0000 @@ -321,7 +321,7 @@ for (i = 0; i < SAB_NCHAN; i++) sc->sc_child[i] = device_get_softc(child[i]); - swi_add(&tty_ithd, "tty:sab", sab_softintr, sc, SWI_TTY, + swi_add(&tty_intr_event, "sab", sab_softintr, sc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); if (sabtty_cons != NULL) { Index: dev/sio/sio.c =================================================================== RCS file: /usr/cvs/src/sys/dev/sio/sio.c,v retrieving revision 1.459 diff -u -r1.459 sio.c --- dev/sio/sio.c 29 May 2005 04:42:25 -0000 1.459 +++ dev/sio/sio.c 2 Mar 2006 15:51:07 -0000 @@ -1055,9 +1055,9 @@ printf("\n"); if (sio_fast_ih == NULL) { - swi_add(&tty_ithd, "sio", siopoll, NULL, SWI_TTY, 0, + swi_add(&tty_intr_event, "sio", siopoll, NULL, SWI_TTY, 0, &sio_fast_ih); - swi_add(&clk_ithd, "sio", siopoll, NULL, SWI_CLOCK, 0, + swi_add(&clk_intr_event, "sio", siopoll, NULL, SWI_CLOCK, 0, &sio_slow_ih); } Index: dev/uart/uart_kbd_sun.c =================================================================== RCS file: /usr/cvs/src/sys/dev/uart/uart_kbd_sun.c,v retrieving revision 1.5 diff -u -r1.5 uart_kbd_sun.c --- dev/uart/uart_kbd_sun.c 4 Jun 2005 21:54:31 -0000 1.5 +++ dev/uart/uart_kbd_sun.c 2 Mar 2006 15:51:07 -0000 @@ -254,7 +254,7 @@ #endif sunkbd_enable(&sunkbd_softc.sc_kbd); - swi_add(&tty_ithd, uart_driver_name, sunkbd_uart_intr, + swi_add(&tty_intr_event, uart_driver_name, sunkbd_uart_intr, &sunkbd_softc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); sc->sc_opened = 1; Index: dev/uart/uart_tty.c =================================================================== RCS file: /usr/cvs/src/sys/dev/uart/uart_tty.c,v retrieving revision 1.22 diff -u -r1.22 uart_tty.c --- dev/uart/uart_tty.c 8 May 2005 20:25:09 -0000 1.22 +++ dev/uart/uart_tty.c 2 Mar 2006 16:03:41 -0000 @@ -377,7 +377,7 @@ ttyconsolemode(tp, 0); } - swi_add(&tty_ithd, uart_driver_name, uart_tty_intr, sc, SWI_TTY, + swi_add(&tty_intr_event, uart_driver_name, uart_tty_intr, sc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); ttycreate(tp, NULL, 0, MINOR_CALLOUT, "u%r", unit); @@ -392,7 +392,7 @@ tp = sc->sc_u.u_tty.tp; tp->t_pps = NULL; ttygone(tp); - ithread_remove_handler(sc->sc_softih); + swi_remove(sc->sc_softih); ttyfree(tp); return (0); Index: dev/zs/zs.c =================================================================== RCS file: /usr/cvs/src/sys/dev/zs/zs.c,v retrieving revision 1.30 diff -u -r1.30 zs.c --- dev/zs/zs.c 20 Oct 2004 16:22:00 -0000 1.30 +++ dev/zs/zs.c 2 Mar 2006 16:08:18 -0000 @@ -183,7 +183,7 @@ for (i = 0; i < ZS_NCHAN; i++) sc->sc_child[i] = device_get_softc(child[i]); - swi_add(&tty_ithd, "tty:zs", zs_softintr, sc, SWI_TTY, + swi_add(&tty_intr_event, "zs", zs_softintr, sc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); ZS_WRITE_REG(sc->sc_child[0], 2, sc->sc_child[0]->sc_creg[2]); Index: i386/i386/intr_machdep.c =================================================================== RCS file: /usr/cvs/src/sys/i386/i386/intr_machdep.c,v retrieving revision 1.14.2.1 diff -u -r1.14.2.1 intr_machdep.c --- i386/i386/intr_machdep.c 7 Mar 2006 18:33:21 -0000 1.14.2.1 +++ i386/i386/intr_machdep.c 7 Mar 2006 19:53:34 -0000 @@ -57,7 +57,7 @@ #define MAX_STRAY_LOG 5 -typedef void (*mask_fn)(uintptr_t vector); +typedef void (*mask_fn)(void *); static int intrcnt_index; static struct intsrc *interrupt_sources[NUM_IO_INTS]; @@ -87,15 +87,14 @@ vector = isrc->is_pic->pic_vector(isrc); if (interrupt_sources[vector] != NULL) return (EEXIST); - error = ithread_create(&isrc->is_ithread, (uintptr_t)isrc, 0, - (mask_fn)isrc->is_pic->pic_disable_source, + error = intr_event_create(&isrc->is_event, isrc, 0, (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector); if (error) return (error); mtx_lock_spin(&intr_table_lock); if (interrupt_sources[vector] != NULL) { mtx_unlock_spin(&intr_table_lock); - ithread_destroy(isrc->is_ithread); + intr_event_destroy(isrc->is_event); return (EEXIST); } intrcnt_register(isrc); @@ -122,8 +121,8 @@ isrc = intr_lookup_source(vector); if (isrc == NULL) return (EINVAL); - error = ithread_add_handler(isrc->is_ithread, name, handler, arg, - ithread_priority(flags), flags, cookiep); + error = intr_event_add_handler(isrc->is_event, name, handler, arg, + intr_priority(flags), flags, cookiep); if (error == 0) { intrcnt_updatename(isrc); mtx_lock_spin(&intr_table_lock); @@ -147,7 +146,7 @@ { int error; - error = ithread_remove_handler(cookie); + error = intr_event_remove_handler(cookie); #ifdef XXX if (error == 0) intrcnt_updatename(/* XXX */); @@ -170,12 +169,11 @@ intr_execute_handlers(struct intsrc *isrc, struct intrframe *iframe) { struct thread *td; - struct ithd *it; - struct intrhand *ih; - int error, vector; + struct intr_event *ie; + struct intr_handler *ih; + int error, vector, thread; td = curthread; - td->td_intr_nesting_level++; /* * We count software interrupts when we process them. The @@ -186,11 +184,7 @@ (*isrc->is_count)++; PCPU_LAZY_INC(cnt.v_intr); - it = isrc->is_ithread; - if (it == NULL) - ih = NULL; - else - ih = TAILQ_FIRST(&it->it_handlers); + ie = isrc->is_event; /* * XXX: We assume that IRQ 0 is only used for the ISA timer @@ -200,40 +194,12 @@ if (vector == 0) clkintr_pending = 1; - if (ih != NULL && ih->ih_flags & IH_FAST) { - /* - * Execute fast interrupt handlers directly. - * To support clock handlers, if a handler registers - * with a NULL argument, then we pass it a pointer to - * a trapframe as its argument. - */ - critical_enter(); - TAILQ_FOREACH(ih, &it->it_handlers, ih_next) { - MPASS(ih->ih_flags & IH_FAST); - CTR3(KTR_INTR, "%s: executing handler %p(%p)", - __func__, ih->ih_handler, - ih->ih_argument == NULL ? iframe : - ih->ih_argument); - if (ih->ih_argument == NULL) - ih->ih_handler(iframe); - else - ih->ih_handler(ih->ih_argument); - } - isrc->is_pic->pic_eoi_source(isrc); - error = 0; - critical_exit(); - } else { - /* - * For stray and threaded interrupts, we mask and EOI the - * source. - */ + /* + * For stray interrupts, mask and EOI the source, bump the + * stray count, and log the condition. + */ + if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) { isrc->is_pic->pic_disable_source(isrc, PIC_EOI); - if (ih == NULL) - error = EINVAL; - else - error = ithread_schedule(it); - } - if (error == EINVAL) { (*isrc->is_straycount)++; if (*isrc->is_straycount < MAX_STRAY_LOG) log(LOG_ERR, "stray irq%d\n", vector); @@ -241,6 +207,47 @@ log(LOG_CRIT, "too many stray irq %d's: not logging anymore\n", vector); + return; + } + + /* + * Execute fast interrupt handlers directly. + * To support clock handlers, if a handler registers + * with a NULL argument, then we pass it a pointer to + * an intrframe as its argument. + */ + td->td_intr_nesting_level++; + thread = 0; + critical_enter(); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) { + thread = 1; + continue; + } + CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, + ih->ih_handler, ih->ih_argument == NULL ? iframe : + ih->ih_argument, ih->ih_name); + if (ih->ih_argument == NULL) + ih->ih_handler(iframe); + else + ih->ih_handler(ih->ih_argument); + } + + /* + * If there are any threaded handlers that need to run, + * mask the source as well as sending it an EOI. Otherwise, + * just send it an EOI but leave it unmasked. + */ + if (thread) + isrc->is_pic->pic_disable_source(isrc, PIC_EOI); + else + isrc->is_pic->pic_eoi_source(isrc); + critical_exit(); + + /* Schedule the ithread if needed. */ + if (thread) { + error = intr_event_schedule_thread(ie); + KASSERT(error == 0, ("bad stray interrupt")); } td->td_intr_nesting_level--; } @@ -283,7 +290,7 @@ intrcnt_updatename(struct intsrc *is) { - intrcnt_setname(is->is_ithread->it_td->td_proc->p_comm, is->is_index); + intrcnt_setname(is->is_event->ie_fullname, is->is_index); } static void @@ -292,7 +299,7 @@ char straystr[MAXCOMLEN + 1]; /* mtx_assert(&intr_table_lock, MA_OWNED); */ - KASSERT(is->is_ithread != NULL, ("%s: isrc with no ithread", __func__)); + KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__)); is->is_index = intrcnt_index; intrcnt_index += 2; snprintf(straystr, MAXCOMLEN + 1, "stray irq%d", @@ -342,7 +349,7 @@ db_setup_paging(db_simple_pager, &quit, db_lines_per_page); for (i = 0; i < NUM_IO_INTS && !quit; i++, isrc++) if (*isrc != NULL) - db_dump_ithread((*isrc)->is_ithread, verbose); + db_dump_intr_event((*isrc)->is_event, verbose); } #endif Index: i386/i386/local_apic.c =================================================================== RCS file: /usr/cvs/src/sys/i386/i386/local_apic.c,v retrieving revision 1.17.2.5 diff -u -r1.17.2.5 local_apic.c --- i386/i386/local_apic.c 7 Mar 2006 18:33:21 -0000 1.17.2.5 +++ i386/i386/local_apic.c 7 Mar 2006 19:53:34 -0000 @@ -774,11 +774,9 @@ isrc = intr_lookup_source(irq); if (isrc == NULL || verbose == 0) db_printf("IRQ %u\n", irq); -#if 0 else db_dump_intr_event(isrc->is_event, verbose == 2); -#endif } else db_printf("IRQ %u ???\n", irq); } Index: i386/include/intr_machdep.h =================================================================== RCS file: /usr/cvs/src/sys/i386/include/intr_machdep.h,v retrieving revision 1.7.2.2 diff -u -r1.7.2.2 intr_machdep.h --- i386/include/intr_machdep.h 7 Mar 2006 18:33:21 -0000 1.7.2.2 +++ i386/include/intr_machdep.h 7 Mar 2006 19:53:36 -0000 @@ -102,7 +102,7 @@ */ struct intsrc { struct pic *is_pic; - struct ithd *is_ithread; + struct intr_event *is_event; u_long *is_count; u_long *is_straycount; u_int is_index; Index: i386/isa/atpic.c =================================================================== RCS file: /usr/cvs/src/sys/i386/isa/atpic.c,v retrieving revision 1.20.2.2 diff -u -r1.20.2.2 atpic.c --- i386/isa/atpic.c 7 Mar 2006 18:33:21 -0000 1.20.2.2 +++ i386/isa/atpic.c 7 Mar 2006 19:53:37 -0000 @@ -562,10 +562,10 @@ isrc = &atintrs[iframe.if_vec].at_intsrc; /* - * If we don't have an ithread, see if this is a spurious + * If we don't have an event, see if this is a spurious * interrupt. */ - if (isrc->is_ithread == NULL && + if (isrc->is_event == NULL && (iframe.if_vec == 7 || iframe.if_vec == 15)) { int port, isr; Index: ia64/ia64/interrupt.c =================================================================== RCS file: /usr/cvs/src/sys/ia64/ia64/interrupt.c,v retrieving revision 1.49.2.1 diff -u -r1.49.2.1 interrupt.c --- ia64/ia64/interrupt.c 13 Sep 2005 21:07:14 -0000 1.49.2.1 +++ ia64/ia64/interrupt.c 2 Mar 2006 16:01:06 -0000 @@ -254,7 +254,7 @@ #define IA64_HARDWARE_IRQ_BASE 0x20 struct ia64_intr { - struct ithd *ithd; /* interrupt thread */ + struct intr_event *event; /* interrupt event */ volatile long *cntp; /* interrupt counter */ }; @@ -268,7 +268,7 @@ ithds_init(void *dummy) { - mtx_init(&ia64_intrs_lock, "ithread table lock", NULL, MTX_SPIN); + mtx_init(&ia64_intrs_lock, "intr table", NULL, MTX_SPIN); } SYSINIT(ithds_init, SI_SUB_INTR, SI_ORDER_SECOND, ithds_init, NULL); @@ -291,7 +291,7 @@ { struct ia64_intr *i; int errcode; - int vector = irq + IA64_HARDWARE_IRQ_BASE; + intptr_t vector = irq + IA64_HARDWARE_IRQ_BASE; char *intrname; /* @@ -321,8 +321,8 @@ memset(intrname, ' ', INTRNAME_LEN - 1); bcopy(name, intrname, strlen(name)); } - errcode = ithread_create(&i->ithd, vector, 0, 0, - ia64_send_eoi, "intr:"); + errcode = intr_event_create(&i->event, (void *)vector, 0, + (void (*)(void *))ia64_send_eoi, "intr:"); if (errcode) { free(i, M_DEVBUF); return errcode; @@ -334,8 +334,8 @@ } /* Second, add this handler. */ - errcode = ithread_add_handler(i->ithd, name, handler, arg, - ithread_priority(flags), flags, cookiep); + errcode = intr_event_add_handler(i->event, name, handler, arg, + intr_priority(flags), flags, cookiep); if (errcode) return errcode; @@ -346,53 +346,59 @@ ia64_teardown_intr(void *cookie) { - return (ithread_remove_handler(cookie)); + return (intr_event_remove_handler(cookie)); } void ia64_dispatch_intr(void *frame, unsigned long vector) { struct ia64_intr *i; - struct ithd *ithd; /* our interrupt thread */ - struct intrhand *ih; - int error; + struct intr_event *ie; /* our interrupt event */ + struct intr_handler *ih; + int error, thread; /* * Find the interrupt thread for this vector. */ i = ia64_intrs[vector]; if (i == NULL) - return; /* no ithread for this vector */ + return; /* no event for this vector */ if (i->cntp) atomic_add_long(i->cntp, 1); - ithd = i->ithd; - KASSERT(ithd != NULL, ("interrupt vector without a thread")); + ie = i->event; + KASSERT(ie != NULL, ("interrupt vector without an event")); /* - * As an optimization, if an ithread has no handlers, don't + * As an optimization, if an event has no handlers, don't * schedule it to run. */ - if (TAILQ_EMPTY(&ithd->it_handlers)) + if (TAILQ_EMPTY(&ie->ie_handlers)) return; /* - * Handle a fast interrupt if there is no actual thread for this - * interrupt by calling the handler directly without Giant. Note + * Execute all fast interrupt handlers directly without Giant. Note * that this means that any fast interrupt handler must be MP safe. */ - ih = TAILQ_FIRST(&ithd->it_handlers); - if ((ih->ih_flags & IH_FAST) != 0) { - critical_enter(); + thread = 0; + critical_enter(); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) { + thread = 1; + continue; + } + CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, + ih->ih_handler, ih->ih_argument, ih->ih_name); ih->ih_handler(ih->ih_argument); - ia64_send_eoi(vector); - critical_exit(); - return; } + critical_exit(); - error = ithread_schedule(ithd); - KASSERT(error == 0, ("got an impossible stray interrupt")); + if (thread) { + error = intr_event_schedule_thread(ie); + KASSERT(error == 0, ("got an impossible stray interrupt")); + } else + ia64_send_eoi(vector); } #ifdef DDB Index: kern/kern_clock.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_clock.c,v retrieving revision 1.178.2.2 diff -u -r1.178.2.2 kern_clock.c --- kern/kern_clock.c 3 Jan 2006 16:43:33 -0000 1.178.2.2 +++ kern/kern_clock.c 2 Mar 2006 15:51:08 -0000 @@ -439,7 +439,8 @@ * so that we know how much of its real time was spent * in ``non-process'' (i.e., interrupt) work. */ - if ((td->td_ithd != NULL) || td->td_intr_nesting_level >= 2) { + if ((td->td_pflags & TDP_ITHREAD) || + td->td_intr_nesting_level >= 2) { p->p_rux.rux_iticks++; cp_time[CP_INTR]++; } else { @@ -447,7 +448,7 @@ thread_statclock(0); td->td_sticks++; p->p_rux.rux_sticks++; - if (p != PCPU_GET(idlethread)->td_proc) + if (td != PCPU_GET(idlethread)) cp_time[CP_SYS]++; else cp_time[CP_IDLE]++; Index: kern/kern_intr.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_intr.c,v retrieving revision 1.124.2.1 diff -u -r1.124.2.1 kern_intr.c --- kern/kern_intr.c 26 Sep 2005 19:49:12 -0000 1.124.2.1 +++ kern/kern_intr.c 2 Mar 2006 21:46:36 -0000 @@ -58,13 +58,26 @@ #include #endif -struct int_entropy { - struct proc *proc; - uintptr_t vector; +/* + * Describe an interrupt thread. There is one of these per interrupt event. + */ +struct intr_thread { + struct intr_event *it_event; + struct thread *it_thread; /* Kernel thread. */ + int it_flags; /* (j) IT_* flags. */ + int it_need; /* Needs service. */ +}; + +/* Interrupt thread flags kept in it_flags */ +#define IT_DEAD 0x000001 /* Thread is waiting to exit. */ + +struct intr_entropy { + struct thread *td; + uintptr_t event; }; -struct ithd *clk_ithd; -struct ithd *tty_ithd; +struct intr_event *clk_intr_event; +struct intr_event *tty_intr_event; void *softclock_ih; void *vm_ih; @@ -75,13 +88,21 @@ SYSCTL_INT(_hw, OID_AUTO, intr_storm_threshold, CTLFLAG_RW, &intr_storm_threshold, 0, "Number of consecutive interrupts before storm protection is enabled"); +static TAILQ_HEAD(, intr_event) event_list = + TAILQ_HEAD_INITIALIZER(event_list); +static void intr_event_update(struct intr_event *ie); +static struct intr_thread *ithread_create(const char *name); +#ifdef notyet +static void ithread_destroy(struct intr_thread *ithread); +#endif +static void ithread_execute_handlers(struct proc *p, struct intr_event *ie); static void ithread_loop(void *); -static void ithread_update(struct ithd *); +static void ithread_update(struct intr_thread *ithd); static void start_softintr(void *); u_char -ithread_priority(enum intr_type flags) +intr_priority(enum intr_type flags) { u_char pri; @@ -115,153 +136,206 @@ break; default: /* We didn't specify an interrupt level. */ - panic("ithread_priority: no interrupt type in flags"); + panic("intr_priority: no interrupt type in flags"); } return pri; } /* - * Regenerate the name (p_comm) and priority for a threaded interrupt thread. + * Update an ithread based on the associated intr_event. */ static void -ithread_update(struct ithd *ithd) +ithread_update(struct intr_thread *ithd) { - struct intrhand *ih; + struct intr_event *ie; struct thread *td; - struct proc *p; - int missed; + u_char pri; - mtx_assert(&ithd->it_lock, MA_OWNED); - td = ithd->it_td; - if (td == NULL) - return; - p = td->td_proc; + ie = ithd->it_event; + td = ithd->it_thread; - strlcpy(p->p_comm, ithd->it_name, sizeof(p->p_comm)); - ithd->it_flags &= ~IT_ENTROPY; + /* Determine the overall priority of this event. */ + if (TAILQ_EMPTY(&ie->ie_handlers)) + pri = PRI_MAX_ITHD; + else + pri = TAILQ_FIRST(&ie->ie_handlers)->ih_pri; - ih = TAILQ_FIRST(&ithd->it_handlers); - if (ih == NULL) { - mtx_lock_spin(&sched_lock); - sched_prio(td, PRI_MAX_ITHD); - mtx_unlock_spin(&sched_lock); - return; - } + /* Update name and priority. */ + strlcpy(td->td_proc->p_comm, ie->ie_fullname, + sizeof(td->td_proc->p_comm)); mtx_lock_spin(&sched_lock); - sched_prio(td, ih->ih_pri); + sched_prio(td, pri); mtx_unlock_spin(&sched_lock); +} + +/* + * Regenerate the full name of an interrupt event and update its priority. + */ +static void +intr_event_update(struct intr_event *ie) +{ + struct intr_handler *ih; + char *last; + int missed, space; + + /* Start off with no entropy and just the name of the event. */ + mtx_assert(&ie->ie_lock, MA_OWNED); + strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname)); + ie->ie_flags &= ~IE_ENTROPY; missed = 0; - TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) { - if (strlen(p->p_comm) + strlen(ih->ih_name) + 1 < - sizeof(p->p_comm)) { - strcat(p->p_comm, " "); - strcat(p->p_comm, ih->ih_name); + space = 1; + + /* Run through all the handlers updating values. */ + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (strlen(ie->ie_fullname) + strlen(ih->ih_name) + 1 < + sizeof(ie->ie_fullname)) { + strcat(ie->ie_fullname, " "); + strcat(ie->ie_fullname, ih->ih_name); + space = 0; } else missed++; if (ih->ih_flags & IH_ENTROPY) - ithd->it_flags |= IT_ENTROPY; + ie->ie_flags |= IE_ENTROPY; } + + /* + * If the handler names were too long, add +'s to indicate missing + * names. If we run out of room and still have +'s to add, change + * the last character from a + to a *. + */ + last = &ie->ie_fullname[sizeof(ie->ie_fullname) - 2]; while (missed-- > 0) { - if (strlen(p->p_comm) + 1 == sizeof(p->p_comm)) { - if (p->p_comm[sizeof(p->p_comm) - 2] == '+') - p->p_comm[sizeof(p->p_comm) - 2] = '*'; - else - p->p_comm[sizeof(p->p_comm) - 2] = '+'; + if (strlen(ie->ie_fullname) + 1 == sizeof(ie->ie_fullname)) { + if (*last == '+') { + *last = '*'; + break; + } else + *last = '+'; + } else if (space) { + strcat(ie->ie_fullname, " +"); + space = 0; } else - strcat(p->p_comm, "+"); + strcat(ie->ie_fullname, "+"); } - CTR2(KTR_INTR, "%s: updated %s", __func__, p->p_comm); + + /* + * If this event has an ithread, update it's priority and + * name. + */ + if (ie->ie_thread != NULL) + ithread_update(ie->ie_thread); + CTR2(KTR_INTR, "%s: updated %s", __func__, ie->ie_fullname); } int -ithread_create(struct ithd **ithread, uintptr_t vector, int flags, - void (*disable)(uintptr_t), void (*enable)(uintptr_t), const char *fmt, ...) +intr_event_create(struct intr_event **event, void *source, int flags, + void (*enable)(void *), const char *fmt, ...) { - struct ithd *ithd; - struct thread *td; - struct proc *p; - int error; + struct intr_event *ie; va_list ap; - /* The only valid flag during creation is IT_SOFT. */ - if ((flags & ~IT_SOFT) != 0) + /* The only valid flag during creation is IE_SOFT. */ + if ((flags & ~IE_SOFT) != 0) return (EINVAL); - - ithd = malloc(sizeof(struct ithd), M_ITHREAD, M_WAITOK | M_ZERO); - ithd->it_vector = vector; - ithd->it_disable = disable; - ithd->it_enable = enable; - ithd->it_flags = flags; - TAILQ_INIT(&ithd->it_handlers); - mtx_init(&ithd->it_lock, "ithread", NULL, MTX_DEF); + ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO); + ie->ie_source = source; + ie->ie_enable = enable; + ie->ie_flags = flags; + TAILQ_INIT(&ie->ie_handlers); + mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF); va_start(ap, fmt); - vsnprintf(ithd->it_name, sizeof(ithd->it_name), fmt, ap); + vsnprintf(ie->ie_name, sizeof(ie->ie_name), fmt, ap); va_end(ap); + strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname)); + mtx_pool_lock(mtxpool_sleep, &event_list); + TAILQ_INSERT_TAIL(&event_list, ie, ie_list); + mtx_pool_unlock(mtxpool_sleep, &event_list); + if (event != NULL) + *event = ie; + CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name); + return (0); +} + +int +intr_event_destroy(struct intr_event *ie) +{ + + mtx_lock(&ie->ie_lock); + if (!TAILQ_EMPTY(&ie->ie_handlers)) { + mtx_unlock(&ie->ie_lock); + return (EBUSY); + } + mtx_pool_lock(mtxpool_sleep, &event_list); + TAILQ_REMOVE(&event_list, ie, ie_list); + mtx_pool_unlock(mtxpool_sleep, &event_list); + mtx_unlock(&ie->ie_lock); + mtx_destroy(&ie->ie_lock); + free(ie, M_ITHREAD); + return (0); +} + +static struct intr_thread * +ithread_create(const char *name) +{ + struct intr_thread *ithd; + struct thread *td; + struct proc *p; + int error; + + ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO); error = kthread_create(ithread_loop, ithd, &p, RFSTOPPED | RFHIGHPID, - 0, "%s", ithd->it_name); - if (error) { - mtx_destroy(&ithd->it_lock); - free(ithd, M_ITHREAD); - return (error); - } + 0, "%s", name); + if (error) + panic("kthread_create() failed with %d", error); td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */ mtx_lock_spin(&sched_lock); td->td_ksegrp->kg_pri_class = PRI_ITHD; - td->td_priority = PRI_MAX_ITHD; TD_SET_IWAIT(td); mtx_unlock_spin(&sched_lock); - ithd->it_td = td; - td->td_ithd = ithd; - if (ithread != NULL) - *ithread = ithd; - CTR2(KTR_INTR, "%s: created %s", __func__, ithd->it_name); - return (0); + td->td_pflags |= TDP_ITHREAD; + ithd->it_thread = td; + CTR2(KTR_INTR, "%s: created %s", __func__, name); + return (ithd); } -int -ithread_destroy(struct ithd *ithread) +#ifdef notyet +static void +ithread_destroy(struct intr_thread *ithread) { - struct thread *td; - if (ithread == NULL) - return (EINVAL); - td = ithread->it_td; - mtx_lock(&ithread->it_lock); - if (!TAILQ_EMPTY(&ithread->it_handlers)) { - mtx_unlock(&ithread->it_lock); - return (EINVAL); - } - ithread->it_flags |= IT_DEAD; + td = ithread->it_thread; mtx_lock_spin(&sched_lock); + ithread->it_flags |= IT_DEAD; if (TD_AWAITING_INTR(td)) { TD_CLR_IWAIT(td); setrunqueue(td, SRQ_INTR); } mtx_unlock_spin(&sched_lock); - mtx_unlock(&ithread->it_lock); CTR2(KTR_INTR, "%s: killing %s", __func__, ithread->it_name); - return (0); } +#endif int -ithread_add_handler(struct ithd* ithread, const char *name, +intr_event_add_handler(struct intr_event *ie, const char *name, driver_intr_t handler, void *arg, u_char pri, enum intr_type flags, void **cookiep) { - struct intrhand *ih, *temp_ih; + struct intr_handler *ih, *temp_ih; + struct intr_thread *it; - if (ithread == NULL || name == NULL || handler == NULL) + if (ie == NULL || name == NULL || handler == NULL) return (EINVAL); - ih = malloc(sizeof(struct intrhand), M_ITHREAD, M_WAITOK | M_ZERO); + /* Allocate and populate an interrupt handler structure. */ + ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO); ih->ih_handler = handler; ih->ih_argument = arg; ih->ih_name = name; - ih->ih_ithread = ithread; + ih->ih_event = ie; ih->ih_pri = pri; if (flags & INTR_FAST) ih->ih_flags = IH_FAST; @@ -272,69 +346,97 @@ if (flags & INTR_ENTROPY) ih->ih_flags |= IH_ENTROPY; - mtx_lock(&ithread->it_lock); - if ((flags & INTR_EXCL) != 0 && !TAILQ_EMPTY(&ithread->it_handlers)) - goto fail; - if (!TAILQ_EMPTY(&ithread->it_handlers)) { - temp_ih = TAILQ_FIRST(&ithread->it_handlers); - if (temp_ih->ih_flags & IH_EXCLUSIVE) - goto fail; - if ((ih->ih_flags & IH_FAST) && !(temp_ih->ih_flags & IH_FAST)) - goto fail; - if (!(ih->ih_flags & IH_FAST) && (temp_ih->ih_flags & IH_FAST)) - goto fail; - } - - TAILQ_FOREACH(temp_ih, &ithread->it_handlers, ih_next) - if (temp_ih->ih_pri > ih->ih_pri) - break; + /* We can only have one exclusive handler in a event. */ + mtx_lock(&ie->ie_lock); + if (!TAILQ_EMPTY(&ie->ie_handlers)) { + if ((flags & INTR_EXCL) || + (TAILQ_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) { + mtx_unlock(&ie->ie_lock); + free(ih, M_ITHREAD); + return (EINVAL); + } + } + + /* Add the new handler to the event in priority order. */ + TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) { + if (temp_ih->ih_pri > ih->ih_pri) + break; + } if (temp_ih == NULL) - TAILQ_INSERT_TAIL(&ithread->it_handlers, ih, ih_next); + TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next); else TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); - ithread_update(ithread); - mtx_unlock(&ithread->it_lock); + intr_event_update(ie); + + /* Create a thread if we need one. */ + while (ie->ie_thread == NULL && !(flags & INTR_FAST)) { + if (ie->ie_flags & IE_ADDING_THREAD) + msleep(ie, &ie->ie_lock, curthread->td_priority, + "ithread", 0); + else { + ie->ie_flags |= IE_ADDING_THREAD; + mtx_unlock(&ie->ie_lock); + it = ithread_create("intr: newborn"); + mtx_lock(&ie->ie_lock); + ie->ie_flags &= ~IE_ADDING_THREAD; + ie->ie_thread = it; + it->it_event = ie; + ithread_update(it); + wakeup(ie); + } + } + CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name, + ie->ie_name); + mtx_unlock(&ie->ie_lock); if (cookiep != NULL) *cookiep = ih; - CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name, - ithread->it_name); return (0); - -fail: - mtx_unlock(&ithread->it_lock); - free(ih, M_ITHREAD); - return (EINVAL); } int -ithread_remove_handler(void *cookie) +intr_event_remove_handler(void *cookie) { - struct intrhand *handler = (struct intrhand *)cookie; - struct ithd *ithread; + struct intr_handler *handler = (struct intr_handler *)cookie; + struct intr_event *ie; #ifdef INVARIANTS - struct intrhand *ih; + struct intr_handler *ih; +#endif +#ifdef notyet + int dead; #endif if (handler == NULL) return (EINVAL); - ithread = handler->ih_ithread; - KASSERT(ithread != NULL, - ("interrupt handler \"%s\" has a NULL interrupt thread", + ie = handler->ih_event; + KASSERT(ie != NULL, + ("interrupt handler \"%s\" has a NULL interrupt event", handler->ih_name)); + mtx_lock(&ie->ie_lock); CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name, - ithread->it_name); - mtx_lock(&ithread->it_lock); + ie->ie_name); #ifdef INVARIANTS - TAILQ_FOREACH(ih, &ithread->it_handlers, ih_next) + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) if (ih == handler) goto ok; - mtx_unlock(&ithread->it_lock); - panic("interrupt handler \"%s\" not found in interrupt thread \"%s\"", - ih->ih_name, ithread->it_name); + mtx_unlock(&ie->ie_lock); + panic("interrupt handler \"%s\" not found in interrupt event \"%s\"", + ih->ih_name, ie->ie_name); ok: #endif /* + * If there is no ithread, then just remove the handler and return. + * XXX: Note that an INTR_FAST handler might be running on another + * CPU! + */ + if (ie->ie_thread == NULL) { + TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next); + mtx_unlock(&ie->ie_lock); + free(handler, M_ITHREAD); + return (0); + } + + /* * If the interrupt thread is already running, then just mark this * handler as being dead and let the ithread do the actual removal. * @@ -343,7 +445,7 @@ * thread do it. */ mtx_lock_spin(&sched_lock); - if (!TD_AWAITING_INTR(ithread->it_td) && !cold) { + if (!TD_AWAITING_INTR(ie->ie_thread->it_thread) && !cold) { handler->ih_flags |= IH_DEAD; /* @@ -351,22 +453,42 @@ * again and remove this handler if it has already passed * it on the list. */ - ithread->it_need = 1; - } else - TAILQ_REMOVE(&ithread->it_handlers, handler, ih_next); + ie->ie_thread->it_need = 1; + } else + TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next); mtx_unlock_spin(&sched_lock); - if ((handler->ih_flags & IH_DEAD) != 0) - msleep(handler, &ithread->it_lock, PUSER, "itrmh", 0); - ithread_update(ithread); - mtx_unlock(&ithread->it_lock); + while (handler->ih_flags & IH_DEAD) + msleep(handler, &ie->ie_lock, curthread->td_priority, "iev_rmh", + 0); + intr_event_update(ie); +#ifdef notyet + /* + * XXX: This could be bad in the case of ppbus(8). Also, I think + * this could lead to races of stale data when servicing an + * interrupt. + */ + dead = 1; + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) { + dead = 0; + break; + } + } + if (dead) { + ithread_destroy(ie->ie_thread); + ie->ie_thread = NULL; + } +#endif + mtx_unlock(&ie->ie_lock); free(handler, M_ITHREAD); return (0); } int -ithread_schedule(struct ithd *ithread) +intr_event_schedule_thread(struct intr_event *ie) { - struct int_entropy entropy; + struct intr_entropy entropy; + struct intr_thread *it; struct thread *td; struct thread *ctd; struct proc *p; @@ -374,93 +496,97 @@ /* * If no ithread or no handlers, then we have a stray interrupt. */ - if ((ithread == NULL) || TAILQ_EMPTY(&ithread->it_handlers)) + if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers) || + ie->ie_thread == NULL) return (EINVAL); ctd = curthread; - td = ithread->it_td; + it = ie->ie_thread; + td = it->it_thread; p = td->td_proc; + /* * If any of the handlers for this ithread claim to be good * sources of entropy, then gather some. */ - if (harvest.interrupt && ithread->it_flags & IT_ENTROPY) { + if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) { CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__, p->p_pid, p->p_comm); - entropy.vector = ithread->it_vector; - entropy.proc = ctd->td_proc; + entropy.event = (uintptr_t)ie; + entropy.td = ctd; random_harvest(&entropy, sizeof(entropy), 2, 0, RANDOM_INTERRUPT); } - KASSERT(p != NULL, ("ithread %s has no process", ithread->it_name)); - CTR4(KTR_INTR, "%s: pid %d: (%s) need = %d", - __func__, p->p_pid, p->p_comm, ithread->it_need); + KASSERT(p != NULL, ("ithread %s has no process", ie->ie_name)); /* * Set it_need to tell the thread to keep running if it is already * running. Then, grab sched_lock and see if we actually need to * put this thread on the runqueue. */ - ithread->it_need = 1; + it->it_need = 1; mtx_lock_spin(&sched_lock); if (TD_AWAITING_INTR(td)) { - CTR2(KTR_INTR, "%s: setrunqueue %d", __func__, p->p_pid); + CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid, + p->p_comm); TD_CLR_IWAIT(td); setrunqueue(td, SRQ_INTR); } else { - CTR4(KTR_INTR, "%s: pid %d: it_need %d, state %d", - __func__, p->p_pid, ithread->it_need, td->td_state); + CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d", + __func__, p->p_pid, p->p_comm, it->it_need, td->td_state); } mtx_unlock_spin(&sched_lock); return (0); } +/* + * Add a software interrupt handler to a specified event. If a given event + * is not specified, then a new event is created. + */ int -swi_add(struct ithd **ithdp, const char *name, driver_intr_t handler, +swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler, void *arg, int pri, enum intr_type flags, void **cookiep) { - struct ithd *ithd; + struct intr_event *ie; int error; if (flags & (INTR_FAST | INTR_ENTROPY)) return (EINVAL); - ithd = (ithdp != NULL) ? *ithdp : NULL; + ie = (eventp != NULL) ? *eventp : NULL; - if (ithd != NULL) { - if ((ithd->it_flags & IT_SOFT) == 0) - return(EINVAL); + if (ie != NULL) { + if (!(ie->ie_flags & IE_SOFT)) + return (EINVAL); } else { - error = ithread_create(&ithd, pri, IT_SOFT, NULL, NULL, + error = intr_event_create(&ie, NULL, IE_SOFT, NULL, "swi%d:", pri); if (error) return (error); - - if (ithdp != NULL) - *ithdp = ithd; + if (eventp != NULL) + *eventp = ie; } - return (ithread_add_handler(ithd, name, handler, arg, + return (intr_event_add_handler(ie, name, handler, arg, (pri * RQ_PPQ) + PI_SOFT, flags, cookiep)); /* XXKSE.. think of a better way to get separate queues */ } - /* - * Schedule a heavyweight software interrupt process. + * Schedule a software interrupt thread. */ void swi_sched(void *cookie, int flags) { - struct intrhand *ih = (struct intrhand *)cookie; - struct ithd *it = ih->ih_ithread; + struct intr_handler *ih = (struct intr_handler *)cookie; + struct intr_event *ie = ih->ih_event; int error; PCPU_LAZY_INC(cnt.v_intr); - - CTR3(KTR_INTR, "swi_sched pid %d(%s) need=%d", - it->it_td->td_proc->p_pid, it->it_td->td_proc->p_comm, it->it_need); + + CTR3(KTR_INTR, "swi_sched: %s %s need=%d", ie->ie_name, ih->ih_name, + ih->ih_need); /* * Set ih_need for this handler so that if the ithread is already @@ -469,30 +595,134 @@ */ atomic_store_rel_int(&ih->ih_need, 1); if (!(flags & SWI_DELAY)) { - error = ithread_schedule(it); + error = intr_event_schedule_thread(ie); KASSERT(error == 0, ("stray software interrupt")); } } /* + * Remove a software interrupt handler. Currently this code does not + * remove the associated interrupt event if it becomes empty. Calling code + * may do so manually via intr_event_destroy(), but that's not really + * an optimal interface. + */ +int +swi_remove(void *cookie) +{ + + return (intr_event_remove_handler(cookie)); +} + +/* ABI compatibility shim. */ +int ithread_remove_handler(void *); + +int +ithread_remove_handler(void *cookie) +{ + + return (intr_event_remove_handler(cookie)); +} + +static void +ithread_execute_handlers(struct proc *p, struct intr_event *ie) +{ + struct intr_handler *ih, *ihn; + + /* Interrupt handlers should not sleep. */ + if (!(ie->ie_flags & IE_SOFT)) + THREAD_NO_SLEEPING(); + TAILQ_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) { + + /* + * If this handler is marked for death, remove it from + * the list of handlers and wake up the sleeper. + */ + if (ih->ih_flags & IH_DEAD) { + mtx_lock(&ie->ie_lock); + TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next); + ih->ih_flags &= ~IH_DEAD; + wakeup(ih); + mtx_unlock(&ie->ie_lock); + continue; + } + + /* + * For software interrupt threads, we only execute + * handlers that have their need flag set. Hardware + * interrupt threads always invoke all of their handlers. + */ + if (ie->ie_flags & IE_SOFT) { + if (!ih->ih_need) + continue; + else + atomic_store_rel_int(&ih->ih_need, 0); + } + + /* Fast handlers are handled in primary interrupt context. */ + if (ih->ih_flags & IH_FAST) + continue; + + /* Execute this handler. */ + CTR6(KTR_INTR, "%s: pid %d exec %p(%p) for %s flg=%x", + __func__, p->p_pid, (void *)ih->ih_handler, ih->ih_argument, + ih->ih_name, ih->ih_flags); + + if (!(ih->ih_flags & IH_MPSAFE)) + mtx_lock(&Giant); + ih->ih_handler(ih->ih_argument); + if (!(ih->ih_flags & IH_MPSAFE)) + mtx_unlock(&Giant); + } + if (!(ie->ie_flags & IE_SOFT)) + THREAD_SLEEPING_OK(); + + /* + * Interrupt storm handling: + * + * If this interrupt source is currently storming, then throttle + * it to only fire the handler once per clock tick. + * + * If this interrupt source is not currently storming, but the + * number of back to back interrupts exceeds the storm threshold, + * then enter storming mode. + */ + if (intr_storm_threshold != 0 && ie->ie_count >= intr_storm_threshold) { + if (ie->ie_warned == 0) { + printf( + "Interrupt storm detected on \"%s\"; throttling interrupt source\n", + ie->ie_name); + ie->ie_warned = 1; + } + tsleep(&ie->ie_count, curthread->td_priority, "istorm", 1); + } else + ie->ie_count++; + + /* + * Now that all the handlers have had a chance to run, reenable + * the interrupt source. + */ + if (ie->ie_enable != NULL) + ie->ie_enable(ie->ie_source); +} + +/* * This is the main code for interrupt threads. */ static void ithread_loop(void *arg) { - struct ithd *ithd; /* our thread context */ - struct intrhand *ih; /* and our interrupt handler chain */ + struct intr_thread *ithd; + struct intr_event *ie; struct thread *td; struct proc *p; - int count, warned; - + td = curthread; p = td->td_proc; - ithd = (struct ithd *)arg; /* point to myself */ - KASSERT(ithd->it_td == td && td->td_ithd == ithd, + ithd = (struct intr_thread *)arg; + KASSERT(ithd->it_thread == td, ("%s: ithread and proc linkage out of sync", __func__)); - count = 0; - warned = 0; + ie = ithd->it_event; + ie->ie_count = 0; /* * As long as we have interrupts outstanding, go through the @@ -503,80 +733,26 @@ * If we are an orphaned thread, then just die. */ if (ithd->it_flags & IT_DEAD) { - CTR3(KTR_INTR, "%s: pid %d: (%s) exiting", __func__, + CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__, p->p_pid, p->p_comm); - td->td_ithd = NULL; - mtx_destroy(&ithd->it_lock); free(ithd, M_ITHREAD); kthread_exit(0); } - CTR4(KTR_INTR, "%s: pid %d: (%s) need=%d", __func__, - p->p_pid, p->p_comm, ithd->it_need); + /* + * Service interrupts. If another interrupt arrives while + * we are running, it will set it_need to note that we + * should make another pass. + */ while (ithd->it_need) { /* - * Service interrupts. If another interrupt - * arrives while we are running, they will set - * it_need to denote that we should make - * another pass. + * This might need a full read and write barrier + * to make sure that this write posts before any + * of the memory or device accesses in the + * handlers. */ atomic_store_rel_int(&ithd->it_need, 0); - if (!(ithd->it_flags & IT_SOFT)) - THREAD_NO_SLEEPING(); -restart: - TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) { - if (ithd->it_flags & IT_SOFT && !ih->ih_need) - continue; - atomic_store_rel_int(&ih->ih_need, 0); - CTR6(KTR_INTR, - "%s: pid %d ih=%p: %p(%p) flg=%x", __func__, - p->p_pid, (void *)ih, - (void *)ih->ih_handler, ih->ih_argument, - ih->ih_flags); - - if ((ih->ih_flags & IH_DEAD) != 0) { - mtx_lock(&ithd->it_lock); - TAILQ_REMOVE(&ithd->it_handlers, ih, - ih_next); - wakeup(ih); - mtx_unlock(&ithd->it_lock); - goto restart; - } - if ((ih->ih_flags & IH_MPSAFE) == 0) - mtx_lock(&Giant); - ih->ih_handler(ih->ih_argument); - if ((ih->ih_flags & IH_MPSAFE) == 0) - mtx_unlock(&Giant); - } - if (!(ithd->it_flags & IT_SOFT)) - THREAD_SLEEPING_OK(); - - /* - * Interrupt storm handling: - * - * If this interrupt source is currently storming, - * then throttle it to only fire the handler once - * per clock tick. - * - * If this interrupt source is not currently - * storming, but the number of back to back - * interrupts exceeds the storm threshold, then - * enter storming mode. - */ - if (intr_storm_threshold != 0 && - count >= intr_storm_threshold) { - if (!warned) { - printf( - "Interrupt storm detected on \"%s\"; throttling interrupt source\n", - p->p_comm); - warned = 1; - } - tsleep(&count, td->td_priority, "istorm", 1); - } else - count++; - - if (ithd->it_enable != NULL) - ithd->it_enable(ithd->it_vector); + ithread_execute_handlers(p, ie); } WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread"); mtx_assert(&Giant, MA_NOTOWNED); @@ -587,12 +763,10 @@ * set again, so we have to check it again. */ mtx_lock_spin(&sched_lock); - if (!ithd->it_need) { + if (!ithd->it_need && !(ithd->it_flags & IT_DEAD)) { TD_SET_IWAIT(td); - count = 0; - CTR2(KTR_INTR, "%s: pid %d: done", __func__, p->p_pid); + ie->ie_count = 0; mi_switch(SW_VOL, NULL); - CTR2(KTR_INTR, "%s: pid %d: resumed", __func__, p->p_pid); } mtx_unlock_spin(&sched_lock); } @@ -603,7 +777,7 @@ * Dump details about an interrupt handler */ static void -db_dump_intrhand(struct intrhand *ih) +db_dump_intrhand(struct intr_handler *ih) { int comma; @@ -686,41 +860,42 @@ } /* - * Dump details about an ithread + * Dump details about a event. */ void -db_dump_ithread(struct ithd *ithd, int handlers) +db_dump_intr_event(struct intr_event *ie, int handlers) { - struct proc *p; - struct intrhand *ih; + struct intr_handler *ih; + struct intr_thread *it; int comma; - if (ithd->it_td != NULL) { - p = ithd->it_td->td_proc; - db_printf("%s (pid %d)", p->p_comm, p->p_pid); - } else - db_printf("%s: (no thread)", ithd->it_name); - if ((ithd->it_flags & (IT_SOFT | IT_ENTROPY | IT_DEAD)) != 0 || - ithd->it_need) { + db_printf("%s ", ie->ie_fullname); + it = ie->ie_thread; + if (it != NULL) + db_printf("(pid %d)", it->it_thread->td_proc->p_pid); + else + db_printf("(no thread)"); + if ((ie->ie_flags & (IE_SOFT | IE_ENTROPY | IE_ADDING_THREAD)) != 0 || + (it != NULL && it->it_need)) { db_printf(" {"); comma = 0; - if (ithd->it_flags & IT_SOFT) { + if (ie->ie_flags & IE_SOFT) { db_printf("SOFT"); comma = 1; } - if (ithd->it_flags & IT_ENTROPY) { + if (ie->ie_flags & IE_ENTROPY) { if (comma) db_printf(", "); db_printf("ENTROPY"); comma = 1; } - if (ithd->it_flags & IT_DEAD) { + if (ie->ie_flags & IE_ADDING_THREAD) { if (comma) db_printf(", "); - db_printf("DEAD"); + db_printf("ADDING_THREAD"); comma = 1; } - if (ithd->it_need) { + if (it != NULL && it->it_need) { if (comma) db_printf(", "); db_printf("NEED"); @@ -730,9 +905,28 @@ db_printf("\n"); if (handlers) - TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) db_dump_intrhand(ih); } + +/* + * Dump data about interrupt handlers + */ +DB_SHOW_COMMAND(intr, db_show_intr) +{ + struct intr_event *ie; + int quit, all, verbose; + + quit = 0; + verbose = index(modif, 'v') != NULL; + all = index(modif, 'a') != NULL; + db_setup_paging(db_simple_pager, &quit, db_lines_per_page); + TAILQ_FOREACH(ie, &event_list, ie_list) { + if (!all && TAILQ_EMPTY(&ie->ie_handlers)) + continue; + db_dump_intr_event(ie, verbose); + } +} #endif /* DDB */ /* @@ -743,19 +937,19 @@ { struct proc *p; - if (swi_add(&clk_ithd, "clock", softclock, NULL, SWI_CLOCK, + if (swi_add(&clk_intr_event, "clock", softclock, NULL, SWI_CLOCK, INTR_MPSAFE, &softclock_ih) || swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, INTR_MPSAFE, &vm_ih)) panic("died while creating standard software ithreads"); - p = clk_ithd->it_td->td_proc; + p = clk_intr_event->ie_thread->it_thread->td_proc; PROC_LOCK(p); p->p_flag |= P_NOLOAD; PROC_UNLOCK(p); } SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr, NULL) -/* +/* * Sysctls used by systat and others: hw.intrnames and hw.intrcnt. * The data for this machine dependent, and the declarations are in machine * dependent code. The layout of intrnames and intrcnt however is machine @@ -767,7 +961,7 @@ static int sysctl_intrnames(SYSCTL_HANDLER_ARGS) { - return (sysctl_handle_opaque(oidp, intrnames, eintrnames - intrnames, + return (sysctl_handle_opaque(oidp, intrnames, eintrnames - intrnames, req)); } @@ -777,7 +971,7 @@ static int sysctl_intrcnt(SYSCTL_HANDLER_ARGS) { - return (sysctl_handle_opaque(oidp, intrcnt, + return (sysctl_handle_opaque(oidp, intrcnt, (char *)eintrcnt - (char *)intrcnt, req)); } Index: kern/subr_witness.c =================================================================== RCS file: /usr/cvs/src/sys/kern/subr_witness.c,v retrieving revision 1.195.2.7 diff -u -r1.195.2.7 subr_witness.c --- kern/subr_witness.c 4 Jan 2006 19:27:22 -0000 1.195.2.7 +++ kern/subr_witness.c 2 Mar 2006 15:51:08 -0000 @@ -374,7 +374,6 @@ { "ng_worklist", &lock_class_mtx_spin }, { "taskqueue_fast", &lock_class_mtx_spin }, { "intr table", &lock_class_mtx_spin }, - { "ithread table lock", &lock_class_mtx_spin }, { "sleepq chain", &lock_class_mtx_spin }, { "sched lock", &lock_class_mtx_spin }, { "turnstile chain", &lock_class_mtx_spin }, Index: netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c =================================================================== RCS file: /usr/cvs/src/sys/netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c,v retrieving revision 1.12 diff -u -r1.12 ng_bt3c_pccard.c --- netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c 24 Jun 2005 14:36:54 -0000 1.12 +++ netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c 2 Mar 2006 16:08:18 -0000 @@ -657,7 +657,7 @@ /* Attach handler to TTY SWI thread */ sc->ith = NULL; - if (swi_add(&tty_ithd, device_get_nameunit(dev), + if (swi_add(&tty_intr_event, device_get_nameunit(dev), bt3c_swi_intr, sc, SWI_TTY, 0, &sc->ith) < 0) { device_printf(dev, "Could not setup SWI ISR\n"); goto bad; @@ -694,7 +694,7 @@ return (0); bad: if (sc->ith != NULL) { - ithread_remove_handler(sc->ith); + swi_remove(sc->ith); sc->ith = NULL; } @@ -736,7 +736,7 @@ device_set_softc(dev, NULL); - ithread_remove_handler(sc->ith); + swi_remove(sc->ith); sc->ith = NULL; bus_teardown_intr(dev, sc->irq, sc->irq_cookie); Index: pc98/cbus/sio.c =================================================================== RCS file: /usr/cvs/src/sys/pc98/cbus/sio.c,v retrieving revision 1.234.2.1 diff -u -r1.234.2.1 sio.c --- pc98/cbus/sio.c 6 Nov 2005 05:01:03 -0000 1.234.2.1 +++ pc98/cbus/sio.c 2 Mar 2006 16:07:37 -0000 @@ -1718,9 +1718,9 @@ printf("\n"); if (sio_fast_ih == NULL) { - swi_add(&tty_ithd, "sio", siopoll, NULL, SWI_TTY, 0, + swi_add(&tty_intr_event, "sio", siopoll, NULL, SWI_TTY, 0, &sio_fast_ih); - swi_add(&clk_ithd, "sio", siopoll, NULL, SWI_CLOCK, 0, + swi_add(&clk_intr_event, "sio", siopoll, NULL, SWI_CLOCK, 0, &sio_slow_ih); } Index: powerpc/include/intr_machdep.h =================================================================== RCS file: /usr/cvs/src/sys/powerpc/include/intr_machdep.h,v retrieving revision 1.5 diff -u -r1.5 intr_machdep.h --- powerpc/include/intr_machdep.h 7 Jan 2005 02:29:19 -0000 1.5 +++ powerpc/include/intr_machdep.h 2 Mar 2006 15:51:08 -0000 @@ -30,12 +30,12 @@ typedef void ih_func_t(void *); -struct ithd; +struct intr_event; -struct intr_handler { +struct ppc_intr_handler { ih_func_t *ih_func; void *ih_arg; - struct ithd *ih_ithd; + struct intr_event *ih_event; u_int ih_irq; u_int ih_flags; u_int ih_index; Index: powerpc/powerpc/intr_machdep.c =================================================================== RCS file: /usr/cvs/src/sys/powerpc/powerpc/intr_machdep.c,v retrieving revision 1.6 diff -u -r1.6 intr_machdep.c --- powerpc/powerpc/intr_machdep.c 2 Jul 2004 20:21:43 -0000 1.6 +++ powerpc/powerpc/intr_machdep.c 2 Mar 2006 15:51:08 -0000 @@ -85,7 +85,7 @@ static int intr_initialized = 0; static u_int intr_nirq; -static struct intr_handler *intr_handlers; +static struct ppc_intr_handler *intr_handlers; static struct mtx intr_table_lock; @@ -100,7 +100,7 @@ static void (*irq_disable)(uintptr_t); static void intrcnt_setname(const char *name, int index); -static void intrcnt_updatename(struct intr_handler *ih); +static void intrcnt_updatename(struct ppc_intr_handler *ih); static void intrcnt_setname(const char *name, int index) @@ -110,18 +110,18 @@ } static void -intrcnt_updatename(struct intr_handler *ih) +intrcnt_updatename(struct ppc_intr_handler *ih) { - intrcnt_setname(ih->ih_ithd->it_td->td_proc->p_comm, ih->ih_index); + intrcnt_setname(ih->ih_event->ie_fullname, ih->ih_index); } static void -intrcnt_register(struct intr_handler *ih) +intrcnt_register(struct ppc_intr_handler *ih) { char straystr[MAXCOMLEN + 1]; - KASSERT(ih->ih_ithd != NULL, - ("%s: intr_handler with no ithread", __func__)); + KASSERT(ih->ih_event != NULL, + ("%s: ppc_intr_handler with no event", __func__)); ih->ih_index = intrcnt_index; intrcnt_index += 2; @@ -145,7 +145,7 @@ intr_initialized++; intr_nirq = nirq; - intr_handlers = malloc(nirq * sizeof(struct intr_handler), M_INTR, + intr_handlers = malloc(nirq * sizeof(struct ppc_intr_handler), M_INTR, M_NOWAIT|M_ZERO); if (intr_handlers == NULL) panic("intr_init: unable to allocate interrupt handler array"); @@ -172,7 +172,7 @@ irq_enable = irq_e; irq_disable = irq_d; - mtx_init(&intr_table_lock, "ithread table lock", NULL, MTX_SPIN); + mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); } void @@ -195,10 +195,10 @@ inthand_add(const char *name, u_int irq, void (*handler)(void *), void *arg, int flags, void **cookiep) { - struct intr_handler *ih; - struct ithd *ithd, *orphan; + struct ppc_intr_handler *ih; + struct intr_event *event, *orphan; int error = 0; - int created_ithd = 0; + int created_event = 0; /* * Work around a race where more than one CPU may be registering @@ -206,30 +206,33 @@ */ ih = &intr_handlers[irq]; mtx_lock_spin(&intr_table_lock); - ithd = ih->ih_ithd; + event = ih->ih_event; mtx_unlock_spin(&intr_table_lock); - if (ithd == NULL) { - error = ithread_create(&ithd, irq, 0, irq_disable, - irq_enable, "irq%d:", irq); + if (event == NULL) { + error = intr_event_create(&event, (void *)irq, 0, + (void (*)(void *))irq_enable, "irq%d:", irq); if (error) return (error); mtx_lock_spin(&intr_table_lock); - if (ih->ih_ithd == NULL) { - ih->ih_ithd = ithd; - created_ithd++; + if (ih->ih_event == NULL) { + ih->ih_event = event; + created_event++; mtx_unlock_spin(&intr_table_lock); } else { - orphan = ithd; - ithd = ih->ih_ithd; + orphan = event; + event = ih->ih_event; mtx_unlock_spin(&intr_table_lock); - ithread_destroy(orphan); + intr_event_destroy(orphan); } } - error = ithread_add_handler(ithd, name, handler, arg, - ithread_priority(flags), flags, cookiep); + /* XXX: Should probably fix support for multiple FAST. */ + if (flags & INTR_FAST) + flags |= INTR_EXCL; + error = intr_event_add_handler(event, name, handler, arg, + intr_priority(flags), flags, cookiep); if ((flags & INTR_FAST) == 0 || error) { intr_setup(irq, sched_ithd, ih, flags); @@ -250,17 +253,17 @@ int inthand_remove(u_int irq, void *cookie) { - struct intr_handler *ih; + struct ppc_intr_handler *ih; int error; - error = ithread_remove_handler(cookie); + error = intr_event_remove_handler(cookie); if (error == 0) { ih = &intr_handlers[irq]; mtx_lock_spin(&intr_table_lock); - if (ih->ih_ithd == NULL) { + if (ih->ih_event == NULL) { intr_setup(irq, intr_stray_handler, ih, 0); } else { intr_setup(irq, sched_ithd, ih, 0); @@ -286,9 +289,9 @@ static void intr_stray_handler(void *cookie) { - struct intr_handler *ih; + struct ppc_intr_handler *ih; - ih = (struct intr_handler *)cookie; + ih = (struct ppc_intr_handler *)cookie; if (*intr_handlers[ih->ih_irq].ih_straycount < MAX_STRAY_LOG) { printf("stray irq %d\n", ih->ih_irq); @@ -303,12 +306,12 @@ static void sched_ithd(void *cookie) { - struct intr_handler *ih; + struct ppc_intr_handler *ih; int error; - ih = (struct intr_handler *)cookie; + ih = (struct ppc_intr_handler *)cookie; - error = ithread_schedule(ih->ih_ithd); + error = intr_event_schedule_thread(ih->ih_event); if (error == EINVAL) intr_stray_handler(ih); Index: sparc64/include/intr_machdep.h =================================================================== RCS file: /usr/cvs/src/sys/sparc64/include/intr_machdep.h,v retrieving revision 1.13 diff -u -r1.13 intr_machdep.h --- sparc64/include/intr_machdep.h 16 Jul 2003 00:08:43 -0000 1.13 +++ sparc64/include/intr_machdep.h 2 Mar 2006 15:51:08 -0000 @@ -67,7 +67,7 @@ struct intr_vector { iv_func_t *iv_func; void *iv_arg; - struct ithd *iv_ithd; + struct intr_event *iv_event; u_int iv_pri; u_int iv_vec; }; Index: sparc64/sparc64/intr_machdep.c =================================================================== RCS file: /usr/cvs/src/sys/sparc64/sparc64/intr_machdep.c,v retrieving revision 1.23 diff -u -r1.23 intr_machdep.c --- sparc64/sparc64/intr_machdep.c 16 Apr 2005 15:05:56 -0000 1.23 +++ sparc64/sparc64/intr_machdep.c 2 Mar 2006 15:51:08 -0000 @@ -227,38 +227,44 @@ intr_init2() { - mtx_init(&intr_table_lock, "ithread table lock", NULL, MTX_SPIN); + mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); } static void intr_execute_handlers(void *cookie) { struct intr_vector *iv; - struct ithd *ithd; - struct intrhand *ih; - int error; + struct intr_event *ie; + struct intr_handler *ih; + int error, thread; iv = cookie; - ithd = iv->iv_ithd; + ie = iv->iv_event; + if (ie == NULL) { + intr_stray_vector(iv); + return; + } - if (ithd == NULL) - ih = NULL; - else - ih = TAILQ_FIRST(&ithd->it_handlers); - if (ih != NULL && ih->ih_flags & IH_FAST) { - /* Execute fast interrupt handlers directly. */ - TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) { - MPASS(ih->ih_flags & IH_FAST && - ih->ih_argument != NULL); - CTR3(KTR_INTR, "%s: executing handler %p(%p)", - __func__, ih->ih_handler, ih->ih_argument); - ih->ih_handler(ih->ih_argument); + /* Execute fast interrupt handlers directly. */ + thread = 0; + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (!(ih->ih_flags & IH_FAST)) { + thread = 1; + continue; } - return; + MPASS(ih->ih_flags & IH_FAST && ih->ih_argument != NULL); + CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__, + ih->ih_handler, ih->ih_argument); + ih->ih_handler(ih->ih_argument); } /* Schedule a heavyweight interrupt process. */ - error = ithread_schedule(ithd); + if (thread) + error = intr_event_schedule_thread(ie); + else if (TAILQ_EMPTY(&ie->ie_handlers)) + error = EINVAL; + else + error = 0; if (error == EINVAL) intr_stray_vector(iv); } @@ -268,8 +274,8 @@ int flags, void **cookiep) { struct intr_vector *iv; - struct ithd *ithd; /* descriptor for the IRQ */ - struct ithd *orphan; + struct intr_event *ie; /* descriptor for the IRQ */ + struct intr_event *orphan; int errcode; /* @@ -278,27 +284,27 @@ */ iv = &intr_vectors[vec]; mtx_lock_spin(&intr_table_lock); - ithd = iv->iv_ithd; + ie = iv->iv_event; mtx_unlock_spin(&intr_table_lock); - if (ithd == NULL) { - errcode = ithread_create(&ithd, vec, 0, NULL, NULL, "vec%d:", - vec); + if (ie == NULL) { + errcode = intr_event_create(&ie, (void *)(intptr_t)vec, 0, NULL, + "vec%d:", vec); if (errcode) return (errcode); mtx_lock_spin(&intr_table_lock); - if (iv->iv_ithd == NULL) { - iv->iv_ithd = ithd; + if (iv->iv_event == NULL) { + iv->iv_event = ie; mtx_unlock_spin(&intr_table_lock); } else { - orphan = ithd; - ithd = iv->iv_ithd; + orphan = ie; + ie = iv->iv_event; mtx_unlock_spin(&intr_table_lock); - ithread_destroy(orphan); + intr_event_destroy(orphan); } } - errcode = ithread_add_handler(ithd, name, handler, arg, - ithread_priority(flags), flags, cookiep); + errcode = intr_event_add_handler(ie, name, handler, arg, + intr_priority(flags), flags, cookiep); if (errcode) return (errcode); @@ -307,7 +313,7 @@ intr_stray_count[vec] = 0; - intrcnt_updatename(vec, ithd->it_td->td_proc->p_comm, 0); + intrcnt_updatename(vec, ie->ie_fullname, 0); return (0); } @@ -318,15 +324,16 @@ struct intr_vector *iv; int error; - error = ithread_remove_handler(cookie); + error = intr_event_remove_handler(cookie); if (error == 0) { /* * XXX: maybe this should be done regardless of whether - * ithread_remove_handler() succeeded? + * intr_event_remove_handler() succeeded? + * XXX: aren't the PIL's backwards below? */ iv = &intr_vectors[vec]; mtx_lock_spin(&intr_table_lock); - if (iv->iv_ithd == NULL) + if (iv->iv_event == NULL) intr_setup(PIL_ITHREAD, intr_fast, vec, intr_stray_vector, iv); else Index: sys/interrupt.h =================================================================== RCS file: /usr/cvs/src/sys/sys/interrupt.h,v retrieving revision 1.30 diff -u -r1.30 interrupt.h --- sys/interrupt.h 7 Jan 2005 02:29:23 -0000 1.30 +++ sys/interrupt.h 2 Mar 2006 20:40:44 -0000 @@ -32,20 +32,28 @@ #include #include +/* Compatibility shims */ +#define tty_intr_event tty_ithd +#define clk_intr_event clk_ithd +#define ithd intr_event + +struct intr_event; +struct intr_thread; + /* * Describe a hardware interrupt handler. * - * Multiple interrupt handlers for a specific vector can be chained + * Multiple interrupt handlers for a specific event can be chained * together. */ -struct intrhand { +struct intr_handler { driver_intr_t *ih_handler; /* Handler function. */ void *ih_argument; /* Argument to pass to handler. */ int ih_flags; const char *ih_name; /* Name of handler. */ - struct ithd *ih_ithread; /* Ithread we are connected to. */ + struct intr_event *ih_event; /* Event we are connected to. */ int ih_need; /* Needs service. */ - TAILQ_ENTRY(intrhand) ih_next; /* Next handler for this vector. */ + TAILQ_ENTRY(intr_handler) ih_next; /* Next handler for this event. */ u_char ih_pri; /* Priority of this handler. */ }; @@ -57,29 +65,26 @@ #define IH_MPSAFE 0x80000000 /* Handler does not need Giant. */ /* - * Describe an interrupt thread. There is one of these per interrupt vector. - * Note that this actually describes an interrupt source. There may or may - * not be an actual kernel thread attached to a given source. + * Describe an interrupt event. An event holds a list of handlers. */ -struct ithd { - struct mtx it_lock; - struct thread *it_td; /* Interrupt process. */ - LIST_ENTRY(ithd) it_list; /* All interrupt threads. */ - TAILQ_HEAD(, intrhand) it_handlers; /* Interrupt handlers. */ - struct ithd *it_interrupted; /* Who we interrupted. */ - void (*it_disable)(uintptr_t); /* Enable interrupt source. */ - void (*it_enable)(uintptr_t); /* Disable interrupt source. */ - void *it_md; /* Hook for MD interrupt code. */ - int it_flags; /* Interrupt-specific flags. */ - int it_need; /* Needs service. */ - uintptr_t it_vector; - char it_name[MAXCOMLEN + 1]; +struct intr_event { + TAILQ_ENTRY(intr_event) ie_list; + TAILQ_HEAD(, intr_handler) ie_handlers; /* Interrupt handlers. */ + char ie_name[MAXCOMLEN]; /* Individual event name. */ + char ie_fullname[MAXCOMLEN]; + struct mtx ie_lock; + void *ie_source; /* Cookie used by MD code. */ + struct intr_thread *ie_thread; /* Thread we are connected to. */ + void (*ie_enable)(void *); + int ie_flags; + int ie_count; /* Loop counter. */ + int ie_warned; /* Warned about interrupt storm. */ }; -/* Interrupt thread flags kept in it_flags */ -#define IT_SOFT 0x000001 /* Software interrupt. */ -#define IT_ENTROPY 0x000002 /* Interrupt is an entropy source. */ -#define IT_DEAD 0x000004 /* Thread is waiting to exit. */ +/* Interrupt event flags kept in ie_flags. */ +#define IE_SOFT 0x000001 /* Software interrupt. */ +#define IE_ENTROPY 0x000002 /* Interrupt is an entropy source. */ +#define IE_ADDING_THREAD 0x000004 /* Currently building an ithread. */ /* Flags to pass to sched_swi. */ #define SWI_DELAY 0x2 @@ -97,9 +102,8 @@ #define SWI_TQ 6 #define SWI_TQ_GIANT 6 -extern struct ithd *tty_ithd; -extern struct ithd *clk_ithd; -extern void *net_ih; +extern struct intr_event *tty_intr_event; +extern struct intr_event *clk_intr_event; extern void *softclock_ih; extern void *vm_ih; @@ -110,21 +114,22 @@ extern char intrnames[]; /* string table containing device names */ #ifdef DDB -void db_dump_ithread(struct ithd *ithd, int handlers); +void db_dump_intr_event(struct intr_event *ie, int handlers); #endif -int ithread_create(struct ithd **ithread, uintptr_t vector, int flags, - void (*disable)(uintptr_t), void (*enable)(uintptr_t), - const char *fmt, ...) __printflike(6, 7); -int ithread_destroy(struct ithd *ithread); -u_char ithread_priority(enum intr_type flags); -int ithread_add_handler(struct ithd *ithread, const char *name, +u_char intr_priority(enum intr_type flags); +int intr_event_add_handler(struct intr_event *ie, const char *name, driver_intr_t handler, void *arg, u_char pri, enum intr_type flags, void **cookiep); -int ithread_remove_handler(void *cookie); -int ithread_schedule(struct ithd *ithread); -int swi_add(struct ithd **ithdp, const char *name, +int intr_event_create(struct intr_event **event, void *source, + int flags, void (*enable)(void *), const char *fmt, ...) + __printflike(5, 6); +int intr_event_destroy(struct intr_event *ie); +int intr_event_remove_handler(void *cookie); +int intr_event_schedule_thread(struct intr_event *ie); +int swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler, void *arg, int pri, enum intr_type flags, void **cookiep); void swi_sched(void *cookie, int flags); +int swi_remove(void *cookie); #endif Index: sys/proc.h =================================================================== RCS file: /usr/cvs/src/sys/sys/proc.h,v retrieving revision 1.432.2.4 diff -u -r1.432.2.4 proc.h --- sys/proc.h 7 Mar 2006 18:08:09 -0000 1.432.2.4 +++ sys/proc.h 7 Mar 2006 19:55:13 -0000 @@ -149,7 +149,6 @@ * either lock is sufficient for read access, but both locks must be held * for write access. */ -struct ithd; struct kg_sched; struct nlminfo; struct kaioinfo; @@ -267,7 +266,7 @@ volatile u_char td_owepreempt; /* (k*) Preempt on last critical_exit */ short td_locks; /* (k) DEBUG: lockmgr count of locks. */ struct turnstile *td_blocked; /* (j) Lock process is blocked on. */ - struct ithd *td_ithd; /* (b) For interrupt threads only. */ + void *td_ithd; /* (n) Unused, kept to preserve ABI. */ const char *td_lockname; /* (j) Name of lock blocked on. */ LIST_HEAD(, turnstile) td_contested; /* (q) Contested locks. */ struct lock_list_entry *td_sleeplocks; /* (k) Held sleep locks. */ @@ -370,7 +369,7 @@ #define TDP_SA 0x00000080 /* A scheduler activation based thread. */ #define TDP_NOSLEEPING 0x00000100 /* Thread is not allowed to sleep on a sq. */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ -#define TDP_UNUSED10 0x00000400 /* --available -- */ +#define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */ #define TDP_CAN_UNBIND 0x00000800 /* Only temporarily bound. */ #define TDP_SCHED1 0x00001000 /* Reserved for scheduler private use */ #define TDP_SCHED2 0x00002000 /* Reserved for scheduler private use */