swapcontext() — Save and restore user context

Standards

Standards / Extensions C or C++ Dependencies

XPG4.2
Single UNIX Specification, Version 3

both POSIX(ON)

Format

#define _XOPEN_SOURCE_EXTENDED 1
#include <ucontext.h>

int swapcontext(ucontext_t *__restrict__ oucp, const ucontext_t *__restrict__ ucp);

General description

The swapcontext() function saves the current user context in the context structure pointed to by oucp and restores the user context structure pointed to by ucp. swapcontext() is equivalent to getcontext() with the oucp argument followed by setcontext() with the ucp argument.

Control does not return from the initial invocation of swapcontext(). However, if the saved context is not modified using makecontext(), and a subsequent setcontext() or swapcontext() is issued using the saved context, swapcontext() returns with a 0 return value.

Notes:
  1. If the ucontext pointed to by ucp that is input to swapcontext(), has not been modified by makecontext(), you must ensure that the function that saved that context by calling either getcontext() or swapcontext() does not return before you call swapcontext() to restore that context. Calling swapcontext() after the function that saved the context returns causes unpredictable program behavior.
  2. If swapcontext() is used to jump back into an XPLINK routine, any alloca() requests issued by the XPLINK routine after the earlier getcontext() was called and before swapcontext() is called are backed out. All storage obtained by these alloca() requests is freed before the XPLINK routine is resumed.
  3. If swapcontext() is used to jump back into a non-XPLINK routine, alloca() requests made after getcontext() and before swapcontext() are not backed out.
  4. Do not issue swapcontext() from any type of condition handling routine (for eample, a signal catcher, a Language Environment® user condition handler or an exception handler).
  5. If ucp is pointing to a user context of a different execution stack from the current, the user context should be either a freshly modified one (by makecontext()) or the most recently saved one (by getcontext() or swapcontext()) when running on its stack.
  6. If ucp is pointing to a user context of a different execution stack from the current, the current stack is never collapsed and any resource associated with it is never freed after swapcontext() being called.

This function is supported only in a POSIX program.

The <ucontext.h> header file defines the ucontext_t type as a structure that includes the following members:
mcontext_t       uc_mcontext     A machine-specific representation
                                 of the saved context.
ucontext_t      *uc_link         Pointer to the context that will
                                 be resumed when this context returns.
sigset_t         uc_sigmask      The set of signals that are blocked
                                 when this context is active.
stack_t          uc_stack        The stack used by this context.

Special behavior for C++: If getcontext() and swapcontext() are used to transfer control in a z/OS® XL C++ program, the behavior in terms of the destruction of automatic objects is undefined. This applies to both z/OS XL C++ and z/OS XL C++ ILC modules. The use of getcontext() and swapcontext() in conjunction with try(), catch(), and throw() is also undefined.

Do not issue getcontext() in a C++ constructor or destructor, since the saved context would not be usable in a subsequent setcontext() or swapcontext() after the constructor or destructor returns.

Special behavior for XPLINK-compiled C/C++: Restrictions concerning setjmp.h and ucontext.h:
  1. All XPLINK programs compiled with the V2R10 or later C compilers that are to run with Language Environment V2R10 or later libraries and use the jmp_buf, sigjmp_buf or ucontext_t types must not be compiled with C headers from Language Environment V2R9 or earlier.
  2. Non-XPLINK functions compiled with any level of Language Environment headers must not define jmp_buf, sigjmp_buf or ucontext_t data items and pass them to XPLINK functions that call getcontext(), longjmp(), _longjmp(), setjmp(), _setjmp(), setcontext(), sigsetjmp(), or swapcontext() with these passed-in data items.
  3. When __XPLINK__ is defined, the Language Environment V2R10 and later headers define a larger jmp_buf, sigjmp_buf or ucontext_t area that is required by setjmp(), getcontext(), and related functions when they are called from an XPLINK routine. If __XPLINK__ is not defined, the Language Environment V2R10 and later headers define a shorter jmp_buf, sigjmp_buf or ucontext_t area. The Language Environment headers before V2R10 also define the shorter version of these data areas. If an XPLINK function calls setjmp(), getcontext() or similar functions with a short jmp_buf, sigjmp_buf or ucontext_t area, a storage overlay or program check may occur when the C library tries to store past the end of the passed-in (too short) data area.

Returned value

If successful, swapcontext() does not return from the initial invocation. If the unmodified saved context is later restored, swapcontext() returns 0.

If unsuccessful, swapcontext() returns -1.

There are no errno values defined.

Example

This example uses two contexts. It creates the first, fcontext, in main with the getcontext() statement, and invokes the function func. It invokes the function with the swapcontext() statement, saving the context at that point in the second context, mcontext. The function returns to the point of the swapcontext() using the setcontext() statement and specifying mcontext as the context.
/* This example shows the usage of swapcontext().                    */

#define _XOPEN_SOURCE_EXTENDED 1
#include <stdlib.h>
#include <stdio.h>
#include <ucontext.h>
#include <errno.h>

 #ifdef _LP64
  #define STACK_SIZE 2097152+16384 /* large enough value for AMODE 64 */
 #else
  #define STACK_SIZE 16384  /* AMODE 31 addressing*/
 #endif
void func(int);

ucontext_t fcontext,mcontext;
int x = 0;

int main(void) {

  int  value = 1;

  getcontext(&fcontext);
  if ((fcontext.uc_stack.ss_sp = (char *) malloc(STACK_SIZE)) != NULL) {
    fcontext.uc_stack.ss_size = STACK_SIZE;
    fcontext.uc_stack.ss_flags = 0;
			errno = 0;
    makecontext(&fcontext,func,1,value);
			if (errno != 0){
				perror("Error reported by makecontext()");
				return -1;    /* Error occurred exit */
	}
  	}
  else {
    perror("not enough storage for stack");
    abort();
  }
  printf("context has been built\n");
  swapcontext(&mcontext,&fcontext);
  if (!x) {
    perror("incorrect return from swapcontext");
    abort();
  }
  else {
    printf("returned from function\n");
  }

}

void func(int arg) {

  printf("function called with value %d\n",arg);
  x++;
  printf("function returning to main\n");
  setcontext(&mcontext);

}
Output
context has been built
function called with value 1
function returning to main
returned from function