setcontext

setcontext

setcontext is one of a family of C library functions (the others being getcontext, makecontext and swapcontext) used for context control. The setcontext family allows the implementation in C of advanced control flow patterns such as iterators, fibers, and coroutines. They may be viewed as an advanced version of setjmp/longjmp; whereas the latter allows only a single non-local jump up the stack, setcontext allows the creation of multiple cooperative threads of control, each with its own stack.

Contents

Specification

setcontext is specified in POSIX.1-2001 and the Single Unix Specification, version 2, but not all Unix-like operating systems provide them. The functions and associated types are defined in the ucontext.h system header file. This includes the ucontext_t type, with which all four functions operate:

typedef struct ucontext {
        struct ucontext *uc_link;
        sigset_t         uc_sigmask;
        stack_t          uc_stack;
        mcontext_t       uc_mcontext;
        ...
} ucontext_t;

uc_link points to the context which will be resumed when the current context exits, if the context was created with makecontext (a secondary context). uc_sigmask is used to store the set of signals blocked in the context, and uc_stack is the stack used by the context. uc_mcontext stores execution state, including all registers and CPU flags, the instruction pointer, and the stack pointer; mcontext_t is an opaque type.

The functions are:

  • int setcontext(const ucontext_t *ucp)
This function transfers control to the context in ucp. Execution continues from the point at which the context was stored in ucp. setcontext does not return.
  • int getcontext(ucontext_t *ucp)
Saves current context into ucp. This function returns in two possible cases: after the initial call, or when a thread switches to the context in ucp via setcontext or swapcontext. The getcontext function does not provide a return value to distinguish the cases (its return value is used solely to signal error), so the programmer must use an explicit flag variable, which must not be a register variable and must be declared volatile to avoid constant propagation or other compiler optimisations.
  • void makecontext(ucontext_t *ucp, void *func(), int argc, ...)
The makecontext function sets up an alternate thread of control in ucp, which has previously been initialised using getcontext. The ucp.uc_stack member should be pointed to an appropriately sized stack; the constant SIGSTKSZ is commonly used. When ucp is jumped to using setcontext or swapcontext, execution will begin at the entry point to the function pointed to by func, with argc arguments as specified. When func terminates, control is returned to ucp.uc_link.
  • int swapcontext(ucontext_t *oucp, ucontext_t *ucp)
Transfers control to ucp and saves the current execution state into oucp.

Example

The example below demonstrates an iterator using setcontext. This form of example is unlikely to be widely seen; as setcontext is somewhat cumbersome to use effectively, programmers writing cooperatively multitasked applications often choose to use a wrapper library such as GNU Portable Threads. Most code using setcontext appears in such wrapper libraries, in high-level programming language implementations, or in emulators.

#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
 
/* This is the iterator function. It is entered on the first call to
 * swapcontext, and loops from 0 to 9. Each value is saved in i_from_iterator,
 * and then swapcontext used to return to the main loop.  The main loop prints
 * the value and calls swapcontext to swap back into the function. When the end
 * of the loop is reached, the function exits, and execution switches to the
 * context pointed to by main_context1. */
void loop(
    ucontext_t *loop_context,
    ucontext_t *other_context,
    int *i_from_iterator)
{
    int i;
 
    for (i=0; i < 10; ++i) {
        /* Write the loop counter into the iterator return location. */
        *i_from_iterator = i;
 
        /* Save the loop context (this point in the code) into ''loop_context'',
         * and switch to other_context. */
        swapcontext(loop_context, other_context);
    }
 
    /* The function falls through to the calling context with an implicit
     * ''setcontext(&loop_context->uc_link);'' */
} 
 
int main(void)
{
    /* The three contexts:
     *    (1) main_context1 : The point in main to which loop will return.
     *    (2) main_context2 : The point in main to which control from loop will
     *                        flow by switching contexts.
     *    (3) loop_context  : The point in loop to which control from main will
     *                        flow by switching contexts. */
    ucontext_t main_context1, main_context2, loop_context;
 
    /* The stack for the iterator function. */
    char iterator_stack[SIGSTKSZ];
 
    /* Flag indicating that the iterator has completed. */
    volatile int iterator_finished;
 
    /* The iterator return value. */
    volatile int i_from_iterator;
 
    /* Initialise the iterator context. uc_link points to main_context1, the
     * point to return to when the iterator finishes. */
    loop_context.uc_link          = &main_context1;
    loop_context.uc_stack.ss_sp   = iterator_stack;
    loop_context.uc_stack.ss_size = sizeof(iterator_stack);
    getcontext(&loop_context);
 
    /* Fill in loop_context so that it makes swapcontext start loop. The
     * (void (*)(void)) typecast is to avoid a compiler warning but it is
     * not relevant to the behaviour of the function. */
    makecontext(&loop_context, (void (*)(void)) loop,
        3, &loop_context, &main_context2, &i_from_iterator);
 
    /* Clear the finished flag. */      
    iterator_finished = 0;
 
    /* Save the current context into main_context1. When loop is finished,
     * control flow will return to this point. */
    getcontext(&main_context1);
 
    if (!iterator_finished) {
        /* Set iterator_finished so that when the previous getcontext is
         * returned to via uc_link, the above if condition is false and the
         * iterator is not restarted. */
        iterator_finished = 1;
 
        while (1) {
            /* Save this point into main_context2 and switch into the iterator.
             * The first call will begin loop.  Subsequent calls will switch to
             * the swapcontext in loop. */
            swapcontext(&main_context2, &loop_context);
            printf("%d\n", i_from_iterator);
        }
    }
 
    return 0;
}

NOTE: this example is not consistent with the manual page or the specification.[1] The function makecontext requires additional parameters to be type int, but the example passes pointers. Thus, the example may fail on 64-bit machines (specifically LP64-architectures, where sizeof(void*) > sizeof(int)). Theoretically these problems can be worked around, but the process for doing so is not portable[citation needed].

For get and set context, a smaller context can be handy:

#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>
 
int main(int argc, const char *argv[]){
        ucontext_t context;
 
        getcontext(&context);
        puts("Hello world");
        sleep(1);
        setcontext(&context);
        return 0;
}

This makes an infinite loop because context holds the program counter.

References

  1. ^ The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition [1]

External links


Wikimedia Foundation. 2010.

Игры ⚽ Нужно сделать НИР?

Look at other dictionaries:

  • Setcontext — is one of a family of C library functions (the others being getcontext, makecontext and swapcontext) used for context control. The setcontext family allows the implementation in C of advanced control flow patterns such as iterators, fibers, and… …   Wikipedia

  • setcontext — одна из библиотечных функций стандарта POSIX (в число других входят getcontext, makecontext и swapcontext), используемая для управления контекстом. Семейство setcontext позволяет реализовать на языке Cи такие паттерны проектирования управления… …   Википедия

  • setjmp.h — C Standard Library Data types Character classification Strings Mathematics File input/output Date/time Localization …   Wikipedia

  • Setjmp.h — Este artículo o sección necesita ser wikificado con un formato acorde a las convenciones de estilo. Por favor, edítalo para que las cumpla. Mientras tanto, no elimines este aviso puesto el 8 de junio de 2011. También puedes ayudar wikificando… …   Wikipedia Español

  • Coroutine — Coroutines are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations. Coroutines are well suited for implementing more familiar program components such as …   Wikipedia

  • Fiber (computer science) — In computer science, a fiber is a particularly lightweight thread of execution.Like threads, fibers share address space; where a distinction exists, it is that fibers use co operative multitasking while threads use pre emptive multitasking.… …   Wikipedia

  • Fibre (informatique) — Pour les articles homonymes, voir Fibre (homonymie). En Informatique, une fibre (fiber en anglais) est un thread d exécution particulièrement léger. Comme les threads, les fibres partagent la même mémoire virtuelle. Toutefois, les fibres… …   Wikipédia en Français

  • Continuation — For other uses, see Continuation (disambiguation). In computer science and programming, a continuation is an abstract representation of the control state of a computer program. A continuation reifies the program control state, i.e. the… …   Wikipedia

  • Call stack — In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, control stack, run time stack, or machine stack, and… …   Wikipedia

  • Continuation — Dieser Artikel wurde aufgrund von inhaltlichen Mängeln auf der Qualitätssicherungsseite der Redaktion Informatik eingetragen. Dies geschieht, um die Qualität der Artikel aus dem Themengebiet Informatik auf ein akzeptables Niveau zu bringen. Hilf… …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”