Provided by: freebsd-manpages_12.2-1_all bug

NAME

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

SYNOPSIS

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

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

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

     int
     ithread_destroy(struct ithd *ithread);

     u_char
     ithread_priority(enum intr_type flags);

     int
     ithread_remove_handler(void *cookie);

     int
     ithread_schedule(struct ithd *ithread, int do_switch);

DESCRIPTION

     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 handlers.

     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 queue.

     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.

RETURN VALUES

     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.

EXAMPLES

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

           int
           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)
                                   return(EINVAL);
                   } 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));
           }

ERRORS

     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 handler.

     [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 parameter.

     [ENOMEM]           Could not allocate needed memory for this interrupt thread.

     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.

SEE ALSO

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

HISTORY

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

BUGS

     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.