Provided by: manpages-ja-dev_0.5.0.0.20131015+dfsg-2_all bug

名前

       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(3), setcontext(3),
       makecontext(), swapcontext()  という 4 つの関数が <ucontext.h> で定義されており、あるプロセス内部で制御下
       にある複数のスレッド間で、 ユーザレベルのコンテキスト切替えができるようになっている。

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

       makecontext()  関数は、ポインタ ucp が指すコンテキストを変更する (ucp は以前の getcontext(3)   呼び出しで
       得られたものである)。 makecontext() を起動する前には、呼び出し者は、このコンテキスト用に 新しいスタックを
       確保し、そのアドレスを    ucp->uc_stack    に代入し、    さらに後継のコンテキストを定義し、そのアドレスを
       ucp->uc_link に 代入しなければならない。

       このコンテキストが将来 (setcontext(3)  または swapcontext()  によって)  有効にされると、関数 func  が呼ば
       れ、  引き数として argc 以降の整数 (int)  引き数の列が渡される。 呼び出し者は argc にこれらの引き数の個数
       を指定しなければならない。 この関数が戻ると、後継のコンテキストが有効になる。  後継コンテキストのポインタ
       が NULL の場合、そのスレッドが終了する。

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

返り値

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

エラー

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

バージョン

       makecontext()  と swapcontext()  は、バージョン 2.1 以降の glibc で提供されている。

準拠

       SUSv2, POSIX.1-2001.  POSIX.1-2008 では、移植性の問題から makecontext()  と swapcontext()  の仕様が削除さ
       れている。 代わりに、アプリケーションを POSIX スレッドを使って書き直すことが 推奨されている。

注意

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

       int  とポインタ型が同じ大きさであるアーキテクチャでは  (x86-32 はその例であり、両方の型とも 32 ビットであ
       る)、  makecontext()   の  argc  以降の引き数としてポインタを渡してもうまく動くかもしれない。  しかしなが
       ら、このようにすると、移植性は保証されず、  標準に従えば動作は未定義であり、ポインタが  int  よりも大きい
       アーキテクチャでは正しく動作しないことだろう。  それにも関わらず、バージョン  2.8  以降の  glibc   では、
       makecontext()   に変更が行われ、(x86-64 などの) いくつかの 64 ビットアーキテクチャで 引き数としてポインタ
       を渡すことができるようになっている。

       以下のサンプル・プログラムは、 getcontext(3), 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 handle_error(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)
               handle_error("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)
               handle_error("swapcontext");
           printf("func2: returning\n");
       }

       int
       main(int argc, char *argv[])
       {
           char func1_stack[16384];
           char func2_stack[16384];

           if (getcontext(&uctx_func1) == -1)
               handle_error("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)
               handle_error("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)
               handle_error("swapcontext");

           printf("main: exiting\n");
           exit(EXIT_SUCCESS);
       }

関連項目

       sigaction(2), sigaltstack(2), sigprocmask(2), getcontext(3), sigsetjmp(3)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクトの説明とバグ報告
       に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。

GNU                                                2013-02-12                                     MAKECONTEXT(3)