操作 |
参照先 |
---|---|
スレッドの生成 | |
最小のスタックサイズの取得 | |
スレッド識別子の取得 | |
スレッドの実行明け渡し | |
スレッドへのシグナルの送信 | |
呼び出しスレッドのシグナルマスクのアクセス | |
スレッドの終了 | |
スレッドの終了待ち | |
スレッド固有データ用キーの作成 | |
スレッド固有データの設定 | |
スレッド固有データの取得 | |
スレッド優先順位の設定 | |
スレッド優先順位の取得 |
thr_create(3C) ルーチンは、Solaris スレッドインタフェースに含まれるルーチンのうち、もっとも精巧なルーチンの 1 つです。
現在のプロセスに新しい制御スレッドを追加するときは、thr_create(3C) を使用します。POSIX スレッドの場合については、「pthread_create の構文」を参照してください。
#include <thread.h> int thr_create(void *stack_base, size_t stack_size, void *(*start_routine) (void *), void *arg, long flags, thread_t *new_thread); size_t thr_min_stack(void);
新しいスレッドは保留中のシグナルは継承しませんが、優先順位とシグナルマスクを継承します。
stack_base 。新しいスレッドが使用するスタックのアドレスを指定します。NULL を指定すると、新しいスレッドに stack_size バイト以上のサイズをもつスタックが割り当てられます。()
stack_size。新しいスレッドが使用するスタックのバイト数を指定します。stack_size が 0 の場合、デフォルトのサイズが使用されます。通常は 0 を指定してください。stack_size が 0 以外の場合は、thr_min_stack() の戻り値よりも大きい値を指定してください。
通常、スレッド用にスタック空間を割り当てる必要はありません。システムが、各スレッドのスタック用に 1M バイトの仮想メモリーをスワップ空間の予約なしで割り当てます。システムは、mmap(2) の -MAP_NORESERVE オプションを使って割り当てを行います。
start_routine — 新しいスレッドが実行を開始するために使用する関数を指定します。start_routine() で指定した関数が終了すると、スレッドはその関数の戻り値を終了状態に設定して終了します。「thr_exit の構文」を参照してください。
arg — void で記述される任意の変数で、通常は 4 バイト値です。それよりも大きな値を渡す場合は、引数が変数を指す方法で間接的に渡す必要があります。
引数は 1 つしか指定できません。複数の引数をとらせるためには、それらを構造体に入れるなどして、1 つのものとしてコーディングします。
flags — 生成されるスレッドの属性を指定します。通常は 0 を指定してください。
flags の値は、以下に示す引数のビット単位の論理和となります。
THR_SUSPENDED — 新しいスレッドを停止させます。thr_continue でスレッドを再開するまで start_routine() は実行されません。 THR_SUSPENDED は、スレッドを実行する前に優先順位の変更などを行いたいときに使用します。
THR_DETACHED — 新しいスレッドを切り離します。その結果、このスレッドのスレッド識別子やその他のリソースが、スレッド終了後ただちに再利用できるようになります。THR_DETACHED は、スレッドの終了を待つ必要がないときに設定してください。
明示的な同期が割り当てられていないとき、停止していない切り離されたスレッドは失敗することがあります。失敗すると、そのスレッドの生成元が thr_create() から復帰する前に、そのスレッド ID が別の新しいスレッドに割り当てられます。
THR_BOUND — 新しいスレッドを永続的に LWP に結合します。新しいスレッドは結合スレッドになります。Solaris 9 リリースから、結合スレッドと非結合スレッドが区別されなくなりました。すべてのスレッドが結合スレッドとして扱われます。
THR_DAEMON — 新しいスレッドをデーモンにします。デーモンスレッドは常に切り離されます。THR_DAEMONを指定すると、暗黙的に THR_DETACHED が適用されます。デーモンでないスレッドがすべて終了すると、プロセスは終了します。デーモンスレッドは、プロセスの終了状態に影響を与えず、また終了するスレッド数にも含まれません。
プロセスを終了するには、exit() を呼び出すか、プロセス内のスレッドのうち THR_DAEMON フラグを指定せずに生成されたすべてのスレッドから thr_exit(3C) を呼び出します。アプリケーションやそのプロセスによって呼び出されるライブラリでは、終了判断の際に無視される (考慮されない) スレッドを生成できます。THR_DAEMON フラグは、プロセスの終了条件に関係しないスレッドを生成するときに指定します。
new_thread — new_thread が NULL 以外の場合には、thr_create() が正常終了したときに新しいスレッドの ID が格納された場所を指しています。この引数が指す記憶領域は、呼び出し側の責任で確保しなければなりません。このスレッド識別子は、呼び出し側のプロセス内でだけ有効です。
スレッド識別子が特に必要でなければ、new_thread に NULL を指定してください。
thr_create() は、正常終了時に 0 を返します。それ以外の戻り値は、エラーが発生したことを示します。以下のいずれかの条件が検出されると、thr_create() は失敗し、対応する値を戻します。
EAGAIN
説明:システム制限を超えました。たとえば、生成する LWP が多すぎます。
ENOMEM
説明:新しいスレッドを生成するための十分なメモリーがありません。
スレッドの最小スタックサイズを取得するには、thr_min_stack(3C) を使用します。
Solaris スレッドでのスタックの動作は、通常は pthread の場合と同じです。スタックの設定と操作の詳細は、「スタックについて」を参照してください。
#include <thread.h> size_t thr_min_stack(void);
thr_min_stack() は、NULL スレッドの実行に必要な空間の量を返します。NULL スレッドは、NULL 手続きを実行するために生成されたスレッドです。実用的なスレッドに必要なスタック空間は、スタックの絶対最小サイズより大きいので、スタックサイズを小さくするときは十分注意してください。
スレッドが NULL 手続きでなく通常の手続きを実行する場合は、thr_min_stack() の戻り値よりも大きなスタックサイズを割り当てなければなりません。
ユーザーが指定したスタックを使用してスレッドが作成される場合には、このスレッドの実行に必要な空間量を確保する必要があります。動的にリンクされる実行環境の場合には、スレッドの最小スタック要件を決定するのがさらにむずかしくなります。
カスタムスタックは、次の 2 つの方法で指定できます。1 つは、thr_create() でスタックアドレスを NULL に指定し、スタック空間の割り当てをスレッドライブラリに任せる方法です。スタックサイズを指定するパラメータには、希望のサイズを指定します。
もう 1 つの方法は、thr_create() にスタックのポインタを渡して、スタックをすべて自分で管理する方法です。この場合は、スタック空間の割り当てだけでなく、割り当ての解放もユーザー自身で行う必要があります。つまり、スレッドを終了するときに、そのスタックをユーザーが解放しなければなりません。
独自のスタックを割り当てる場合は、mprotect(2) を呼び出して、スタックの最後に必ずレッドゾーンを付加してください。
通常、ユーザー独自のスタックが必要になることはまれです。実際、アプリケーション側が実行環境を完全に制御するなどのごく限られた状況でしか必要になりません。
ユーザーは、システムにスタックの割り当てを任せることができます。システムのデフォルトのスタックは、すべてのスレッドの要求を満たします。
エラーが未定義です。
呼び出しスレッドの ID を取得するには、thr_self(3C) を使用します。POSIX スレッドの場合については、「pthread_self の構文」を参照してください。
#include <thread.h> thread_t thr_self(void);
エラーが未定義です。
thr_yield(3C) は、現在のスレッドから、同じ優先順位かより高い優先順位をもつ別のスレッドに実行を譲ります。thr_yield() には、それ以外の効果はありません。ただし、thr_yield() の呼び出しスレッドが実行権を必ず譲るとは限りません。
#include <thread.h> void thr_yield(void);
thr_yield() は何も返さず、errno を設定しません。
thr_kill(3C) は、スレッドにシグナルを送ります。POSIX スレッドの場合については、「pthread_kill の構文」を参照してください。
#include <thread.h> #include <signal.h> int thr_kill(thread_t target_thread, int sig);
thr_kill() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_kill() は失敗し、対応する値を返します。障害が発生したときには、シグナルは送信されません。
ESRCH
説明:スレッド ID (thread) で指定されたスレッドに関連付けられたスレッドがありません。
EINVAL
説明:sig 引数の値が 0 以外です。sig が無効であるか、サポートされていないシグナル番号です。
呼び出しスレッドのシグナルマスクを変更または検査するには、thr_sigsetmask(3C) を使用します。
#include <thread.h> #include <signal.h> int thr_sigsetmask(int how, const sigset_t *set, sigset_t *oset);
thr_sigsetmask() は、呼び出しスレッドのシグナルマスクを変更または検査します。各スレッドは、スレッド専用のシグナルマスクを持っています。新しいスレッドは、呼び出しスレッドのシグナルマスクと優先順位を継承します。ただし、保留中のシグナルは継承の対象にはなりません。保留中のシグナルは、新しいスレッドでは空になります。
引数 set の値が NULL 以外の場合、set は、現在ブロックされているシグナルセットを変更するシグナルセットになります。set の値が NULL の場合、how の値は意味を持たず、スレッドのシグナルマスクは変更されません。この動作を利用して、現在ブロックされているシグナルについて問い合わせることができます。
how の値には、セットの変更方法を指定します。how は、次のいずれかの値をとります。
SIG_BLOCK — set は、ブロックするシグナルセットになります。これらのシグナルは、現在のシグナルマスクに追加されます。
SIG_UNBLOCK — set は、ブロックを解除するシグナルセットになります。これらのシグナルは、現在のシグナルマスクから削除されます。
SIG_SETMASK — set は、新しいシグナルマスクになります。現在のシグナルマスクは、 set で置き換えられます。
thr_sigsetmask () は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_sigsetmask() は失敗し、対応する値を返します。
EINVAL
説明:set が NULL 以外なのに、how の値が未定義です。
スレッドを終了するには、thr_exit(3C) を使用します。POSIX スレッドの場合については、「pthread_exit Syntax」を参照してください。
#include <thread.h> void thr_exit(void *status);
ターゲットスレッドの終了を待つには、thr_join(3C) を使用します。POSIX スレッドの場合については、「pthread_join の構文」を参照してください。
#include <thread.h> int thr_join(thread_t tid, thread_t *departedid, void **status);
ターゲットスレッドは、現在のプロセスのメンバーでなければなりません。また、切り離されたスレッドやデーモンスレッドであってはなりません。
複数のスレッドが、同じスレッドの終了を待つことはできません。1 つのスレッドだけが正常に終了します。ほかのスレッドは、ESRCH エラーを発行して終了します。
thr_join() は、ターゲットスレッドがすでに終了している場合に、呼び出しスレッドの処理をブロックすることはありません。
#include <thread.h> thread_t tid; thread_t departedid; int ret; void *status; /* waiting to join thread "tid" with status */ ret = thr_join(tid, &departedid, &status); /* waiting to join thread "tid" without status */ ret = thr_join(tid, &departedid, NULL); /* waiting to join thread "tid" without return id and status */ ret = thr_join(tid, NULL, NULL);
tid が (thread_t) 0
の場合は、thr_join() はプロセス内の切り離されていない任意のスレッドの終了を待ちます。つまり、スレッド識別子を指定しなければ、切り離されていないスレッドのどれかが終了すると thr_join() が復帰します。
#include <thread.h> thread_t tid; thread_t departedid; int ret; void *status; /* waiting to join any non-detached thread with status */ ret = thr_join(0, &departedid, &status);
thr_join() でスレッド識別子としてゼロを指定すると、プロセス内の切り離されていない任意のスレッドの終了を待ちます。departedid には、終了したスレッドのスレッド識別子が格納されます。
thr_join() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_join() は失敗し、対応する値を返します。
ESRCH
説明:ターゲットスレッド ID に対応する、切り離されていないスレッドが見つかりません。
EDEADLK
説明:デッドロックが検出されたか、ターゲットスレッドの値に呼び出しスレッドが指定されています。
thr_keycreate(3C) は、プロセス内のスレッド固有データを識別するために使用されるキーを割り当てます。このキーは、プロセス内のすべてのスレッドに大域的なキーです。各スレッドは、このキーの生成時に値を 1 つずつ割り当てます。
スレッド固有のデータは、POSIX スレッドの場合も Solaris スレッドの場合も、関数名と引数を除いて同じです。この節では、Solaris の関数の概要を説明します。POSIX スレッドの場合については、「pthread_key_create の構文」を参照してください。
#include <thread.h> int thr_keycreate(thread_key_t *keyp, void (*destructor) (void *value));
keyp は、各結合スレッド固有の値を個別に管理します。各スレッドは、スレッド固有のデータへのアクセスを許可するために、最初に固有要素の keyp に結合されます。キーが生成されるときに、すべてのアクティブなスレッドに対して、新しいキーに値 NULL が割り当てられます。また、スレッドが生成されるときに、新しいスレッドのすでに生成されているすべてのキーには、値 NULL が割り当てられます。
オプションの destructor 関数は、各 keyp に関連付けることができます。スレッドが終了するときに、keyp に NULL 以外 destructor が関連付けられ、そのスレッドの keyp に NULL 以外の value が関連付けられている場合には、現在関連付けられている value を使用して destructor が呼び出されます。スレッドが終了するときに 1 つ以上の destructor が存在する場合には、デストラクタは不特定に呼び出されます。
thr_keycreate() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_keycreate() は失敗し、対応する値を返します。
EAGAIN
説明:追加のスレッド固有のデータキーを生成するために必要なリソースがありません。または、キーの数が、PTHREAD_KEYS_MAX に指定されたプロセスごとの最大キー数を超えています。
ENOMEM
説明:value と keyp を関連付けるために必要なメモリーが不足しています。
thr_setspecific(3C) は、呼び出しスレッドに対して、スレッド固有データキー key に value を結合します。POSIX スレッドの場合については、「pthread_setspecific の構文」を参照してください。
#include <thread.h> int thr_setspecific(thread_key_t key, void *value);
thr_setspecific() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_setspecific () は失敗し、対応する値を返します。
ENOMEM
説明:value と keyp を関連付けるために必要なメモリーが不足しています。
EINVAL
説明:keyp が無効です。
thr_getspecific(3C) は、呼び出しスレッドの key に結合された現在の値を valuep が指す場所に格納します。POSIX スレッドの場合については、「pthread_getspecific の構文」を参照してください。
#include <thread.h> int thr_getspecific(thread_key_t key, void **valuep);
thr_getspecific() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_getspecific () は失敗し、対応する値を返します。
ENOMEM
説明:value と keyp を関連付けるために必要なメモリーが不足しています。
EINVAL
説明:keyp が無効です。
Solaris スレッドでは、優先順位が親と異なるスレッドを生成する場合、SUSPEND モードで生成します。スレッドの優先順位は、停止している間に thr_setprio(3C) 関数を呼び出して変更されます。thr_setprio() が終了すると、スレッドは実行を再開します。
優先順位の高いスレッドは、同期オブジェクトの競合を考慮しながら、優先順位の低いスレッドより優先されます。
thr_setprio(3C) は、tid に指定されたスレッドの優先順位を、現在のプロセス内で newprio に指定された優先順位に変更します。POSIX スレッドの場合については、「pthread_setschedparam の構文」を参照してください。
#include <thread.h> int thr_setprio(thread_t tid, int newprio)
スレッドの有効な優先順位の範囲は、スケジューリングポリシーによって異なります。
thread_t tid; int ret; int newprio = 20; /* suspended thread creation */ ret = thr_create(NULL, NULL, func, arg, THR_SUSPENDED, &tid); /* set the new priority of suspended child thread */ ret = thr_setprio(tid, newprio); /* suspended child thread starts executing with new priority */ ret = thr_continue(tid);
thr_setprio() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_setprio() は失敗し、対応する値を返します。
ESRCH
説明:tid で指定した値が既存のスレッドを表していません。
EINVAL
説明:priority の値は、指定されたスレッドのスケジューリングポリシーには無効です。
EPERM
説明:呼び出し元は、優先順位を指定された値に設定するための適切なアクセス権を持っていません。
スレッドの現在の優先順位を取得するには、thr_getprio(3C) を使用します。各スレッドは生成側の優先順位を継承します。thr_getprio() は、tid で指定されたスレッドの現在の優先順位を、newprio が指している位置に格納します。POSIX スレッドの場合については、「pthread_getschedparam の構文」を参照してください。
#include <thread.h> int thr_getprio(thread_t tid, int *newprio)
thr_getprio() は、正常終了時に 0 を返します。次の条件が検出された場合、thr_getprio() は失敗し、対応する値を返します。
ESRCH
説明:tid で指定した値が既存のスレッドを表していません。