Author: kan Date: Mon Aug 6 16:37:43 2012 New Revision: 239095 URL: http://svn.freebsd.org/changeset/base/239095
Log: Do not add handler to event handlers list until ithread is created. In rare event when fast and ithread interrupts share the same vector and the fast handler was registered first, we can end up trying to schedule the ithread that is not created yet. The kernel built with INVARIANTS then triggers an assertion. Change the order to create the ithread first and only then add the handler that needs it to the interrupt event handlers list. Reviewed by: jhb Modified: head/sys/kern/kern_intr.c Modified: head/sys/kern/kern_intr.c ============================================================================== --- head/sys/kern/kern_intr.c Mon Aug 6 15:22:11 2012 (r239094) +++ head/sys/kern/kern_intr.c Mon Aug 6 16:37:43 2012 (r239095) @@ -545,17 +545,6 @@ intr_event_add_handler(struct intr_event } } - /* 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(&ie->ie_handlers, ih, ih_next); - else - TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); - intr_event_update(ie); - /* Create a thread if we need one. */ while (ie->ie_thread == NULL && handler != NULL) { if (ie->ie_flags & IE_ADDING_THREAD) @@ -572,6 +561,18 @@ intr_event_add_handler(struct intr_event wakeup(ie); } } + + /* 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(&ie->ie_handlers, ih, ih_next); + else + TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); + intr_event_update(ie); + CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name, ie->ie_name); mtx_unlock(&ie->ie_lock); @@ -618,23 +619,12 @@ intr_event_add_handler(struct intr_event } } - /* 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(&ie->ie_handlers, ih, ih_next); - else - TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); - intr_event_update(ie); - /* For filtered handlers, create a private ithread to run on. */ - if (filter != NULL && handler != NULL) { + if (filter != NULL && handler != NULL) { mtx_unlock(&ie->ie_lock); - it = ithread_create("intr: newborn", ih); + it = ithread_create("intr: newborn", ih); mtx_lock(&ie->ie_lock); - it->it_event = ie; + it->it_event = ie; ih->ih_thread = it; ithread_update(it); /* XXX - do we really need this?!?!? */ } else { /* Create the global per-event thread if we need one. */ @@ -654,6 +644,18 @@ intr_event_add_handler(struct intr_event } } } + + /* 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(&ie->ie_handlers, ih, ih_next); + else + TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); + intr_event_update(ie); + CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name, ie->ie_name); mtx_unlock(&ie->ie_lock); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"