makecontext() — Modify 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>

void makecontext(ucontext_t *ucp, void (*func)(), int argc, …);

General description

The makecontext() function modifies the context specified by ucp, which has been initialized using getcontext(). When this context is resumed using setcontext() or swapcontext(), program execution continues by calling func(), passing it the arguments that follow argc in the makecontext() call.

The value of argc must match the number of integer arguments passed to func(), otherwise the behavior is undefined.

The uc_link member of ucontext_t is used to determine the context that will be resumed when the context being modified by makecontext() returns. If the uc_link member is not equal to 0, the process continues as if after a call to setcontext() with the context pointed to by the uc_link member. If the uc_link member is equal to 0, the process exits as if exit() were called. The uc_link member should be initialized before the call to makecontext().

This function is supported only in a POSIX program.

This function is not supported in an AMODE 31 XPLINK environment (for example, one which is in AMODE 31 and in which either the main() function was compiled with the XPLINK option, or the XPLINK(ON) runtime option was specified).

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++

Because C and C++ linkage conventions are incompatible, makecontext() cannot receive C++ function pointers. If you attempt to pass a C++ function pointer to makecontext(), the compiler will flag it as an error. To use the C++ makecontext() function, you must ensure that all functions registered for makecontext() have C linkage by declaring them as extern “C”. For example:
C:   void func(int, int);
     :
     makecontext(&context, func, 2, arg1, arg2);

C++: extern "C" void func();
     :
     makecontext(&context, func, 2, arg1, arg2);

AMODE 64 considerations

Storage for the stack must be above the 2GB bar. It may not be storage acquired with the __malloc24() or __malloc31() functions. The stack must be big enough to allow for the creation of a 1M guard page (aligned on a 1M boundary).

The environment variable _EDC_CONTEXT_GUARD can be used to control when the stack is guarded and unguarded. For details on the _EDC_CONTEXT_GUARD environment variable, see the "Using Environment Variables" chapter in z/OS XL C/C++ Programming Guide.

Returned value

makecontext() returns no values.

If unsuccessful, makecontext() sets errno to one of the following values:
Error Code
Description
EINVAL
The context being modified is using an alternate stack, and the target function entry point is not a valid Language Environment or C entry point.

The argc argument specifies a value less than 0.

ENOMEM
The ucp argument does not have enough stack left to complete the operation. Or more than 15 arguments are passed to the target function, and there is not enough storage to hold all of the arguments.
Note: If the target function is in a DLL that has not yet been loaded, then makecontext() cannot determine the size requirement and assumes that the size required is MINSIGSTKSZ. Therefore, in this case, the stack must be at least the size indicated by MINSIGSTKSZ. If the size required by the target function is more than MINSIGSTKSZ, then you must load the DLL before invoking makecontext().

Example

This example creates a context in main with the getcontext() statement, then modifies the context to have its own stack and to invoke the function func. It invokes the function with the setcontext() statement. Since the uc_link member is set to 0, the process exits when the function returns.
/* This example shows the usage of makecontext().                    */

#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 context, *cp = &context;

int main(void) {

  int  value = 1;

  getcontext(cp);
  context.uc_link = 0;
  if ((context.uc_stack.ss_sp = (char *) malloc(STACK_SIZE)) != NULL) {
    context.uc_stack.ss_size = STACK_SIZE;
    context.uc_stack.ss_flags = 0;
             errno = 0;
    makecontext(cp,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");
  setcontext(cp);
  perror("returned from setcontext");
  abort();

}

void func(int arg) {

  printf("function called with value %d\n",arg);
  printf("process will exit when function returns\n");
  return;

}
Output
context has been built
function called with value 1
process will exit when function returns

Related information