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.