kazmax - Linux で自宅サーバー

makecontext - ライブラリコールの説明 - Linux コマンド集 一覧表

  1. 名前
  2. 書式
  3. 説明
  4. 返り値
  5. エラー
  6. 注意
  7. 準拠
  8. 関連項目

名前

makecontext, swapcontext - ユーザコンテキストを操作する

書式

#include <ucontext.h>
void makecontext(ucontext_t * ucp , void * func (), int argc , ...);
int swapcontext(ucontext_t * oucp , ucontext_t * ucp );

説明

System V 的な環境では、 mcontext_t および ucontext_t という 2 つの型と、 getcontext (), setcontext (), makecontext (), swapcontext () という 4 つの関数が <ucontext.h> で定義されており、あるプロセス内部で制御下にある複数のスレッド間で、 ユーザレベルのコンテキスト切替えができるようになっている。

これらの型と、最初の 2 つの関数については、   getcontext (2) を参照のこと。

makecontext () 関数は、ポインタ ucp が指すコンテキストを変更する (ucp は以前の getcontext () 呼び出しで得られたものである)。 makecontext () を起動する前には、呼び出し者は、このコンテキスト用に 新しいスタックを確保し、そのアドレスを ucp->uc_stack に代入し、 さらに後継のコンテキストを定義し、そのアドレスを ucp->uc_link に 代入しなければならない。
このコンテキストが将来 (setcontext () または swapcontext () によって) 有効にされると、関数 func が呼ばれ、 引き数として argc 以降の整数 ( int )引き数の列が渡される。 呼び出し者は argc にこれらの引き数の個数を指定しなければならない。 この関数が戻ると、後継のコンテキストが有効になる。 後継コンテキストのポインタが NULL の場合、そのスレッドが終了する。

swapcontext () 関数は現在のコンテキストを ポインタ oucp が指す構造体に保存し、 ポインタ ucp が指すコンテキストを有効にする。

返り値

成功すると、swapcontext () は返らない (しかし後に oucp が有効になった場合には返ることがある。 このときには swapcontext () は 0 を返すように見える。) 失敗すると、swapcontext () は -1 を返し、 errno をエラーに応じて設定する。

エラー

ENOMEM
スタックに割り当てる空間が残っていない。

注意

ucp->uc_stack の解釈は   sigaltstack (2) の場合と同じである。 すなわちこの構造体には、 スタックとして用いられるメモリ領域の開始アドレスと長さが含まれ、 これはスタックが伸びる方向がどちらであるかには関係しない。 したがって、ユーザプログラムはこの件については心配しなくてよい。

準拠

SUSv2, POSIX.1-2001.

以下のサンプル・プログラムは、 getcontext (), makecontext (), swapcontext ().の使用方法の例を示すものである。 このプログラムを実行すると、以下のような出力が得られる:


$ ./a.out main: swapcontext(&uctx_main, &uctx_func2) func2: started func2: swapcontext(&uctx_func2, &uctx_func1) func1: started func1: swapcontext(&uctx_func1, &uctx_func2) func2: returning func1: returning main: exiting

#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>


static ucontext_t uctx_main, uctx_func1, uctx_func2;
#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void func1(void) { printf("func1: started\n"); printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n"); if (swapcontext(&uctx_func1, &uctx_func2) == -1) die("swapcontext"); printf("func1: returning\n"); }
static void func2(void) { printf("func2: started\n"); printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n"); if (swapcontext(&uctx_func2, &uctx_func1) == -1) die("swapcontext"); printf("func2: returning\n"); }
int main(int argc, char *argv[]) { char func1_stack[16384]; char func2_stack[16384];
if (getcontext(&uctx_func1) == -1) die("getcontext"); uctx_func1.uc_stack.ss_sp = func1_stack; uctx_func1.uc_stack.ss_size = sizeof(func1_stack); uctx_func1.uc_link = &uctx_main; makecontext(&uctx_func1, func1, 0);
if (getcontext(&uctx_func2) == -1) die("getcontext"); uctx_func2.uc_stack.ss_sp = func2_stack; uctx_func2.uc_stack.ss_size = sizeof(func2_stack); /* Successor context is f1(), unless argc > 1 */ uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1; makecontext(&uctx_func2, func2, 0);
printf("main: swapcontext(&uctx_main, &uctx_func2)\n"); if (swapcontext(&uctx_main, &uctx_func2) == -1) die("swapcontext");
printf("main: exiting\n"); exit(EXIT_SUCCESS); }

関連項目