.\" Generated by scdoc 1.11.4 .\" Complete documentation for this program is not available as a GNU info page .ie \n(.g .ds Aq \(aq .el .ds Aq ' .nh .ad l .\" Begin generated content: .TH "libucontext" "3" "2025-11-18" .PP .SH NAME .PP libucontext - a library for userspace context swapping .PP .SH SYNOPSIS .PP \fB#include \fR .PP .nf .RS 4 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; .fi .RE .PP \fBint libucontext_getcontext(libucontext_ucontext_t\fR *\fIucp\fR\fB);\fR .PP \fBint libucontext_setcontext(const libucontext_ucontext_t\fR *\fIucp\fR\fB);\fR .PP \fBvoid libucontext_makecontext(libucontext_ucontext_t\fR *\fIucp\fR\fB, void\fR \fI(*func)()\fR\fB, int\fR \fIargc\fR\fB,\fR \fI.\&.\&.\&\fR\fB);\fR .PP \fBint libucontext_swapcontext(libucontext_ucontext_t\fR *\fIoucp\fR\fB, const libucontext_ucontext_t\fR *\fIucp\fR\fB);\fR .PP .SH DESCRIPTION .PP The \fBlibucontext\fR library provides an implementation of the SysV ucontext functions.\& These are traditionally used to implement user-space context swapping.\& This is achieved by using the \fBlibucontext_getcontext\fR, \fBlibucontext_setcontext\fR, \fBlibucontext_makecontext\fR and \fBlibucontext_swapcontext\fR functions as appropriate.\& .PP The \fBlibucontext_getcontext\fR function initializes a structure pointed to by \fIucp\fR with the current user context.\& .PP The \fBlibucontext_setcontext\fR function sets the current user context to the structure pointed to by \fIucp\fR.\& It discards the current user context.\& .PP The \fBlibucontext_swapcontext\fR function saves the current user context in a structure pointed to by \fIoucp\fR and then sets the current user context to the new context in a structure pointed to by \fIucp\fR.\& .PP The \fBlibucontext_makecontext\fR function modifies a user context in a structure pointed to by \fIucp\fR to run a function pointed to by \fIfunc\fR and sets up an argument list of \fIargc\fR values.\& .PP .SH CAVEATS .PP In SysV, the ucontext functions save and restore signal masks.\& The \fBlibucontext\fR library, however, does not.\& In practice, this does not usually matter, as users of these functions rarely change the signal mask between contexts.\& .PP Other implementations may or may not save and restore additional processor registers that this implementation does not.\& The \fBlibucontext\fR library only saves and restores the general purpose registers.\& In practice, this has proven sufficient.\& .PP .SH EXAMPLE .PP A practical example showing cooperative multithreading.\& This program is intended for illustrative purpose only and has been written in a way favoring simplicity over performance and robustness: .PP .nf .RS 4 #include #include #include #include #include #include #include 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; } .fi .RE .PP .SH AUTHORS .PP Ariadne Conill .PP