libucontext(3)
π¦ libucontext(3) β Library Functions Manual π¦
okay so bestie, this is libucontext(3) from the Library Functions Manual, and it is literally the userspace context-swapping cheat sheet. no cap, it's giving low-level but make it cute. π
β¨
πΈ NAME πΈ
libucontext β a library for userspace context swapping. that's the whole vibe. π«Ά
β¨ SYNOPSIS β¨
here's the include and the structs, bestie β copy these exactly, okay?
#include <libucontext/libucontext.h>
typedef struct {
/* depends on target architecture */
} libucontext_mcontext_t;
typedef struct {
void *ss_sp;
int ss_flags;
size_t ss_size;
} libucontext_stack_t;
typedef struct libucontext_ucontext {
unsigned int uc_flags;
struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack;
libucontext_mcontext_t uc_mcontext;
} libucontext_ucontext_t;
and the functions go like this:
int libucontext_getcontext(libucontext_ucontext_t *ucp);
int libucontext_setcontext(const libucontext_ucontext_t *ucp);
void libucontext_makecontext(libucontext_ucontext_t *ucp, void
(*func)(), int argc, ...);
int libucontext_swapcontext(libucontext_ucontext_t *oucp, const
libucontext_ucontext_t *ucp);
π DESCRIPTION π
so what is this library actually doing? libucontext provides an implementation of the SysV ucontext functions. those are traditionally used to implement user-space context swapping. iconic behavior, honestly.
you make that happen by using libucontext_getcontext, libucontext_setcontext, libucontext_makecontext, and libucontext_swapcontext as appropriate. yes bestie, all four, and yes they slay.
libucontext_getcontextβ initializes a structure pointed to by ucp with the current user context. β¨libucontext_setcontextβ sets the current user context to the structure pointed to by ucp. it discards the current user context, so yeah, that context is gone-gone. πlibucontext_swapcontextβ saves the current user context in a structure pointed to by oucp, then sets the current user context to the new context in a structure pointed to by ucp. very main character energy. πlibucontext_makecontextβ modifies a user context in a structure pointed to by ucp to run a function pointed to by func, and sets up an argument list ofargcvalues. cute little function-launcher setup. π
π¨ CAVEATS π¨
okay, important stuff, bestie β read this part fr fr.
In SysV, theucontextfunctions save and restore signal masks. Thelibucontextlibrary, however, does not. In practice, this does not usually matter, as users of these functions rarely change the signal mask between contexts. π«Ά
also:
Other implementations may or may not save and restore additional processor registers that this implementation does not. The libucontext library only saves and restores the general purpose registers. In practice, this has proven sufficient. π
so like, don't expect it to save every single little register, because it doesn't. it's still sufficient in practice, and that's the tea. π
π EXAMPLE π
here's a practical example showing cooperative multithreading. it is intended for illustrative purpose only and has been written in a way favoring simplicity over performance and robustness:
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libucontext/libucontext.h>
libucontext_ucontext_t mainctx = {};
libucontext_ucontext_t *curthr = &mainctx;
libucontext_ucontext_t *threads = NULL;
size_t thrcount = 0;
void
yieldto(libucontext_ucontext_t *target)
{
libucontext_ucontext_t *oldthr = curthr;
curthr = target;
libucontext_swapcontext(oldthr, curthr);
}
void
yield(void)
{
libucontext_ucontext_t *newthr;
/* we set uc_flags to non-zero to signal thread completion. */
do
newthr = &threads[random() % thrcount];
while (newthr == curthr || newthr->uc_flags);
srandom(time(NULL));
yieldto(newthr);
}
void
worker(size_t multiple)
{
size_t accum = 1;
for (size_t i = 0; i < 10; i++)
{
accum += (multiple * i);
printf("[%p] accumulated %zun", curthr, accum);
yield();
}
/* mark thread as completed, so we don't return here */
curthr->uc_flags = 1;
}
void
create(size_t multiple)
{
libucontext_ucontext_t *cursor;
thrcount += 1;
threads = realloc(threads, sizeof(*threads) * thrcount);
cursor = &threads[thrcount - 1];
memset(cursor, '0', sizeof *cursor);
/* initialize the new thread's values to our current context */
libucontext_getcontext(cursor);
/* set up uc_link */
cursor->uc_link = thrcount > 1 ? &threads[thrcount - 2] : &mainctx;
/* set up a stack */
cursor->uc_stack.ss_size = 8192;
cursor->uc_stack.ss_sp = calloc(1, cursor->uc_stack.ss_size);
/* set up the function call */
libucontext_makecontext(cursor, worker, 1, multiple);
}
int
main(int argc, const char *argv[])
{
srandom(time(NULL));
libucontext_getcontext(&mainctx);
for (size_t i = 1; i < 4; i++)
create(i);
/* start the threads off by yielding to the last one */
yieldto(&threads[thrcount - 1]);
return EXIT_SUCCESS;
}
π AUTHORS π
Ariadne Conill <ariadne@dereferenced.org> β iconic author behavior, we love to see it. π«Άβ¨
and that's the whole page, bestie! this was libucontext(3) from the Library Functions Manual, dated 2026-05-10. mwah, periodt. ππ
π¦ where this page comes from
- alpine 3.24: libucontext-doc 1.5.1-r0 Β· ISC
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms