FreeBSD/sys/kern/kern_intr.c
/*
 * This is a public function for use by drivers that mux interrupt
 * handlers for child devices from their interrupt handler.
 */
This is a public function for use by drivers that mux interrupt
handlers for child devices from their interrupt handler.
This is a public function for use by drivers that mux interrupt handlers for child devices from their interrupt handler .
void
intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
{
	struct intr_handler *ih, *ihn;
	TAILQ_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
		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;
		}
		if (ih->ih_handler == NULL)
			continue;
		if ((ie->ie_flags & IE_SOFT) != 0 &&
		    atomic_cmpset_int(&ih->ih_need, 1, 0) == 0)
			continue;
		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);
	}
}
void intr_event_execute_handlers ( struct proc * p , struct intr_event * ie ) { struct intr_handler * ih , * ihn ; TAILQ_FOREACH_SAFE ( ih , & ie -> ie_handlers , ih_next , ihn ) { 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 ; } if ( ih -> ih_handler == NULL ) continue ; if ( ( ie -> ie_flags & IE_SOFT ) != 0 && atomic_cmpset_int ( & ih -> ih_need , 1 , 0 ) == 0 ) continue ; CTR6 ( KTR_INTR , " " , __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 ) ; } }
This is a public function for use by drivers that mux interrupt
 handlers for child devices from their interrupt handler.
This is a public function for use by drivers that mux interrupt handlers for child devices from their interrupt handler .
/*
		 * If this handler is marked for death, remove it from
		 * the list of handlers and wake up the sleeper.
		 */ /* Skip filter only handlers */ /*
		 * For software interrupt threads, we only execute
		 * handlers that have their need flag set.  Hardware
		 * interrupt threads always invoke all of their handlers.
		 *
		 * ih_need can only be 0 or 1.  Failed cmpset below
		 * means that there is no request to execute handlers,
		 * so a retry of the cmpset is not needed.
		 */ /* Execute this handler. */