KCONT(9)

NAME
kcont - continuation-passing framework for deferring execution and for notification of asynchronous events

SYNOPSIS
#include <sys/kcont.h>
struct kc *
kcont(struct kc *, void (*fn) (void *kernel_obj, void *env_arg, int status), void *env_arg, int desired_ipl);
struct kc *
kcont_malloc(int mallocflags, void (*fn) (void *kernel_obj, void *env_arg, int status), void *env_arg, int desired_ipl);
void
kcont_defer(struct kc *kc, void (*fn) (void *kernel_obj, void *env_arg, int status), void *kernel_obj, void *env_arg, int status, int desired_ipl);
void
kcont_defer_malloc(int mallocflags, void (*fn) (void *kernel_obj, void *env_arg, int status), void *kernel_obj, void *env_arg, int status, int desired_ipl);
void
kcont_enqueue(struct kcq *kcont_queue, struct kc* kcont);
void
kcont_run(kcq_t *kcq, void *obj, int status, int curipl);

DESCRIPTION
kcont provides a method of asynchronous notification of kernel events (such as I/O completion events) loosely modelled on the continuation-passing model associated with functional languages such as Scheme. In the context of C and Unix kernels, a continuation can be thought of as a combination of three items:

•   a function pointer, or “callback” function;
•   an argument (or arguments) to that function; and
•   other “environment” state which is passed into the function.

The continuations supported by kcont can be used to defer execution from a high-priority context (such as a hardware-priority interrupt handler) to a lower-priority context (such as a software-interrupt callout queue specifically for executing kcont functions). The kcont mechanism can also be used to deliver notification of asynchronous events, such as I/O completion.

TRADITIONAL I/O COMPLETION NOTIFICATION
The traditional Unix methods for asynchronous notification are ltsleep(9), tsleep(9), and wakeup(9), which assume the operation or I/O request are being issued from process context. Once the I/O operation is actually issued, the requesting process is suspended by issuing a tsleep(9) on the address of the I/O buffer. When the I/O operation completes, the I/O subsystem issues a wakeup(9) call on the address of the I/O buffer. The process is then awakened, rescheduled, and continues execution from the tsleep() function call, eventually returning to the function which requested I/O.

CONTINUATIONS
In contrast, kcont constructs an object called a continuation -- a function representing “the rest of the program to be performed”. Continuations are constructed via the kcont() and kcont_malloc() functions, which use caller-supplied or dynamically-allocated space, respectively. In addition to the continuation-function, argument-object, and environment, the constructor of each continuation specifies an target interrupt priority (IPL) above which the continuation should not be run.

Once constructed, the continuation can be destined for execution in one of two ways. First, kcont_defer() or kcont_defer_malloc() schedule a continuation for execution as soon as interrupt priority falls to or below the target IPL of the continuation. Alternatively, a kcont can be passed by its creator across kernel interfaces which accept kcont objects as methods for notifying the caller (i.e., the kcont creator) on completion of an asynchronous operation.

DATA TYPES

  Deferral Priorities
Arguments shown above with the name desired_ipl are drawn from the following namespace:

KC_IPL_IMMED
    Execute the continuation as soon as possible, without regard to current IPL.

KC_IPL_DEFER_SOFTSERIAL
    Execute the continuation once IPL falls to IPL_SOFTSERIAL or below.

KC_IPL_DEFER_SOFTCLOCK
    Execute the continuation once IPL falls to IPL_SOFTCLOCK or below.

KC_IPL_DEFER_SOFTNET
    Execute the continuation once IPL falls to IPL_SOFTNET or below.

KC_IPL_DEFER_PROCESS
    Defer execution of the continuation to process context.

NOTES
The desired_ipl argument should be interpreted as an upper-bound: the continuation will not be executed before interrupt priority drops to, or below, the requested level. In particular, the current implementation uses NetBSD generic software callouts. On NetBSD ports which lack generic software callouts, all kcont continuations will always be deferred all the way to the context of a “helper” kernel thread.

SEE ALSO
kthread(9), spl(9), tsleep(9), wakeup(9), workqueue(9)

AUTHORS
The kcont interface was designed and implemented by Jonathan Stone. Additional input on the kcont design was provided by Jason Thorpe and Nathan Williams.