I took operating systems last year, during which I used user contexts (defined in the header ucontext.h
) to implement a thread scheduler (in which each thread simulated a process) for a project. I'm taking part in a lecture and will talk about user contexts, and it just occurred to me that, despite having done this project last year, I don't really understand what exactly the getcontext
system call actually does.
The man pages for getcontext
states that it
initializes the structure pointed at by ucp to the currently active context."
It also states, for the argument to setcontext
, that if the ucp argument
was obtained by a call of getcontext(), program execution continues as if this call just returned.
Okay, so I understand that.
So here's what I'm confused about. Typically, for the way I learned it, to perform a context switch, one would initialize the ucontext_t
struct and swap/set it as such:
ucontext_t ucp;
ucontext_t oucp;
getcontext(&ucp);
// Initialize the stack_t struct in the ucontext_t struct
ucp.uc_stack.ss_sp = malloc(STACK_SIZE);
ucp.uc_stack.ss_size = STACK_SIZE;
ucp.uc_stack.ss_flags = 0;
ucp.uc_link = /* some other context, or just NULL */;
// Don't block any signals in this context
sigemptyset(&ucp.uc_sigmask);
// Assume that fn is a function that takes 0 arguments and returns void
makecontext(&ucp, fn, 0);
// Perform the context switch. Function 'fn' will be active now
swapcontext(&oucp, &ucp);
// alternatively: setcontext(&ucp);
If I omit getcontext
in smaller programs, nothing interesting happens. In somewhat larger programs in which there is more context switching via user contexts, I get a segmentation fault that is only resolved by adding getcontext
back in.
What exactly does getcontext
do? Why can't I just allocate a ucontext_t
struct, initialize it by initializing the uc_stack
and uc_sigmask
fields, and calling makecontext
without the getcontext
? Is there some necessary initialization that getcontext
performs that makecontext
does not perform?