---
name: "KNOTE_LOCKED"
section: "9"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/KNOTE_LOCKED"
---

# KNOTE\_LOCKED(9)

event delivery subsystem

## NAME

**kqueue\_add\_filteropts**, **kqueue\_del\_filteropts**, **kqfd\_register**, **knote\_fdclose**, **knlist\_init**, **knlist\_init\_mtx**, **knlist\_add**, **knlist\_remove**, **knlist\_empty**, **knlist\_clear**, **knlist\_delete**, **knlist\_destroy**, **KNOTE\_LOCKED**, **KNOTE\_UNLOCKED** – event delivery subsystem

## SYNOPSIS

**#include \<sys/event.h\>**

*int*\

**kqueue\_add\_filteropts**(*int filt*, *struct filterops \*filtops*);

*int*\

**kqueue\_del\_filteropts**(*int filt*);

*int*\

**kqfd\_register**(*int fd*, *struct kevent \*kev*, *struct thread \*td*, *int waitok*);

*void*\

**knote\_fdclose**(*struct thread \*td*, *int fd*);

*void*\

**knlist\_init**(*struct knlist \*knl*, *void \*lock*, *void \*kl\_lockvoid \**, *void \*kl\_unlockvoid \**, *int \*kl\_lockedvoid \**);

*void*\

**knlist\_init\_mtx**(*struct knlist \*knl*, *struct mtx \*lock*);

*void*\

**knlist\_add**(*struct knlist \*knl*, *struct knote \*kn*, *int islocked*);

*void*\

**knlist\_remove**(*struct knlist \*knl*, *struct knote \*kn*, *int islocked*);

*int*\

**knlist\_empty**(*struct knlist \*knl*);

*void*\

**knlist\_clear**(*struct knlist \*knl*, *int islocked*);

*void*\

**knlist\_delete**(*struct knlist \*knl*, *struct thread \*td*, *int islocked*);

*void*\

**knlist\_destroy**(*struct knlist \*knl*);

*void*\

**KNOTE\_LOCKED**(*struct knlist \*knl*, *long hint*);

*void*\

**KNOTE\_UNLOCKED**(*struct knlist \*knl*, *long hint*);

## DESCRIPTION

The functions **kqueue\_add\_filteropts**() and **kqueue\_del\_filteropts**() allow for the addition and removal of a filter type. The filter is statically defined by the EVFILT\_\* macros. The function **kqueue\_add\_filteropts**() will make *filt* available. The *struct filterops* has the following members:

- *f\_isfd*

  If *f\_isfd* is set, *ident* in *struct kevent* is taken to be a file descriptor. In this case, the *knote* passed into *f\_attach* will have the *kn\_fp* member initialized to the *struct file \** that represents the file descriptor.

- *f\_attach*

  The *f\_attach* function will be called when attaching a *knote* to the object. The method should call **knlist\_add**() to add the *knote* to the list that was initialized with **knlist\_init**(). The call to **knlist\_add**() is only necessary if the object can have multiple *knotes* associated with it. If there is no *knlist* to call **knlist\_add**() with, the function *f\_attach* must clear the KN\_DETACHED bit of *kn\_status* in the *knote*. The function shall return 0 on success, or appropriate error for the failure, such as when the object is being destroyed, or does not exist. During *f\_attach*, it is valid to change the *kn\_fop* pointer to a different pointer. This will change the *f\_event* and *f\_detach* functions called when processing the *knote*.

- *f\_detach*

  The *f\_detach* function will be called to detach the *knote* if the *knote* has not already been detached by a call to **knlist\_remove**() or **knlist\_delete**(). The list *lock* will not be held when this function is called.

- *f\_event*

  The *f\_event* function will be called to update the status of the *knote*. If the function returns 0, it will be assumed that the object is not ready (or no longer ready) to be woken up. The *hint* argument will be 0 when scanning *knotes* to see which are triggered. Otherwise, the *hint* argument will be the value passed to either KNOTE\_LOCKED or KNOTE\_UNLOCKED. The *kn\_data* value should be updated as necessary to reflect the current value, such as number of bytes available for reading, or buffer space available for writing.

  Locks *must* *not* be acquired in *f\_event*. If a lock is required in *f\_event*, it must be obtained in the *kl\_lock* function of the *knlist* that the *knote* was added to.

- *f\_copy*

  The *f\_copy* function is called to copy notes when the process forks. When NULL, the current node is not duplicated to the child process. Filter might set f\_copy to **knote\_triv\_copy**() if there is no additional handling required, besides shallow copying of the knote itself.

The function **kqfd\_register**() will register the *kevent* on the kqueue file descriptor *fd*. If it is safe to sleep, *waitok* should be set.

The function **knote\_fdclose**() is used to delete all *knotes* associated with *fd*. Once returned, there will no longer be any *knotes* associated with the *fd*. The *knotes* removed will never be returned from a [kevent(2)](/kevent/2.md) call, so if userland uses the *knote* to track resources, they will be leaked. The **FILEDESC\_LOCK**() lock must be held over the call to **knote\_fdclose**() so that file descriptors cannot be added or removed.

The **knlist\_\***() family of functions are for managing *knotes* associated with an object. A *knlist* is not required, but is commonly used. If used, the *knlist* must be initialized with either **knlist\_init**() or **knlist\_init\_mtx**(). The *knlist* structure may be embedded into the object structure. The *lock* will be held over *f\_event* calls.

For the **knlist\_init**() function, if *lock* is NULL, a shared global lock will be used and the remaining arguments must be NULL. The function pointers *kl\_lock*, *kl\_unlock*, and *kl\_locked* will be used to manipulate the argument *lock*. If any of the function pointers are NULL, a function operating on MTX\_DEF style [mutex(9)](/mutex/9.md) locks will be used instead.

The function **knlist\_init\_mtx**() may be used to initialize a *knlist* when *lock* is a MTX\_DEF style [mutex(9)](/mutex/9.md) lock.

The function **knlist\_empty**() returns true when there are no *knotes* on the list. The function requires that the *lock* be held when called.

The function **knlist\_clear**() removes all *knotes* from the list. The *islocked* argument declares if the *lock* has been acquired. All *knotes* will have EV\_ONESHOT set so that the *knote* will be returned and removed during the next scan. The *f\_detach* function will be called when the *knote* is deleted during the next scan.

The function **knlist\_delete**() removes and deletes all *knotes* on the list. The function *f\_detach* will not be called, and the *knote* will not be returned on the next scan. Using this function could leak userland resources if a process uses the *knote* to track resources.

Both the **knlist\_clear**() and **knlist\_delete**() functions may sleep. They also may release the *lock* to wait for other *knotes* to drain.

The **knlist\_destroy**() function is used to destroy a *knlist*. There must be no *knotes* associated with the *knlist* (**knlist\_empty**() returns true) and no more *knotes* may be attached to the object. A *knlist* may be emptied by calling **knlist\_clear**() or **knlist\_delete**().

The macros **KNOTE\_LOCKED**() and **KNOTE\_UNLOCKED**() are used to notify *knotes* about events associated with the object. It will iterate over all *knotes* on the list calling the *f\_event* function associated with the *knote*. The macro **KNOTE\_LOCKED**() must be used if the lock associated with the *knl* is held. The function **KNOTE\_UNLOCKED**() will acquire the lock before iterating over the list of *knotes*.

## RETURN VALUES

The function **kqueue\_add\_filteropts**() will return zero on success, EINVAL in the case of an invalid *filt*, or EEXIST if the filter has already been installed.

The function **kqueue\_del\_filteropts**() will return zero on success, EINVAL in the case of an invalid *filt*, or EBUSY if the filter is still in use.

The function **kqfd\_register**() will return zero on success, EBADF if the file descriptor is not a kqueue, or any of the possible values returned by [kevent(2)](/kevent/2.md).

## SEE ALSO

[kevent(2)](/kevent/2.md), [kqueue(2)](/kqueue/2.md)

## AUTHORS

This manual page was written by John-Mark Gurney ⟨*jmg@FreeBSD.org*⟩.
