マルチスレッドのプログラミング

Solaris スレッドに類似した関数

表 6–3 Solaris スレッドに類似した関数

操作 

参照先 

スレッドの生成 

thr_create の構文」

最小のスタックサイズの取得 

thr_min_stack の構文」

スレッド識別子の取得 

thr_self の構文」

スレッドの実行明け渡し 

thr_yield の構文」

スレッドへのシグナルの送信 

thr_kill の構文」

呼び出しスレッドのシグナルマスクのアクセス 

thr_sigsetmask の構文」

スレッドの終了 

thr_exit の構文」

スレッドの終了待ち 

thr_join の構文」

スレッド固有データ用キーの作成 

thr_keycreate の構文」

スレッド固有データの設定 

thr_setspecific の構文」

スレッド固有データの取得 

thr_getspecific の構文」

スレッド優先順位の設定 

thr_setprio の構文」

スレッド優先順位の取得 

thr_getprio の構文」

スレッドの生成

thr_create(3C) ルーチンは、Solaris スレッドインタフェースに含まれるルーチンのうち、もっとも精巧なルーチンの 1 つです。

現在のプロセスに新しい制御スレッドを追加するときは、thr_create(3C) を使用します。POSIX スレッドの場合については、pthread_create の構文」を参照してください。

thr_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 の構文」を参照してください。

argvoid で記述される任意の変数で、通常は 4 バイト値です。それよりも大きな値を渡す場合は、引数が変数を指す方法で間接的に渡す必要があります。

引数は 1 つしか指定できません。複数の引数をとらせるためには、それらを構造体に入れるなどして、1 つのものとしてコーディングします。

flags — 生成されるスレッドの属性を指定します。通常は 0 を指定してください。

flags の値は、以下に示す引数のビット単位の論理和となります。


注 –

明示的な同期が割り当てられていないとき、停止していない切り離されたスレッドは失敗することがあります。失敗すると、そのスレッドの生成元が thr_create() から復帰する前に、そのスレッド ID が別の新しいスレッドに割り当てられます。


new_threadnew_threadNULL 以外の場合には、thr_create() が正常終了したときに新しいスレッドの ID が格納された場所を指しています。この引数が指す記憶領域は、呼び出し側の責任で確保しなければなりません。このスレッド識別子は、呼び出し側のプロセス内でだけ有効です。

スレッド識別子が特に必要でなければ、new_thread に NULL を指定してください。

thr_create の戻り値

thr_create() は、正常終了時に 0 を返します。それ以外の戻り値は、エラーが発生したことを示します。以下のいずれかの条件が検出されると、thr_create() は失敗し、対応する値を戻します。


EAGAIN

説明:

システム制限を超えました。たとえば、生成する LWP が多すぎます。


ENOMEM

説明:

新しいスレッドを生成するための十分なメモリーがありません。


EINVAL

説明:

stack_baseNULL でなく、しかも stack_sizethr_min_stack() の戻り値より小さな値を指定しました。

最小のスタックサイズの取得

スレッドの最小スタックサイズを取得するには、thr_min_stack(3C) を使用します。

Solaris スレッドでのスタックの動作は、通常は pthread の場合と同じです。スタックの設定と操作の詳細は、「スタックについて」を参照してください。

thr_min_stack の構文

#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) を呼び出して、スタックの最後に必ずレッドゾーンを付加してください。

通常、ユーザー独自のスタックが必要になることはまれです。実際、アプリケーション側が実行環境を完全に制御するなどのごく限られた状況でしか必要になりません。

ユーザーは、システムにスタックの割り当てを任せることができます。システムのデフォルトのスタックは、すべてのスレッドの要求を満たします。

thr_min_stack の戻り値

エラーが未定義です。

スレッド識別子の獲得

呼び出しスレッドの ID を取得するには、thr_self(3C) を使用します。POSIX スレッドの場合については、pthread_self の構文」を参照してください。

thr_self の構文

#include <thread.h>

thread_t thr_self(void);

thr_self の戻り値

エラーが未定義です。

スレッドの実行明け渡し

thr_yield(3C) は、現在のスレッドから、同じ優先順位かより高い優先順位をもつ別のスレッドに実行を譲ります。thr_yield() には、それ以外の効果はありません。ただし、thr_yield() の呼び出しスレッドが実行権を必ず譲るとは限りません。

thr_yield の構文

#include <thread.h>

void thr_yield(void);

thr_yield の戻り値

thr_yield() は何も返さず、errno を設定しません。

スレッドへのシグナルの送信

thr_kill(3C) は、スレッドにシグナルを送ります。POSIX スレッドの場合については、pthread_kill の構文」を参照してください。

thr_kill の構文

#include <thread.h>
#include <signal.h>
int thr_kill(thread_t target_thread, int sig);

thr_kill の戻り値

thr_kill() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_kill() は失敗し、対応する値を返します。障害が発生したときには、シグナルは送信されません。


ESRCH

説明:

スレッド ID (thread) で指定されたスレッドに関連付けられたスレッドがありません。


EINVAL

説明:

sig 引数の値が 0 以外です。sig が無効であるか、サポートされていないシグナル番号です。

呼び出しスレッドのシグナルマスクのアクセス

呼び出しスレッドのシグナルマスクを変更または検査するには、thr_sigsetmask(3C) を使用します。

thr_sigsetmask の構文

#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 は、次のいずれかの値をとります。

thr_sigsetmask の戻り値

thr_sigsetmask () は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_sigsetmask() は失敗し、対応する値を返します。


EINVAL

説明:

set が NULL 以外なのに、how の値が未定義です。

スレッドの終了

スレッドを終了するには、thr_exit(3C) を使用します。POSIX スレッドの場合については、pthread_exit Syntax」を参照してください。

thr_exit の構文

#include <thread.h>

void thr_exit(void *status);

thr_exit の戻り値

thr_exit() は呼び出し側に値を返しません。

スレッドの終了待ち

ターゲットスレッドの終了を待つには、thr_join(3C) を使用します。POSIX スレッドの場合については、pthread_join の構文」を参照してください。

thr_join の構文

#include <thread.h>

int thr_join(thread_t tid, thread_t *departedid, void **status);

ターゲットスレッドは、現在のプロセスのメンバーでなければなりません。また、切り離されたスレッドやデーモンスレッドであってはなりません。

複数のスレッドが、同じスレッドの終了を待つことはできません。1 つのスレッドだけが正常に終了します。ほかのスレッドは、ESRCH エラーを発行して終了します。

thr_join() は、ターゲットスレッドがすでに終了している場合に、呼び出しスレッドの処理をブロックすることはありません。

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() が復帰します。

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 の戻り値

thr_join() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_join() は失敗し、対応する値を返します。


ESRCH

説明:

ターゲットスレッド ID に対応する、切り離されていないスレッドが見つかりません。


EDEADLK

説明:

デッドロックが検出されたか、ターゲットスレッドの値に呼び出しスレッドが指定されています。

スレッド固有データ用キーの作成

thr_keycreate(3C) は、プロセス内のスレッド固有データを識別するために使用されるキーを割り当てます。このキーは、プロセス内のすべてのスレッドに大域的なキーです。各スレッドは、このキーの生成時に値を 1 つずつ割り当てます。

スレッド固有のデータは、POSIX スレッドの場合も Solaris スレッドの場合も、関数名と引数を除いて同じです。この節では、Solaris の関数の概要を説明します。POSIX スレッドの場合については、pthread_key_create の構文」を参照してください。

thr_keycreate の構文

#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 の戻り値

thr_keycreate() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_keycreate() は失敗し、対応する値を返します。


EAGAIN

説明:

追加のスレッド固有のデータキーを生成するために必要なリソースがありません。または、キーの数が、PTHREAD_KEYS_MAX に指定されたプロセスごとの最大キー数を超えています。


ENOMEM

説明:

valuekeyp を関連付けるために必要なメモリーが不足しています。

スレッド固有データの値の設定

thr_setspecific(3C) は、呼び出しスレッドに対して、スレッド固有データキー keyvalue を結合します。POSIX スレッドの場合については、pthread_setspecific の構文」を参照してください。

thr_setspecific の構文

#include <thread.h>

int thr_setspecific(thread_key_t key, void *value);

thr_setspecific の戻り値

thr_setspecific() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_setspecific () は失敗し、対応する値を返します。


ENOMEM

説明:

valuekeyp を関連付けるために必要なメモリーが不足しています。


EINVAL

説明:

keyp が無効です。

スレッド固有データの値の取得

thr_getspecific(3C) は、呼び出しスレッドの key に結合された現在の値を valuep が指す場所に格納します。POSIX スレッドの場合については、pthread_getspecific の構文」を参照してください。

thr_getspecific の構文

#include <thread.h>

int thr_getspecific(thread_key_t key, void **valuep);

thr_getspecific の戻り値

thr_getspecific() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_getspecific () は失敗し、対応する値を返します。


ENOMEM

説明:

valuekeyp を関連付けるために必要なメモリーが不足しています。


EINVAL

説明:

keyp が無効です。

スレッド優先順位の設定

Solaris スレッドでは、優先順位が親と異なるスレッドを生成する場合、SUSPEND モードで生成します。スレッドの優先順位は、停止している間に thr_setprio(3C) 関数を呼び出して変更されます。thr_setprio() が終了すると、スレッドは実行を再開します。

優先順位の高いスレッドは、同期オブジェクトの競合を考慮しながら、優先順位の低いスレッドより優先されます。

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 の戻り値

thr_setprio() は、正常終了時に 0 を返します。次のいずれかの条件が検出された場合、thr_setprio() は失敗し、対応する値を返します。


ESRCH

説明:

tid で指定した値が既存のスレッドを表していません。


EINVAL

説明:

priority の値は、指定されたスレッドのスケジューリングポリシーには無効です。


EPERM

説明:

呼び出し元は、優先順位を指定された値に設定するための適切なアクセス権を持っていません。

スレッド優先順位の取得

スレッドの現在の優先順位を取得するには、thr_getprio(3C) を使用します。各スレッドは生成側の優先順位を継承します。thr_getprio() は、tid で指定されたスレッドの現在の優先順位を、newprio が指している位置に格納します。POSIX スレッドの場合については、pthread_getschedparam の構文」を参照してください。

thr_getprio の構文

#include <thread.h>

int thr_getprio(thread_t tid, int *newprio)

thr_getprio の戻り値

thr_getprio() は、正常終了時に 0 を返します。次の条件が検出された場合、thr_getprio() は失敗し、対応する値を返します。


ESRCH

説明:

tid で指定した値が既存のスレッドを表していません。