---
name: "ithread_add_handler"
section: "9freebsd"
platform: "linux"
package: "freebsd-manpages"
version: "12.2-2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/ithread/9freebsd"
---

# ithread\_add\_handler(9freebsd)

kernel interrupt threads

Part of [ithread(9freebsd)](/ithread/9freebsd.md).

## 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)](/printf/9.md) 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)](/sysctl/3.md) 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)](/kthread/9.md), [malloc(9)](/malloc/9.md), [swi(9)](/swi/9.md), [uma(9)](/uma/9.md)

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