SWI(9)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1

πŸ’… SWI(9) β€” like, the kernel developer's manual, but make it make sense ✨

okay so bestie, this is SWI(9) from the Kernel Developer's Manual and it's literally all about software interrupt handlers β€” registering them, removing them, scheduling them. no cap, it's giving "the plumbing behind the plumbing" and honestly? iconic. πŸŽ€


🌸 NAME 🌸

swi_add, swi_remove, swi_sched β€” register and schedule software interrupt handlers πŸ¦‹


✨ SYNOPSIS ✨

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

extern struct intr_event *clk_intr_event;

int
swi_add(struct intr_event **eventp, const char *name,
    driver_intr_t handler, void *arg, int pri, enum intr_type flags,
    void **cookiep);

int
swi_remove(void *cookie);

void
swi_sched(void *cookie, int flags);

like, just copy that exactly into your file and you're so valid πŸ’–


πŸ’… DESCRIPTION πŸ’…

so these functions register and schedule software interrupt handlers, periodt. software interrupt handlers get attached to a software interrupt thread, the exact same way hardware interrupt handlers get attached to a hardware interrupt thread. and here's the gag: multiple handlers can be attached to the same thread. πŸ‘‘

the whole point? software interrupt handlers let you queue up less critical processing inside of hardware interrupt handlers so all that work can happen at a later time. main character energy β€” the hardware handler does the quick important bit and the software thread swoops in later, slay. πŸ¦‹

software interrupt threads are different from other kernel threads in that they're treated as an interrupt thread. which means:

  • time spent executing these threads is counted as interrupt time, and
  • they can be run via a lightweight context switch.

ngl that's the whole vibe check right there.

🫢 swi_add() β€” the new-handler maker 🫢

swi_add() adds a new software interrupt handler to a specified interrupt event. let's break it down:

  • eventp β€” an optional pointer to a struct intr_event pointer. if this argument points to an existing event that holds a list of interrupt handlers, your handler gets attached to that event. otherwise a new event is created, and if eventp is not NULL, then the pointer at that address will be modified to point to the newly created event. 😭 that's it, that's the pointer-to-a-pointer lore.
  • name β€” associates a name with this specific handler. this name is appended to the name of the software interrupt thread that this handler is attached to.
  • handler β€” the function that will be executed when the handler is scheduled to run.
  • arg β€” passed in as the only parameter to handler when the function is executed.
  • pri β€” specifies the priority of this interrupt handler relative to other software interrupt handlers. if an interrupt event is created, then this value is used as the vector, and the flags argument is used to specify the attributes of a handler such as INTR_MPSAFE.
  • cookiep β€” points to a void * cookie. this cookie gets set to a value that uniquely identifies this handler, and it's what you use to schedule the handler for execution later on. keep it safe, bestie πŸŽ€

🧚 swi_remove() β€” the cleanup girlie 🧚

swi_remove() tears down an interrupt handler pointed to by the cookie argument. it detaches the interrupt handler from the associated interrupt event and frees its memory. bye bye, no notes, we love a clean exit πŸ’œ

πŸ”₯ swi_sched() β€” the "go now (or not yet)" πŸ”₯

swi_sched() schedules an interrupt handler and its associated thread to run.

  • cookie β€” specifies which software interrupt handler should be scheduled to run.
  • flags β€” specifies how and when the handler should be run, and it's a mask of one or more of these flags:
  • SWI_DELAY β€” specifies that the kernel should mark the specified handler as needing to run, but the kernel should not schedule the software interrupt thread to run. instead, handler will be executed the next time that the software interrupt thread runs after being scheduled by another event. lowkey a "you're on deck, not up to bat" situation πŸ™ˆ
  • SWI_FROMNMI β€” specifies that swi_sched() is called from NMI context and should be careful about used KPIs. on platforms allowing IPI sending from NMI context it immediately wakes clk_intr_event via the IPI, otherwise it works just like SWI_DELAY. πŸ’€ careful with this one.

also: clk_intr_event is a pointer to the struct intr_event used to hang delayed handlers off of the clock interrupt, and is invoked directly by hardclock(9). ⭐


πŸ’– RETURN VALUES πŸ’–

swi_add() and swi_remove() return zero on success and non-zero on failure. that's the whole thing, short and sweet πŸ“


😭 ERRORS 😭

swi_add() 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] β€” the flags argument specifies INTR_ENTROPY.
  • [EINVAL] β€” the eventp argument points to a hardware interrupt thread.
  • [EINVAL] β€” either of the name or handler arguments are NULL.
  • [EINVAL] β€” the INTR_EXCL flag is specified and the interrupt event pointed to by eventp already has at least one handler, or the interrupt event already has an exclusive handler.

πŸ₯Ί swi_remove() will fail if:

  • [EINVAL] β€” a software interrupt handler pointed to by cookie is NULL.
fr fr, check your cookies before you call these. NULL is not the vibe. πŸ’…

🌈 SEE ALSO 🌈

hardclock(9), intr_event(9), taskqueue(9)

go read those next, iykyk πŸ“šβœ¨


πŸ‘‘ HISTORY πŸ‘‘

  • swi_add() and swi_sched() first appeared in FreeBSD 5.0.
  • they replaced the register_swi() function which appeared in FreeBSD 3.0, and the setsoft*() and schedsoft*() functions which date back to at least 4.4BSD.
  • swi_remove() first appeared in FreeBSD 6.1.

a whole glow-up timeline, honestly 🫢πŸ”₯


okay that's the page!! this one came from Debian, dated October 12, 2022, and it's SWI(9) in the Kernel Developer's Manual β€” love that for us, mwah πŸ’‹πŸŒΈ

πŸ“¦ where this page comes from