ITHREAD(9)                BSD Kernel Developer's Manual               ITHREAD(9)

     ithread_add_handler, ithread_create, ithread_destroy, ithread_priority,
     ithread_remove_handler, ithread_schedule — kernel interrupt threads

     #include <sys/param.h>
     #include <sys/bus.h>
     #include <sys/interrupt.h>

     ithread_add_handler(struct ithd *ithread, const char *name,
         driver_intr_t handler, void *arg, u_char pri, enum intr_type flags,
         void **cookiep);

     ithread_create(struct ithd **ithread, int vector, int flags,
         void (*disable)(int), void (*enable)(int), const char *fmt, ...);

     ithread_destroy(struct ithd *ithread);

     ithread_priority(enum intr_type flags);

     ithread_remove_handler(void *cookie);

     ithread_schedule(struct ithd *ithread, int do_switch);

     Interrupt threads are kernel threads that run a list of handlers when
     triggered by either a hardware or software interrupt.  Each interrupt
     handler has a name, handler function, handler argument, priority, and
     various flags.  Each interrupt thread maintains a list of handlers sorted
     by priority.  This results in higher priority handlers being executed prior
     to lower priority handlers.  Each thread assumes the priority of its
     highest priority handler for its process priority, or PRIO_MAX if it has no
     handlers.  Interrupt threads are also associated with a single interrupt
     source, represented as a vector number.

     The ithread_create() function creates a new interrupt thread.  The ithread
     argument points to an struct ithd pointer that will point to the newly
     created thread upon success.  The vector argument specifies the interrupt
     source to associate this thread with.  The flags argument is a mask of
     properties of this thread.  The only valid flag currently for
     ithread_create() is IT_SOFT to specify that this interrupt thread is a
     software interrupt.  The enable and disable arguments specify optional
     functions used to enable and disable this interrupt thread's interrupt
     source.  The functions receive the vector corresponding to the thread's
     interrupt source as their only argument.  The remaining arguments form a
     printf(9) argument list that is used to build the base name of the new
     ithread.  The full name of an interrupt thread is formed by concatenating
     the base name of an interrupt thread with the names of all of its interrupt

     The ithread_destroy() function destroys a previously created interrupt
     thread by releasing its resources and arranging for the backing kernel
     thread to terminate.  An interrupt thread can only be destroyed if it has
     no handlers remaining.

     The ithread_add_handler() function adds a new handler to an existing
     interrupt thread specified by ithread.  The name argument specifies a name
     for this handler.  The handler and arg arguments provide the function to
     execute for this handler and an argument to pass to it.  The pri argument
     specifies the priority of this handler and is used both in sorting it in
     relation to the other handlers for this thread and to specify the priority
     of the backing kernel thread.  The flags argument can be used to specify
     properties of this handler as defined in <sys/bus.h>.  If cookiep is not
     NULL, then it will be assigned a cookie that can be used later to remove
     this handler.

     The ithread_remove_handler() removes a handler from an interrupt thread.
     The cookie argument specifies the handler to remove from its thread.

     The ithread_schedule() function schedules an interrupt thread to run.  If
     the do_switch argument is non-zero and the interrupt thread is idle, then a
     context switch will be forced after putting the interrupt thread on the run

     The ithread_priority() function translates the INTR_TYPE_* interrupt flags
     into interrupt handler priorities.

     The interrupt flags not related to the type of a particular interrupt
     (INTR_TYPE_*) can be used to specify additional properties of both hardware
     and software interrupt handlers.  The INTR_EXCL flag specifies that this
     handler cannot share an interrupt thread with another handler.  The
     INTR_MPSAFE flag specifies that this handler is MP safe in that it does not
     need the Giant mutex to be held while it is executed.  The INTR_ENTROPY
     flag specifies that the interrupt source this handler is tied to is a good
     source of entropy, and thus that entropy should be gathered when an
     interrupt from the handler's source triggers.  Presently, the INTR_ENTROPY
     flag is not valid for software interrupt handlers.

     It is not permitted to sleep in an interrupt thread; hence, any memory or
     zone allocations in an interrupt thread should be specified with the
     M_NOWAIT flag set.  Any allocation errors must be handled thereafter.

     The ithread_add_handler(), ithread_create(), ithread_destroy(),
     ithread_remove_handler(), and ithread_schedule() functions return zero on
     success and non-zero on failure.  The ithread_priority() function returns a
     process priority corresponding to the passed in interrupt flags.

     The swi_add() function demonstrates the use of ithread_create() and

           swi_add(struct ithd **ithdp, const char *name, driver_intr_t handler,
                       void *arg, int pri, enum intr_type flags, void **cookiep)
                   struct proc *p;
                   struct ithd *ithd;
                   int error;

                   if (flags & INTR_ENTROPY)
                           return (EINVAL);

                   ithd = (ithdp != NULL) ? *ithdp : NULL;

                   if (ithd != NULL) {
                           if ((ithd->it_flags & IT_SOFT) == 0)
                   } else {
                           error = ithread_create(&ithd, pri, IT_SOFT, NULL, NULL,
                               "swi%d:", pri);
                           if (error)
                                   return (error);

                           if (ithdp != NULL)
                                   *ithdp = ithd;
                   return (ithread_add_handler(ithd, name, handler, arg, pri + PI_SOFT,
                               flags, cookiep));

     The ithread_add_handler() function will fail if:

     [EINVAL]           Any of the ithread, handler, or name arguments are NULL.

     [EINVAL]           The INTR_EXCL flag is specified and the interrupt thread
                        ithread already has at least one handler, or the
                        interrupt thread ithread already has an exclusive

     [ENOMEM]           Could not allocate needed memory for this handler.

     The ithread_create() function will fail if:

     [EAGAIN]           The system-imposed limit on the total number of
                        processes under execution would be exceeded.  The limit
                        is given by the sysctl(3) MIB variable KERN_MAXPROC.

     [EINVAL]           A flag other than IT_SOFT was specified in the flags

     [ENOMEM]           Could not allocate needed memory for this interrupt

     The ithread_destroy() function will fail if:

     [EINVAL]           The ithread argument is NULL.

     [EINVAL]           The interrupt thread pointed to by ithread has at least
                        one handler.

     The ithread_remove_handler() function will fail if:

     [EINVAL]           The cookie argument is NULL.

     The ithread_schedule() function will fail if:

     [EINVAL]           The ithread argument is NULL.

     [EINVAL]           The interrupt thread pointed to by ithread has no
                        interrupt handlers.

     kthread(9), malloc(9), swi(9), uma(9)

     Interrupt threads and their corresponding API first appeared in
     FreeBSD 5.0.

     Currently struct ithd represents both an interrupt source and an interrupt
     thread.  There should be a separate struct isrc that contains a vector
     number, enable and disable functions, etc. that an ithread holds a
     reference to.

BSD                              August 25, 2006                             BSD