Blame manual/setjmp.texi

Packit Service 82fcde
@node Non-Local Exits, Signal Handling, Resource Usage And Limitation, Top
Packit Service 82fcde
@c %MENU% Jumping out of nested function calls
Packit Service 82fcde
@chapter Non-Local Exits
Packit Service 82fcde
@cindex non-local exits
Packit Service 82fcde
@cindex long jumps
Packit Service 82fcde
Packit Service 82fcde
Sometimes when your program detects an unusual situation inside a deeply
Packit Service 82fcde
nested set of function calls, you would like to be able to immediately
Packit Service 82fcde
return to an outer level of control.  This section describes how you can
Packit Service 82fcde
do such @dfn{non-local exits} using the @code{setjmp} and @code{longjmp}
Packit Service 82fcde
functions.
Packit Service 82fcde
Packit Service 82fcde
@menu
Packit Service 82fcde
* Intro: Non-Local Intro.        When and how to use these facilities.
Packit Service 82fcde
* Details: Non-Local Details.    Functions for non-local exits.
Packit Service 82fcde
* Non-Local Exits and Signals::  Portability issues.
Packit Service 82fcde
* System V contexts::            Complete context control a la System V.
Packit Service 82fcde
@end menu
Packit Service 82fcde
Packit Service 82fcde
@node Non-Local Intro, Non-Local Details,  , Non-Local Exits
Packit Service 82fcde
@section Introduction to Non-Local Exits
Packit Service 82fcde
Packit Service 82fcde
As an example of a situation where a non-local exit can be useful,
Packit Service 82fcde
suppose you have an interactive program that has a ``main loop'' that
Packit Service 82fcde
prompts for and executes commands.  Suppose the ``read'' command reads
Packit Service 82fcde
input from a file, doing some lexical analysis and parsing of the input
Packit Service 82fcde
while processing it.  If a low-level input error is detected, it would
Packit Service 82fcde
be useful to be able to return immediately to the ``main loop'' instead
Packit Service 82fcde
of having to make each of the lexical analysis, parsing, and processing
Packit Service 82fcde
phases all have to explicitly deal with error situations initially
Packit Service 82fcde
detected by nested calls.
Packit Service 82fcde
Packit Service 82fcde
(On the other hand, if each of these phases has to do a substantial
Packit Service 82fcde
amount of cleanup when it exits---such as closing files, deallocating
Packit Service 82fcde
buffers or other data structures, and the like---then it can be more
Packit Service 82fcde
appropriate to do a normal return and have each phase do its own
Packit Service 82fcde
cleanup, because a non-local exit would bypass the intervening phases and
Packit Service 82fcde
their associated cleanup code entirely.  Alternatively, you could use a
Packit Service 82fcde
non-local exit but do the cleanup explicitly either before or after
Packit Service 82fcde
returning to the ``main loop''.)
Packit Service 82fcde
Packit Service 82fcde
In some ways, a non-local exit is similar to using the @samp{return}
Packit Service 82fcde
statement to return from a function.  But while @samp{return} abandons
Packit Service 82fcde
only a single function call, transferring control back to the point at
Packit Service 82fcde
which it was called, a non-local exit can potentially abandon many
Packit Service 82fcde
levels of nested function calls.
Packit Service 82fcde
Packit Service 82fcde
You identify return points for non-local exits by calling the function
Packit Service 82fcde
@code{setjmp}.  This function saves information about the execution
Packit Service 82fcde
environment in which the call to @code{setjmp} appears in an object of
Packit Service 82fcde
type @code{jmp_buf}.  Execution of the program continues normally after
Packit Service 82fcde
the call to @code{setjmp}, but if an exit is later made to this return
Packit Service 82fcde
point by calling @code{longjmp} with the corresponding @w{@code{jmp_buf}}
Packit Service 82fcde
object, control is transferred back to the point where @code{setjmp} was
Packit Service 82fcde
called.  The return value from @code{setjmp} is used to distinguish
Packit Service 82fcde
between an ordinary return and a return made by a call to
Packit Service 82fcde
@code{longjmp}, so calls to @code{setjmp} usually appear in an @samp{if}
Packit Service 82fcde
statement.
Packit Service 82fcde
Packit Service 82fcde
Here is how the example program described above might be set up:
Packit Service 82fcde
Packit Service 82fcde
@smallexample
Packit Service 82fcde
@include setjmp.c.texi
Packit Service 82fcde
@end smallexample
Packit Service 82fcde
Packit Service 82fcde
The function @code{abort_to_main_loop} causes an immediate transfer of
Packit Service 82fcde
control back to the main loop of the program, no matter where it is
Packit Service 82fcde
called from.
Packit Service 82fcde
Packit Service 82fcde
The flow of control inside the @code{main} function may appear a little
Packit Service 82fcde
mysterious at first, but it is actually a common idiom with
Packit Service 82fcde
@code{setjmp}.  A normal call to @code{setjmp} returns zero, so the
Packit Service 82fcde
``else'' clause of the conditional is executed.  If
Packit Service 82fcde
@code{abort_to_main_loop} is called somewhere within the execution of
Packit Service 82fcde
@code{do_command}, then it actually appears as if the @emph{same} call
Packit Service 82fcde
to @code{setjmp} in @code{main} were returning a second time with a value
Packit Service 82fcde
of @code{-1}.
Packit Service 82fcde
Packit Service 82fcde
@need 250
Packit Service 82fcde
So, the general pattern for using @code{setjmp} looks something like:
Packit Service 82fcde
Packit Service 82fcde
@smallexample
Packit Service 82fcde
if (setjmp (@var{buffer}))
Packit Service 82fcde
  /* @r{Code to clean up after premature return.} */
Packit Service 82fcde
  @dots{}
Packit Service 82fcde
else
Packit Service 82fcde
  /* @r{Code to be executed normally after setting up the return point.} */
Packit Service 82fcde
  @dots{}
Packit Service 82fcde
@end smallexample
Packit Service 82fcde
Packit Service 82fcde
@node Non-Local Details, Non-Local Exits and Signals, Non-Local Intro, Non-Local Exits
Packit Service 82fcde
@section Details of Non-Local Exits
Packit Service 82fcde
Packit Service 82fcde
Here are the details on the functions and data structures used for
Packit Service 82fcde
performing non-local exits.  These facilities are declared in
Packit Service 82fcde
@file{setjmp.h}.
Packit Service 82fcde
@pindex setjmp.h
Packit Service 82fcde
Packit Service 82fcde
@deftp {Data Type} jmp_buf
Packit Service 82fcde
@standards{ISO, setjmp.h}
Packit Service 82fcde
Objects of type @code{jmp_buf} hold the state information to
Packit Service 82fcde
be restored by a non-local exit.  The contents of a @code{jmp_buf}
Packit Service 82fcde
identify a specific place to return to.
Packit Service 82fcde
@end deftp
Packit Service 82fcde
Packit Service 82fcde
@deftypefn Macro int setjmp (jmp_buf @var{state})
Packit Service 82fcde
@standards{ISO, setjmp.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Packit Service 82fcde
@c _setjmp ok
Packit Service 82fcde
@c  __sigsetjmp(!savemask) ok
Packit Service 82fcde
@c   __sigjmp_save(!savemask) ok, does not call sigprocmask
Packit Service 82fcde
When called normally, @code{setjmp} stores information about the
Packit Service 82fcde
execution state of the program in @var{state} and returns zero.  If
Packit Service 82fcde
@code{longjmp} is later used to perform a non-local exit to this
Packit Service 82fcde
@var{state}, @code{setjmp} returns a nonzero value.
Packit Service 82fcde
@end deftypefn
Packit Service 82fcde
Packit Service 82fcde
@deftypefun void longjmp (jmp_buf @var{state}, int @var{value})
Packit Service 82fcde
@standards{ISO, setjmp.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @asucorrupt{} @asulock{/hurd}}@acunsafe{@acucorrupt{} @aculock{/hurd}}}
Packit Service 82fcde
@c __libc_siglongjmp @ascuplugin @asucorrupt @asulock/hurd @acucorrupt @aculock/hurd
Packit Service 82fcde
@c  _longjmp_unwind @ascuplugin @asucorrupt @acucorrupt
Packit Service 82fcde
@c   __pthread_cleanup_upto @ascuplugin @asucorrupt @acucorrupt
Packit Service 82fcde
@c     plugins may be unsafe themselves, but even if they weren't, this
Packit Service 82fcde
@c     function isn't robust WRT async signals and cancellation:
Packit Service 82fcde
@c     cleanups aren't taken off the stack right away, only after all
Packit Service 82fcde
@c     cleanups have been run.  This means that async-cancelling
Packit Service 82fcde
@c     longjmp, or interrupting longjmp with an async signal handler
Packit Service 82fcde
@c     that calls longjmp may run the same cleanups multiple times.
Packit Service 82fcde
@c    _JMPBUF_UNWINDS_ADJ ok
Packit Service 82fcde
@c    *cleanup_buf->__routine @ascuplugin
Packit Service 82fcde
@c  sigprocmask(SIG_SETMASK) dup @asulock/hurd @aculock/hurd
Packit Service 82fcde
@c  __longjmp ok
Packit Service 82fcde
This function restores current execution to the state saved in
Packit Service 82fcde
@var{state}, and continues execution from the call to @code{setjmp} that
Packit Service 82fcde
established that return point.  Returning from @code{setjmp} by means of
Packit Service 82fcde
@code{longjmp} returns the @var{value} argument that was passed to
Packit Service 82fcde
@code{longjmp}, rather than @code{0}.  (But if @var{value} is given as
Packit Service 82fcde
@code{0}, @code{setjmp} returns @code{1}).@refill
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
There are a lot of obscure but important restrictions on the use of
Packit Service 82fcde
@code{setjmp} and @code{longjmp}.  Most of these restrictions are
Packit Service 82fcde
present because non-local exits require a fair amount of magic on the
Packit Service 82fcde
part of the C compiler and can interact with other parts of the language
Packit Service 82fcde
in strange ways.
Packit Service 82fcde
Packit Service 82fcde
The @code{setjmp} function is actually a macro without an actual
Packit Service 82fcde
function definition, so you shouldn't try to @samp{#undef} it or take
Packit Service 82fcde
its address.  In addition, calls to @code{setjmp} are safe in only the
Packit Service 82fcde
following contexts:
Packit Service 82fcde
Packit Service 82fcde
@itemize @bullet
Packit Service 82fcde
@item
Packit Service 82fcde
As the test expression of a selection or iteration
Packit Service 82fcde
statement (such as @samp{if}, @samp{switch}, or @samp{while}).
Packit Service 82fcde
Packit Service 82fcde
@item
Packit Service 82fcde
As one operand of an equality or comparison operator that appears as the
Packit Service 82fcde
test expression of a selection or iteration statement.  The other
Packit Service 82fcde
operand must be an integer constant expression.
Packit Service 82fcde
Packit Service 82fcde
@item
Packit Service 82fcde
As the operand of a unary @samp{!} operator, that appears as the
Packit Service 82fcde
test expression of a selection or iteration statement.
Packit Service 82fcde
Packit Service 82fcde
@item
Packit Service 82fcde
By itself as an expression statement.
Packit Service 82fcde
@end itemize
Packit Service 82fcde
Packit Service 82fcde
Return points are valid only during the dynamic extent of the function
Packit Service 82fcde
that called @code{setjmp} to establish them.  If you @code{longjmp} to
Packit Service 82fcde
a return point that was established in a function that has already
Packit Service 82fcde
returned, unpredictable and disastrous things are likely to happen.
Packit Service 82fcde
Packit Service 82fcde
You should use a nonzero @var{value} argument to @code{longjmp}.  While
Packit Service 82fcde
@code{longjmp} refuses to pass back a zero argument as the return value
Packit Service 82fcde
from @code{setjmp}, this is intended as a safety net against accidental
Packit Service 82fcde
misuse and is not really good programming style.
Packit Service 82fcde
Packit Service 82fcde
When you perform a non-local exit, accessible objects generally retain
Packit Service 82fcde
whatever values they had at the time @code{longjmp} was called.  The
Packit Service 82fcde
exception is that the values of automatic variables local to the
Packit Service 82fcde
function containing the @code{setjmp} call that have been changed since
Packit Service 82fcde
the call to @code{setjmp} are indeterminate, unless you have declared
Packit Service 82fcde
them @code{volatile}.
Packit Service 82fcde
Packit Service 82fcde
@node Non-Local Exits and Signals, System V contexts, Non-Local Details, Non-Local Exits
Packit Service 82fcde
@section Non-Local Exits and Signals
Packit Service 82fcde
Packit Service 82fcde
In BSD Unix systems, @code{setjmp} and @code{longjmp} also save and
Packit Service 82fcde
restore the set of blocked signals; see @ref{Blocking Signals}.  However,
Packit Service 82fcde
the POSIX.1 standard requires @code{setjmp} and @code{longjmp} not to
Packit Service 82fcde
change the set of blocked signals, and provides an additional pair of
Packit Service 82fcde
functions (@code{sigsetjmp} and @code{siglongjmp}) to get the BSD
Packit Service 82fcde
behavior.
Packit Service 82fcde
Packit Service 82fcde
The behavior of @code{setjmp} and @code{longjmp} in @theglibc{} is
Packit Service 82fcde
controlled by feature test macros; see @ref{Feature Test Macros}.  The
Packit Service 82fcde
default in @theglibc{} is the POSIX.1 behavior rather than the BSD
Packit Service 82fcde
behavior.
Packit Service 82fcde
Packit Service 82fcde
The facilities in this section are declared in the header file
Packit Service 82fcde
@file{setjmp.h}.
Packit Service 82fcde
@pindex setjmp.h
Packit Service 82fcde
Packit Service 82fcde
@deftp {Data Type} sigjmp_buf
Packit Service 82fcde
@standards{POSIX.1, setjmp.h}
Packit Service 82fcde
This is similar to @code{jmp_buf}, except that it can also store state
Packit Service 82fcde
information about the set of blocked signals.
Packit Service 82fcde
@end deftp
Packit Service 82fcde
Packit Service 82fcde
@deftypefun int sigsetjmp (sigjmp_buf @var{state}, int @var{savesigs})
Packit Service 82fcde
@standards{POSIX.1, setjmp.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}}
Packit Service 82fcde
@c sigsetjmp @asulock/hurd @aculock/hurd
Packit Service 82fcde
@c  __sigsetjmp(savemask) @asulock/hurd @aculock/hurd
Packit Service 82fcde
@c   __sigjmp_save(savemask) @asulock/hurd @aculock/hurd
Packit Service 82fcde
@c    sigprocmask(SIG_BLOCK probe) dup @asulock/hurd @aculock/hurd
Packit Service 82fcde
This is similar to @code{setjmp}.  If @var{savesigs} is nonzero, the set
Packit Service 82fcde
of blocked signals is saved in @var{state} and will be restored if a
Packit Service 82fcde
@code{siglongjmp} is later performed with this @var{state}.
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
@deftypefun void siglongjmp (sigjmp_buf @var{state}, int @var{value})
Packit Service 82fcde
@standards{POSIX.1, setjmp.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @asucorrupt{} @asulock{/hurd}}@acunsafe{@acucorrupt{} @aculock{/hurd}}}
Packit Service 82fcde
@c Alias to longjmp.
Packit Service 82fcde
This is similar to @code{longjmp} except for the type of its @var{state}
Packit Service 82fcde
argument.  If the @code{sigsetjmp} call that set this @var{state} used a
Packit Service 82fcde
nonzero @var{savesigs} flag, @code{siglongjmp} also restores the set of
Packit Service 82fcde
blocked signals.
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
@node System V contexts,, Non-Local Exits and Signals, Non-Local Exits
Packit Service 82fcde
@section Complete Context Control
Packit Service 82fcde
Packit Service 82fcde
The Unix standard provides one more set of functions to control the
Packit Service 82fcde
execution path and these functions are more powerful than those
Packit Service 82fcde
discussed in this chapter so far.  These functions were part of the
Packit Service 82fcde
original @w{System V} API and by this route were added to the Unix
Packit Service 82fcde
API.  Besides on branded Unix implementations these interfaces are not
Packit Service 82fcde
widely available.  Not all platforms and/or architectures @theglibc{}
Packit Service 82fcde
is available on provide this interface.  Use @file{configure} to
Packit Service 82fcde
detect the availability.
Packit Service 82fcde
Packit Service 82fcde
Similar to the @code{jmp_buf} and @code{sigjmp_buf} types used for the
Packit Service 82fcde
variables to contain the state of the @code{longjmp} functions the
Packit Service 82fcde
interfaces of interest here have an appropriate type as well.  Objects
Packit Service 82fcde
of this type are normally much larger since more information is
Packit Service 82fcde
contained.  The type is also used in a few more places as we will see.
Packit Service 82fcde
The types and functions described in this section are all defined and
Packit Service 82fcde
declared respectively in the @file{ucontext.h} header file.
Packit Service 82fcde
Packit Service 82fcde
@deftp {Data Type} ucontext_t
Packit Service 82fcde
@standards{SVID, ucontext.h}
Packit Service 82fcde
Packit Service 82fcde
The @code{ucontext_t} type is defined as a structure with at least the
Packit Service 82fcde
following elements:
Packit Service 82fcde
Packit Service 82fcde
@table @code
Packit Service 82fcde
@item ucontext_t *uc_link
Packit Service 82fcde
This is a pointer to the next context structure which is used if the
Packit Service 82fcde
context described in the current structure returns.
Packit Service 82fcde
Packit Service 82fcde
@item sigset_t uc_sigmask
Packit Service 82fcde
Set of signals which are blocked when this context is used.
Packit Service 82fcde
Packit Service 82fcde
@item stack_t uc_stack
Packit Service 82fcde
Stack used for this context.  The value need not be (and normally is
Packit Service 82fcde
not) the stack pointer.  @xref{Signal Stack}.
Packit Service 82fcde
Packit Service 82fcde
@item mcontext_t uc_mcontext
Packit Service 82fcde
This element contains the actual state of the process.  The
Packit Service 82fcde
@code{mcontext_t} type is also defined in this header but the definition
Packit Service 82fcde
should be treated as opaque.  Any use of knowledge of the type makes
Packit Service 82fcde
applications less portable.
Packit Service 82fcde
Packit Service 82fcde
@end table
Packit Service 82fcde
@end deftp
Packit Service 82fcde
Packit Service 82fcde
Objects of this type have to be created by the user.  The initialization
Packit Service 82fcde
and modification happens through one of the following functions:
Packit Service 82fcde
Packit Service 82fcde
@deftypefun int getcontext (ucontext_t *@var{ucp})
Packit Service 82fcde
@standards{SVID, ucontext.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@assafe{}@acsafe{}}
Packit Service 82fcde
@c Linux-only implementations in assembly, including sigprocmask
Packit Service 82fcde
@c syscall.  A few cases call the sigprocmask function, but that's safe
Packit Service 82fcde
@c too.  The ppc case is implemented in terms of a swapcontext syscall.
Packit Service 82fcde
The @code{getcontext} function initializes the variable pointed to by
Packit Service 82fcde
@var{ucp} with the context of the calling thread.  The context contains
Packit Service 82fcde
the content of the registers, the signal mask, and the current stack.
Packit Service 82fcde
Executing the contents would start at the point where the
Packit Service 82fcde
@code{getcontext} call just returned.
Packit Service 82fcde
Packit Service 82fcde
@strong{Compatibility Note:} Depending on the operating system,
Packit Service 82fcde
information about the current context's stack may be in the
Packit Service 82fcde
@code{uc_stack} field of @var{ucp}, or it may instead be in
Packit Service 82fcde
architecture-specific subfields of the @code{uc_mcontext} field.
Packit Service 82fcde
Packit Service 82fcde
The function returns @code{0} if successful.  Otherwise it returns
Packit Service 82fcde
@code{-1} and sets @var{errno} accordingly.
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
The @code{getcontext} function is similar to @code{setjmp} but it does
Packit Service 82fcde
not provide an indication of whether @code{getcontext} is returning for
Packit Service 82fcde
the first time or whether an initialized context has just been restored.
Packit Service 82fcde
If this is necessary the user has to determine this herself.  This must
Packit Service 82fcde
be done carefully since the context contains registers which might contain
Packit Service 82fcde
register variables.  This is a good situation to define variables with
Packit Service 82fcde
@code{volatile}.
Packit Service 82fcde
Packit Service 82fcde
Once the context variable is initialized it can be used as is or it can
Packit Service 82fcde
be modified using the @code{makecontext} function.  The latter is normally
Packit Service 82fcde
done when implementing co-routines or similar constructs.
Packit Service 82fcde
Packit Service 82fcde
@deftypefun void makecontext (ucontext_t *@var{ucp}, void (*@var{func}) (void), int @var{argc}, @dots{})
Packit Service 82fcde
@standards{SVID, ucontext.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@assafe{}@acsafe{}}
Packit Service 82fcde
@c Linux-only implementations mostly in assembly, nothing unsafe.
Packit Service 82fcde
Packit Service 82fcde
The @var{ucp} parameter passed to @code{makecontext} shall be
Packit Service 82fcde
initialized by a call to @code{getcontext}.  The context will be
Packit Service 82fcde
modified in a way such that if the context is resumed it will start by
Packit Service 82fcde
calling the function @code{func} which gets @var{argc} integer arguments
Packit Service 82fcde
passed.  The integer arguments which are to be passed should follow the
Packit Service 82fcde
@var{argc} parameter in the call to @code{makecontext}.
Packit Service 82fcde
Packit Service 82fcde
Before the call to this function the @code{uc_stack} and @code{uc_link}
Packit Service 82fcde
element of the @var{ucp} structure should be initialized.  The
Packit Service 82fcde
@code{uc_stack} element describes the stack which is used for this
Packit Service 82fcde
context.  No two contexts which are used at the same time should use the
Packit Service 82fcde
same memory region for a stack.
Packit Service 82fcde
Packit Service 82fcde
The @code{uc_link} element of the object pointed to by @var{ucp} should
Packit Service 82fcde
be a pointer to the context to be executed when the function @var{func}
Packit Service 82fcde
returns or it should be a null pointer.  See @code{setcontext} for more
Packit Service 82fcde
information about the exact use.
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
While allocating the memory for the stack one has to be careful.  Most
Packit Service 82fcde
modern processors keep track of whether a certain memory region is
Packit Service 82fcde
allowed to contain code which is executed or not.  Data segments and
Packit Service 82fcde
heap memory are normally not tagged to allow this.  The result is that
Packit Service 82fcde
programs would fail.  Examples for such code include the calling
Packit Service 82fcde
sequences the GNU C compiler generates for calls to nested functions.
Packit Service 82fcde
Safe ways to allocate stacks correctly include using memory on the
Packit Service 82fcde
original thread's stack or explicitly allocating memory tagged for
Packit Service 82fcde
execution using (@pxref{Memory-mapped I/O}).
Packit Service 82fcde
Packit Service 82fcde
@strong{Compatibility note}: The current Unix standard is very imprecise
Packit Service 82fcde
about the way the stack is allocated.  All implementations seem to agree
Packit Service 82fcde
that the @code{uc_stack} element must be used but the values stored in
Packit Service 82fcde
the elements of the @code{stack_t} value are unclear.  @Theglibc{}
Packit Service 82fcde
and most other Unix implementations require the @code{ss_sp} value of
Packit Service 82fcde
the @code{uc_stack} element to point to the base of the memory region
Packit Service 82fcde
allocated for the stack and the size of the memory region is stored in
Packit Service 82fcde
@code{ss_size}.  There are implementations out there which require
Packit Service 82fcde
@code{ss_sp} to be set to the value the stack pointer will have (which
Packit Service 82fcde
can, depending on the direction the stack grows, be different).  This
Packit Service 82fcde
difference makes the @code{makecontext} function hard to use and it
Packit Service 82fcde
requires detection of the platform at compile time.
Packit Service 82fcde
Packit Service 82fcde
@deftypefun int setcontext (const ucontext_t *@var{ucp})
Packit Service 82fcde
@standards{SVID, ucontext.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}}
Packit Service 82fcde
@c Linux-only implementations mostly in assembly.  Some ports use
Packit Service 82fcde
@c sigreturn or swapcontext syscalls; others restore the signal mask
Packit Service 82fcde
@c first and then proceed restore other registers in userland, which
Packit Service 82fcde
@c leaves a window for cancellation or async signals with misaligned or
Packit Service 82fcde
@c otherwise corrupt stack.  ??? Switching to a different stack, or even
Packit Service 82fcde
@c to an earlier state on the same stack, may conflict with pthread
Packit Service 82fcde
@c cleanups.  This is not quite MT-Unsafe, it's a different kind of
Packit Service 82fcde
@c safety issue.
Packit Service 82fcde
Packit Service 82fcde
The @code{setcontext} function restores the context described by
Packit Service 82fcde
@var{ucp}.  The context is not modified and can be reused as often as
Packit Service 82fcde
wanted.
Packit Service 82fcde
Packit Service 82fcde
If the context was created by @code{getcontext} execution resumes with
Packit Service 82fcde
the registers filled with the same values and the same stack as if the
Packit Service 82fcde
@code{getcontext} call just returned.
Packit Service 82fcde
Packit Service 82fcde
If the context was modified with a call to @code{makecontext} execution
Packit Service 82fcde
continues with the function passed to @code{makecontext} which gets the
Packit Service 82fcde
specified parameters passed.  If this function returns execution is
Packit Service 82fcde
resumed in the context which was referenced by the @code{uc_link}
Packit Service 82fcde
element of the context structure passed to @code{makecontext} at the
Packit Service 82fcde
time of the call.  If @code{uc_link} was a null pointer the application
Packit Service 82fcde
terminates normally with an exit status value of @code{EXIT_SUCCESS}
Packit Service 82fcde
(@pxref{Program Termination}).
Packit Service 82fcde
Packit Service 82fcde
If the context was created by a call to a signal handler or from any
Packit Service 82fcde
other source then the behaviour of @code{setcontext} is unspecified.
Packit Service 82fcde
Packit Service 82fcde
Since the context contains information about the stack no two threads
Packit Service 82fcde
should use the same context at the same time.  The result in most cases
Packit Service 82fcde
would be disastrous.
Packit Service 82fcde
Packit Service 82fcde
The @code{setcontext} function does not return unless an error occurred
Packit Service 82fcde
in which case it returns @code{-1}.
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
The @code{setcontext} function simply replaces the current context with
Packit Service 82fcde
the one described by the @var{ucp} parameter.  This is often useful but
Packit Service 82fcde
there are situations where the current context has to be preserved.
Packit Service 82fcde
Packit Service 82fcde
@deftypefun int swapcontext (ucontext_t *restrict @var{oucp}, const ucontext_t *restrict @var{ucp})
Packit Service 82fcde
@standards{SVID, ucontext.h}
Packit Service 82fcde
@safety{@prelim{}@mtsafe{@mtsrace{:oucp} @mtsrace{:ucp}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}}
Packit Service 82fcde
@c Linux-only implementations mostly in assembly.  Some ports call or
Packit Service 82fcde
@c inline getcontext and/or setcontext, adjusting the saved context in
Packit Service 82fcde
@c between, so we inherit the potential issues of both.
Packit Service 82fcde
Packit Service 82fcde
The @code{swapcontext} function is similar to @code{setcontext} but
Packit Service 82fcde
instead of just replacing the current context the latter is first saved
Packit Service 82fcde
in the object pointed to by @var{oucp} as if this was a call to
Packit Service 82fcde
@code{getcontext}.  The saved context would resume after the call to
Packit Service 82fcde
@code{swapcontext}.
Packit Service 82fcde
Packit Service 82fcde
Once the current context is saved the context described in @var{ucp} is
Packit Service 82fcde
installed and execution continues as described in this context.
Packit Service 82fcde
Packit Service 82fcde
If @code{swapcontext} succeeds the function does not return unless the
Packit Service 82fcde
context @var{oucp} is used without prior modification by
Packit Service 82fcde
@code{makecontext}.  The return value in this case is @code{0}.  If the
Packit Service 82fcde
function fails it returns @code{-1} and sets @var{errno} accordingly.
Packit Service 82fcde
@end deftypefun
Packit Service 82fcde
Packit Service 82fcde
@heading Example for SVID Context Handling
Packit Service 82fcde
Packit Service 82fcde
The easiest way to use the context handling functions is as a
Packit Service 82fcde
replacement for @code{setjmp} and @code{longjmp}.  The context contains
Packit Service 82fcde
on most platforms more information which may lead to fewer surprises
Packit Service 82fcde
but this also means using these functions is more expensive (besides
Packit Service 82fcde
being less portable).
Packit Service 82fcde
Packit Service 82fcde
@smallexample
Packit Service 82fcde
int
Packit Service 82fcde
random_search (int n, int (*fp) (int, ucontext_t *))
Packit Service 82fcde
@{
Packit Service 82fcde
  volatile int cnt = 0;
Packit Service 82fcde
  ucontext_t uc;
Packit Service 82fcde
Packit Service 82fcde
  /* @r{Safe current context.}  */
Packit Service 82fcde
  if (getcontext (&uc) < 0)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  /* @r{If we have not tried @var{n} times try again.}  */
Packit Service 82fcde
  if (cnt++ < n)
Packit Service 82fcde
    /* @r{Call the function with a new random number}
Packit Service 82fcde
       @r{and the context}.  */
Packit Service 82fcde
    if (fp (rand (), &uc) != 0)
Packit Service 82fcde
      /* @r{We found what we were looking for.}  */
Packit Service 82fcde
      return 1;
Packit Service 82fcde
Packit Service 82fcde
  /* @r{Not found.}  */
Packit Service 82fcde
  return 0;
Packit Service 82fcde
@}
Packit Service 82fcde
@end smallexample
Packit Service 82fcde
Packit Service 82fcde
Using contexts in such a way enables emulating exception handling.  The
Packit Service 82fcde
search functions passed in the @var{fp} parameter could be very large,
Packit Service 82fcde
nested, and complex which would make it complicated (or at least would
Packit Service 82fcde
require a lot of code) to leave the function with an error value which
Packit Service 82fcde
has to be passed down to the caller.  By using the context it is
Packit Service 82fcde
possible to leave the search function in one step and allow restarting
Packit Service 82fcde
the search which also has the nice side effect that it can be
Packit Service 82fcde
significantly faster.
Packit Service 82fcde
Packit Service 82fcde
Something which is harder to implement with @code{setjmp} and
Packit Service 82fcde
@code{longjmp} is to switch temporarily to a different execution path
Packit Service 82fcde
and then resume where execution was stopped.
Packit Service 82fcde
Packit Service 82fcde
@smallexample
Packit Service 82fcde
@include swapcontext.c.texi
Packit Service 82fcde
@end smallexample
Packit Service 82fcde
Packit Service 82fcde
This an example how the context functions can be used to implement
Packit Service 82fcde
co-routines or cooperative multi-threading.  All that has to be done is
Packit Service 82fcde
to call every once in a while @code{swapcontext} to continue running a
Packit Service 82fcde
different context.  It is not recommended to do the context switching from
Packit Service 82fcde
the signal handler directly since leaving the signal handler via
Packit Service 82fcde
@code{setcontext} if the signal was delivered during code that was not
Packit Service 82fcde
asynchronous signal safe could lead to problems. Setting a variable in
Packit Service 82fcde
the signal handler and checking it in the body of the functions which
Packit Service 82fcde
are executed is a safer approach.  Since @code{swapcontext} is saving the
Packit Service 82fcde
current context it is possible to have multiple different scheduling points
Packit Service 82fcde
in the code.  Execution will always resume where it was left.