Go to the first, previous, next, last section, table of contents.


リファレンス

この章は, ライブラリのリファレンスマニュアルです.

スレッド管理のための関数

スレッド属性の操作

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int *detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr);
int pthread_attr_setstackprop_np(pthread_attr_t *attr, int property);
int pthread_attr_getstackprop_np(pthread_attr_t *attr);
int pthread_attr_setsuspended_np(pthread_attr_t *attr, int suspendstate);
int pthread_attr_getsuspended_np(pthread_attr_t *attr);
pthread_attr_init
pthread_attr_init()は, attr で指定されたスレッドアトリビュー トオブジェクトを初期化します. 生成されたスレッドアトリビュートオブジェクトは, pthread_create() によってスレッドを作成する際に用いられます. 単一のスレッドアトリビュート オブジェクトを複数の pthread_create()の呼出しに用いても構いません.
pthread_attr_destroy
pthread_attr_destroy()は, スレッドアトリビュートオブジェクト を削除するために用います. 削除されたスレッドアトリビュートオブジェ クトを用いてはなりません.
pthread_attr_setstacksize
pthread_attr_setstacksize()は, attrのスタックサイズ属性 を設定します. stacksizeの単位は byte です.
pthread_attr_getstacksize
pthread_attr_getstacksize()は, attrのスタックサイズ属性 を取得します. stacksizeの単位は byte です.
pthread_attr_setdetachstate
pthread_attr_setdetachstate() は, attr のデタッチス テート属性を設定します. detachstate は 0 か 1 の値をとります. 1 ならば, attr を用いて生成された全てのスレッドはデタッチされた状 態で開始されます. 0 ならば, デタッチされない状態で開始されます.
pthread_attr_getdetachstate
pthread_attr_getdetachstate() は, attr のデタッチステート 属性を取得し, 返り値として返します.
pthread_attr_setstackprop_np
pthread_attr_setstackprop_np() は, attr の スタックプロパティ属性を property に設定します. property は以下の定数の論理和です. @tindex{PTHREAD_STACK_SAFE_NP} @tindex{PTHREAD_STACK_EXTENSIBLE_NP} @tindex{PTHREAD_STACK_NONE_NP}

PTHREAD_STACK_SAFE_NP
安全なスタック(溢れ検出可能)
PTHREAD_STACK_EXTENSIBLE_NP
自動拡張可能なスタック
PTHREAD_STACK_NONE_NP
特に性質を指定しない

(Thread StackについてはSee section スタックプロパティ.).

pthread_attr_getstackprop_np
pthread_attr_getstackprop_np() は, attr の スタックプロパティ属性を返り値として返します.
pthread_attr_setsuspended_np
pthread_attr_setsuspended_np() は, attr のサスペンドス テート属性を設定します. suspendstate は 0 か 1 の値をとります. 1 ならば, attr を用いて生成された全てのスレッドはサスペンドされた 状態で生成され, pthread_resume_np() が呼ばれるまでブロックしま す. 0 ならば, サスペンドされない状態で開始されます.
pthread_attr_getsuspended_np
pthread_attr_suspendedstate_np() は, attr のサスペンドス テート属性を取得し, 返り値として返します.

スレッドの生成

#include <pthread.h>

int pthread_create(pthread_t *thread, pthread_attr_t *attr,
                   void *(*start_routine)(void *arg), void *arg);

pthread_create() は, プロセス中に attr を属性として, 新た なスレッドを生成します. もし, attr が NULL ならば, デフォルトアト リビュート(See section スレッドアトリビュートオブジェクト.) が用いられます. attr が後に変更された としても, スレッドの属性には影響を与えません. スレッドの生成に成功すると, pthread_create() は, thread の指す場所に生成したスレッドの IDを返します.

生成されたスレッドは, start_routine から実行され, そのただ一つの引 数は arg です. start_routine からリターンした場合は, 暗黙に start_routine からの返り値を引数として pthread_exit() が呼 ばれます. ただし, 初期スレッドはこれと異なり, main() からリターン すると, 暗黙に main() からの返り値を引数として exit() が呼 ばれます.

もし, pthread_create() が失敗した場合には, thread の指 す内容は不定となります.

生成したスレッドのシグナルの状態に関しては See section シグナルの状態の継承. を参照して下さい.

スレッドの終了の Wait

#include <pthread.h>

int pthread_join(pthread_t thread, void **status);

pthread_join() は, thread が既に終了していない場合, この関 数を呼び出したスレッドの実行を thread が終了するまで停止させます. statusが NULL で無いpthread_join() の呼出しが成功してリター ンすると, 終了したスレッドが pthread_exit() に渡した値が, status の指す場所に返ります. デタッチされたスレッドに対する pthread_join() の呼出しの結果は不定です.

thread に自分自身のスレッドを指定した場合, errno に EAGAIN がセッ トされ, -1 を返します.

スレッドのデタッチ

#include <pthread.h>

int pthread_detach(pthread_t *thread);

pthread_detach() は, thread で示されるスレッドが終了し た場合, そのスレッドのための領域を再利用しても良いことを宣言します. もし, thread が終了していなかった場合は, thread が終了 次第, 領域を再利用します.

pthread_detach() は, スレッドに関連した領域を再利用するため, 全てのスレッドについていつかは呼ばれるべきです.

スレッドの終了

#include <pthread.h>

void pthread_exit(void *status);

pthread_exit() は, この関数を呼び出したスレッドを終了させ, status の値を, join しているスレッドに伝えます. プッシュされているが ポップされていない全ての Cleanup ハンドラはプッシュされた順番と逆順に 取り出され, 実行されます. 全ての Cleanup ハンドラが実行された後, スレッ ドが Thread-Specific データを保持していた場合, 適当なデストラクタ関数 が, 定義されない順序で呼び出されます. スレッドの終了時には, Mutex 等の リソースは自動的には一切開放されません.

初期スレッド以外のスレッドが, 作成する時に用いた start routine からリ ターンする時, 返り値がスレッドの終了ステータスとして用いられます. 初期 スレッドが main() からリターンすると, その返り値を引数として暗 黙に exit() が呼ばれます.

暗黙の, あるいは明示的な pthread_exit() の呼出しによるcleanup ハンドラやデストラクタ関数の実行中に pthread_exit() が呼ばれた 場合の動作は不定です.

最後の未終了のスレッドが pthread_exit() を呼ぶことによってプ ロセスは終了します. このときのプロセスの終了ステータスは, このスレッ ドがデタッチされていた場合は0, そうでない場合は1になります.

スレッドの終了ステータスの解釈は, アプリケーションによってなさ れるため(スレッドがキャンセルされたときの返り値 (void*)-1 を除く), ステータスとして(小さな)整数を使うことは自由です.

スレッドのサスペンド

#include <pthread.h>

extern int pthread_suspend_np(pthread_t thread);
extern int pthread_resume_np(pthread_t thread);
pthread_suspend_np
pthread_suspend_np() は, thread をサスペンドするために用 います. (See section スレッドのサスペンドの概要.) 指定したスレッドが既にサスペンドされていた場合, errno = EALREADY として -1 を返します.
pthread_resume_np
pthread_resume_np() は, サスペンドされた thread を再開す るために用います. 指定したスレッドがサスペンドされていなかった場合, errno = EALREADY として -1 を返します.

スレッドは自分自身をサスペンドしても構いません. この場合, 他のスレッド から pthread_resume_np() を呼び出してもらうことになります.

pthread_mutex_lock(), pthread_cond_wait(), pthread_join(), sleep() 等の呼び出しによってブロックして いるスレッドをサスペンドした場合, サスペンドされたスレッドは, 待ってい るイベントが発生し, かつ pthread_resume_np() が呼ばれるまで実行 を再開することはありません.

サスペンドされているスレッドに, 非同期シグナルが配送されることはありま せん. また, 同期シグナルや pthread_kill() によるシグナルが配送 された場合, pthread_resume_np() が呼ばれるまでシグナルハンドラ の実行は延期されます. (See section シグナルの配送.)

スレッド ID の取得

#include <pthread.h>

pthread_t pthread_self(void);

pthread_self() は, この関数を呼び出したスレッドのIDを返します.

スレッド ID の比較

#include <pthread.h>

int pthread_equal(pthread_t t1, pthread_t t2);

この関数はスレッド ID t1t2 を比較し, 同一のスレッド ならば非0, そうでなければ0を返します.

パッケージの動的な初期化

#include <pthread.h>

pthread_once_t once_control = PTHREAD_ONCE_INIT;

int pthread_once(pthread_once_t *once_control, void (*init_routine)());
int pthread_first_np(pthread_once_t *once_control);
void pthread_first_done_np(pthread_once_t *once_control);

これらの関数は, ユーザの指定した関数やブロックを正確に一回だけ呼び出すた めに存在します. たとえ, この呼出しが複数のスレッドから同時に行なわれたり, 複数回呼ばれても, 関数やブロックは一回しか呼ばれません.

プロセスで最初の once_control を伴う pthread_once() の呼出 しは, init_routine を引数無しで呼び出します. それ以降の pthread_once() の呼出しは init_routine を呼び出しません. pthread_once() からのリターンは, init_routine が終了してい ることを保証します. 2回目以降の呼出し時にまだinit_routineが実行中 だった場合, pthread_once()init_routine が終了するまで ブロックします. once_control パラメータは, 関連したどの初期化ルー チンが呼ばれたかどうかを決定するのに用いられます.

PTHREAD_ONCE_INIT の値は, `<pthread.h>' で定義されます.

もし once_control のストレージクラスが auto か, あるいは初期化され ていない場合の pthread_once() の振る舞いは未定義です.

pthread_first_np() は, 最初の once_control を伴う呼出しでは 非0を返し, それ以降の呼出しでは0を返します. ユーザが関数内の一回だけ実行 したい初期化ブロックは, pthread_first_np() が1を返した時に実行す れば良いことになります. この際, 初期化ブロックが終了したことを示すため, 初期化ブロックの最後で pthread_first_done_np() を, pthread_first_np() と同一の引数で実行する必要があります.

スレッドに対するネーミング

スレッドに名前を与えることができます. 名前は, ユニークで無くても構いませ ん. ライブラリでは, SIGSEGV 等が発生して停止する際に, 実行中のスレッドに 名前が与えられていれば, その名前を表示します.

#include <pthread.h>

int pthread_set_name_np(pthread_t thread, const char *name);
char *pthread_get_name_np(pthread_t thread);
pthread_set_name_np
pthread_set_name_np() は, thread に名前として name を割り当てます. name は内部でヒープ領域にコピーされるため, name の領域は pthread_set_name_np() の呼出しの後に開放し ても構いません.
pthread_get_name_np
pthread_get_name_np() は, thread の名前へのポインタを返し ます. 返り値は, thread が exitして, detach されるまで有効な名前 を指しています.

スタックキャッシュ

#include <pthread.h>

int pthread_alloc_stack_cache_np(pthread_attr_t *attr, int nstack);

この関数は, スレッドアトリビュートオブジェクト attr で指定される スタックを nstack 個確保し, 確保できたスタックの数を返します. attr 中でスタックプロパティ属性と, スタックサイズ属性のみが参照 されます. 確保したスタックはスタックキャッシュに蓄えられ, 以降の pthread_create() によるスレッドの生成の際に利用されます.

同期のための関数

Mutex アトリビュートオブジェクト

#include <pthread.h>

int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
pthread_protocol_t pthread_mutexattr_getprotocol(pthread_mutexattr_t attr);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
                                  pthread_protocol_t protocol);
int pthread_mutexattr_getprio_ceiling(pthread_mutexattr_t attr);
int pthread_mutexattr_setprio_ceiling(pthread_mutexattr_t *attr);

pthread_mutexattr_init
pthread_mutexattr_init は, Mutex アトリビュートオブジェクトを生 成, 初期化します. Mutex アトリビュートオブジェクトの初期値については, See section Mutex アトリビュートオブジェクト. を参照してください.
pthread_mutexattr_destroy
pthread_mutexattr_destroyは, Mutex アトリビュートオブジェクトを 破棄します.
pthread_mutexattr_getpshared
PTLではサポートしていません.
pthread_mutexattr_setpshared
PTLではサポートしていません.
pthread_mutexattr_getprotocol
pthread_mutexattr_getprotocol()attrMutex プ ロトコル (See section プライオリティの逆転の回避.) を取得します.
pthread_mutexattr_setprotocol
pthread_mutexattr_setprotocol()attrMutex プ ロトコルを設定します.
pthread_mutexattr_getprio_ceiling
pthread_mutexattr_getprio_ceiling()attr の Mutex のシー リングを取得します.
pthread_mutexattr_setprio_ceiling
pthread_mutexattr_setprio_ceiling()attr にシーリング を設定します.

PTLでは, 現在のところシーリングをサポートしていないため, pthread_mutexattr_setprio_ceiling(), pthread_mutexattr_getprio_ceiling() は errno = ENOSUP として, -1 を返します.

Mutex の初期化と破棄

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
pthread_mutex_init
pthread_mutex_init() は, attr で指定された Mutex アトリビュート オブジェクトを用いてmutex で示される Mutex を初期化します. attr が NULL ならば, デフォルトの Mutex アトリビュートオブジェク ト(See section Mutex アトリビュートオブジェクト.)が用いられます. pthread_mutex_init() が失敗した場合, Mutex は初期化されず, mutex の内容は不定になります.
pthread_mutex_destroy
pthread_mutex_destroy() は, mutex で指定された Mutex を破 棄します. ロックされた Mutex を破棄したり, 他のスレッドがブロックして いる Mutex を破棄した場合の動作は未定義です.

Mutexのロックとアンロック

#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_lock
pthread_mutex_lock() によって mutex で示さ れる Mutex をロックすることが出来ます(See section Mutex のロック.) もし, Mutex が既に他のスレッドによってロック されていた場合, pthread_mutex_lock() を呼び出したスレッドは Mutex が再びロックできるようになるまでブロックされます. pthread_mutex_lock が成功すると, mutexで示される Mutex を, ロックした状態でリターンします. 呼びだしスレッドが既にロックしている Mutex を再びロックしようとした場 合, errno = EDEADLK として-1 が返ります.
pthread_mutex_trylock
pthread_mutex_trylock()mutex によって示される Mutex が ロックされていた場合に errno = EBUSY として直ちに -1 を返すことを 除いて, pthread_mutex_lock() と同じです.
pthread_mutex_unlock
pthread_mutex_unlock() は, mutex によって示される Mutex をアンロックするために用います. pthread_mutex_unlock() が Mutex をロックしていないスレッドから呼ば れた場合, あるいは, Mutex がロックされていない場合は errno = EPERM と して -1 を返します. Mutex を待ってブロックしているスレッドが複数存在した場合, もっとも高い プライオリティのスレッドが Mutex をロックします.

Mutexのプライオリティシーリングの変更

PTLでは, 現在 PRIO_PROTECT プロトコルをサポートしていないため, これらの関数は errno = ENOSUP として, -1 を返します.

#include <pthread.h>

int pthread_mutex_getprio_ceiling(pthread_mutex_t mutex);
int pthread_mutex_setprio_ceiling(pthread_mutex_t mutex,
                                  int prio_ceiling);
pthread_mutex_getprio_ceiling
pthread_mutex_getprio_ceiling() は Mutex のシーリングを返します.
pthread_mutex_setprio_ceiling
pthread_mutex_setprio_ceiling() は, Mutex をロックし, Mutex の シーリングを変更し, Mutex を開放します. もし, pthread_mutex_setprio_ceiling() が失敗した場合, Mutex の シーリングは変更されません.

Mutex に対するネーミング

Mutex に名前を与えることができます. 名前は, ユニークで無くても構いませ ん. ライブラリでは, スレッドが終了する際に, Mutex がアンロックされてい ないと, Mutex の名前を表示して警告を発します.

#include <pthread.h>

int pthread_mutex_set_name_np(pthread_mutex_t mutex, const char *name);
char *pthread_mutex_get_name_np(pthread_mutex_t mutex);
pthread_mutex_set_name_np
pthread_mutex_set_name_np() は, mutex に名前として name を割り当てます. name は内部でヒープ領域にコピーされる ため, name の領域は pthread_mutex_set_name_np() の呼出し の後に開放しても構いません.
pthread_mutex_get_name_np
pthread_mutex_get_name_np() は, mutex の名前へのポインタを返し ます. 返り値は, mutex が破棄されるまで有効な名前を指しています.

Mutex で Wait 中のスレッドの数

#include <pthread.h>

int pthread_mutex_waiters_np(pthread_mutex_t mutex);

この関数は, mutex でブロックしているスレッドの数を返します. この 返り値は, mutex がロックされている時のみ信頼できます.

Condition アトリビュートオブジェクトの操作

#include <pthread.h>

int pthread_condattr_init(pthread_condattr_t *attr);
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_getpshared(pthread_condattr_t *attr, int *pshared);
int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared);
pthread_condattr_init
pthread_condattr_init() は, Condition アトリビュートオブジェク ト attr を初期化します(See section Condition アトリビュートオブジェクト.). pthread_condattr_init() が失敗した場合, attr の内容は不 定となります. Condition アトリビュートオブジェクトを変更, 破棄しても, それは既に作ら れた Condition Variable に影響を与えません.
pthread_condattr_destroy
pthread_condattr_destroy() は, Conditionアトリビュートオブジェク トを破棄します.
pthread_condattr_getpshared
この関数は, PTLではサポートしていません.
pthread_condattr_setpshared
この関数は, PTLではサポートしていません.

Condition の初期化と破棄

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cond);
pthread_cond_init
pthread_cond_init() は, attr で指定された Condition アト リビュートオブジェクトを用いて cond で示される Condition Variable を初期化します. attr が NULL ならば, デフォルトの Condition アトリビュート (See section Condition アトリビュートオブジェクト.)が用いられます. pthread_cond_init() が失敗した場合, Condition Variable は初期化 されず, cond の内容は不定になります.
pthread_cond_destroy
pthread_cond_destroy()は, Condition Variable を破棄します. 他のスレッドがブロックしている Condition Variable を破棄した場合の動作 は未定義です.

Conditionのブロードキャストとシグナル

#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

これらの関数は, Condition Variable でブロックしているスレッドをアンブロッ クします.

pthread_cond_signal
pthread_cond_signal() は, 指定した cond でブロックして いるスレッドを一つアンブロックします. 複数のスレッドが Condition Variable でブロックしていた場合, もっとも高いプライオリティのスレッド がアンブロックされます.
pthread_cond_broadcast
pthread_cond_broadcast() は, 指定した cond でブロックして いるスレッドを全てアンブロックします.

これらの関数によって, Condition Variable でのブロックから開放されるス レッドは, pthread_cond_wait()pthread_cond_timedwait() からリターンする前に, 関連した Mutex をロックします. (See section Condition Variable での Wait.)

pthread_cond_signal()pthread_cond_broadcast() は, cond でブロックしているスレッドが存在しなけば何の効果もありませ ん.

Condition での Wait

#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond,
                           pthread_mutex_t *mutex,
                           const struct timespec *abstime);

pthread_cond_wait()pthread_cond_timedwait() は, Condition Variableでブロックするために用いられます. これらは呼びだしス レッドが mutex をロックした状態で呼び出さなければなりません. さ もなくば未定義の動作を引き起こします. これらの関数は mutex をア ンロックし, 呼び出しスレッドを Condition Variable code でブロッ クさせます. これらの関数からリターンした際には, Mutexは呼び出しスレッ ドによってロックされた状態となっています.

pthread_cond_timedwait() は, cond がシグナルされる前に abstime によって指定される絶対時刻が過ぎた場合にエラーでリターン する(Mutexは再びロックされます)ことを除いて, pthread_cond_wait() と同一です.

Condition に対するネーミング

Condition Variable に名前を与えることができます. 名前は, ユニークで無 くても構いません.

#include <pthread.h>

int pthread_cond_set_name_np(pthread_cond_t cond, const char *name);
char *pthread_cond_get_name_np(pthread_cond_t cond);
pthread_cond_set_name_np
pthread_cond_set_name_np() は, cond に名前として name を割り当てます. name は内部でヒープ領域にコピーされる ため, name の領域は pthread_cond_set_name_np() の呼出しの 後に開放しても構いません.
pthread_cond_get_name_np
pthread_cond_get_name_np() は, cond の名前へのポインタを返し ます. 返り値は, cond が破棄されるまで有効な名前を指しています.

#include <pthread.h>

int pthread_cond_waiters_np(pthread_cond_t cond);

この関数は, cond でブロックしているスレッドの数を返します. 返さ れる値には, 「Condition でのブロックからは開放されているが, 引き続く Mutex のロックでブロックしているスレッド」の数は含まれません. この値は, 関連する Mutex がロックされている場合のみ信頼できます.

Thread-Specific データのための関数

Thread-Specific データキーの管理

#include <pthread.h>

int pthread_key_create(pthread_key_t *key,
                       void (*destructor)(void *value));

この関数は, プロセス中の全てのスレッドで共有される キー を作りま す. pthread_key_create() によって返されるキーは, Thread-Specific データを指定するために使われます. 異なったスレッドによっ て同じ キー の値が使われたとしても, pthread_setspecific() による キー に対応した値はスレッド毎に管理され, 呼びだしスレッド が存在しなくなるまで存在します. (See section Thread-Specific データの概要.)

キー が作成された時, 全ての既存のスレッドのキーに対応した値は NULL で初期化されます. また, 新たにスレッドが生成された場合は, いまま でに定義されたキーに対応した値は NULL に初期化されます.

複数のスレッドによる, 同一の key を指定した pthread_key_create() の並行した呼出しの結果は未定義です.

それぞれのキーに対応して, オプショナルなデストラクタ関数を結び 付けることが出来ます. スレッドが終了する際, キー がNULLでないデ ストラクタポインタを持っていて, スレッドの キー に対応する値が NULLでない場合, その値を引数としてデストラクタ関数が呼ばれます. スレッ ドが終了する際に複数のデストラクタが存在した場合, デストラクタの呼ば れる順序は不定です.

Thread-Specific データの管理

#include <pthread.h>

int pthread_setspecific(pthread_key_t key, void *value);
int pthread_getspecific(pthread_key_t key, void **value));
pthread_setspecific
pthread_setspecific() は, pthread_key_create() を用いて 得られた key に対して Thread-Specific データ, valueを対応 させます. 異なったスレッドが同一のキーに異なった値を結び付けることが出 来ます. これらの値は典型的には, 呼びだしスレッドが用いるために動的に確 保したメモリブロックへのポインタです.
pthread_setspecific
pthread_getspecific() は, 呼びだしスレッドの指定した key に対応する値を返します.

スレッドのSpecificデータデストラクタからの pthread_setspecific()pthread_getspecific() の呼出し の結果は未定義です.

これらの関数は, マクロとして実装される可能性があります. (PTLでは関数として実装しています)

スケジューリングのための関数

スケジューリング属性の設定

#include <pthread.h>

int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
int pthread_attr_getscope(pthread_attr_t *attr);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit);
int pthread_attr_getinheritsched(pthread_attr_t *attr);
int pthread_attr_setsched(pthread_attr_t *attr, int scheduler);
int pthread_attr_getsched(pthread_attr_t *attr);
int pthread_attr_setprio(pthread_attr_t *attr, int priority);
int pthread_attr_getprio(pthread_attr_t *attr);
pthread_attr_setscope
pthread_attr_getscope
@tindex{PTHREAD_SCOPE_GLOBAL} @tindex{PTHREAD_SCOPE_LOCAL} これらの関数は, attrコンテンションスコープ属性 を設定, 取得します(See section コンテンションスコープ.). contentionscope が PTHREAD_SCOPE_GLOBAL ならば, グローバルなコンテ ンションスコープ, PTHREAD_SCOPE_LOCAL ならばローカルなコンテンションスコー プです. PTHREAD_SCOPE_GLOBAL, PTHREAD_SCOPE_LOCAL は, `<pthread.h>'で定義 されます. PTLではコンテンションスコープは設定, 取得できますが, 何の意味も持ちませ ん.
pthread_attr_setinheritsched
pthread_attr_getinheritsched
これらの関数は, attrinheritsched属性を設定, 取得します (See section Inherit スケジューリング.).
pthread_attr_setprio
pthread_attr_getprio
これらの関数は, attrスケジューリングプライオリティ属性を 設定, 取得します(See section スケジューリングプライオリティ.).

pthread_create() によってアトリビュートオブジェクトが使用され る際, inheritsched 属性が, 生成されるスレッドのその他のスケジュー リング属性を決定するために用いられます.

PTHREAD_INHERIT_SCHED
スケジューラや, 関連する属性が, スレッドを生成するスレッドから引き継がれます
PTHREAD_DEFAULT_SCHED
スケジューラや, 関連する属性が, アトリビュートオブジェクトの対応する値から設定されます

PTHREAD_INHERIT_SCHED, PTHREAD_DEFAULT_SCHED は, `<pthread.h>' で定義されます.

pthread_attr_setsched
pthread_attr_getsched
pthread_attr_setsched(), pthread_attr_getsched() は, attr のスケジューリングポリシーを設定, 取得します.

スケジューリングポリシー 属性はスレッドのスケジューリングポリシー を決定します. ポリシーとして, `<pthread.h>' で定義される SCHED_FIFO, SCHED_RR, SCHED_OTHER のいずれかを選ぶ ことができます. scheduler の値の意味に関しては, See section スケジューリングポリシー. を参照して下さい.

動的なスケジューリング属性の変更

#include <pthread.h>

int pthread_getschedattr(pthread_t thread, pthread_attr_t *attrs);
int pthread_setschedattr(pthread_t thread, pthread_attr_t attrs);
pthread_getschedattr
pthread_setschedattr
pthread_getschedattr(), pthread_setschedattr() によっ て, それぞれのスレッドのスケジューリング属性を取得, 変更できます. pthread_setschedattr() は, スケジューリングポリシーとスケジュー リングプライオリティのみ変更します. pthread_getschedattr()thread によって与えられるスレッ ド ID を持つスレッドのスケジューリングポリシーと, スケジューリングプラ イオリティを attrs に格納します. pthread_setschedattr()thread によって与えられるスレッ ド ID を持つスレッドのスケジューリングポリシーと, スケジューリングプラ イオリティを attrs のポリシーとプライオリティに設定します. この 関数は, 既存のスレッドのスケジューリングポリシー, プライオリティを再設 定する唯一の手段です.

pthread_setschedattr() が失敗した場合, thread のどのスケジュー リング属性も変更されません.

CPU の明渡し

void pthread_yield(void *arg);

pthread_yield() は, 呼びだしスレッドの CPU を明け渡させます. す なわち, この関数を呼び出したスレッドの実行は再びスケジュールされるま で停止します.

%この関数は 同一のプライオリティ間 でコンテキストスイッチを %行ないます. すなわち, 同一のプライオリティに呼び出しスレッドしか存在 %しなければ, この関数の呼び出しは無意味です.

この関数は, 走行可能な最も高い優先度のスレッドへコンテキストスイッチを 行ないます.

PTLでは, arg は単に無視されます. 更に, `<pthread.h>' では, pthread_yield() は, 引数無しと宣言されています.

プライオリティの範囲

#include <pthread.h>

int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);

これらの関数は, スレッドのスケジューリングポリシー毎のプライオリティの 最大値, 最小値を得るために使用します.

プロセスコントロールのための関数

プロセスの生成

#include <sys/types.h>

pid_t fork(void);

プロセスは, 常に単一のスレッドを持つように生成されます. 複数のスレッド を持つプロセスが fork() を呼び出すと, 新たなプロセスは呼びだし スレッドと完全なアドレス空間の複製を持ちます(もしかすると, Mutexやその 他のリソースの状態をも含みます). 従ってエラーを避けるためには, 子プロ セスは exec 関数の一つが呼ばれるまで, 安全な操作だけを実行すべ きです. 安全な操作に関しては, POSIX.1 3.3.1.3 Signal Action 参 照.

PTLでは, 現在 fork() に関しては何も処理していません. 全てのスレッ ドが子プロセスに引き継がれます.

ファイルの実行

int execl(char *path, char *arg0, char *arg1, ...,
          char *argn, (char *)0);
int execv(char *path, char *argv[]);
int execle(char *path, char *arg0, char *arg1, ...,
           char *argn, (char *)0, char *envp[]);
int execlp(char *file, char *arg0, char *arg1, ...,
           char *argn, (char *)0);
int execvp(char *file, char *argv[]);

exec 関数は単一のスレッドを持つプロセスから呼び出すと, POSIX.1 で 定義されたように働きます. 複数のスレッドを持つプロセスから呼び出すと, 全てのスレッドが終了し, 新たな実行ファイルが POSIX.1 のようにロードさ れます.

PTLでは, これらの関数については何も処理していませんが, 既存の関数で問題 ないと思われます.

プロセスの終了

void _exit(int status);

スレッドが _exit() を呼び出すと, プロセス全体が終了します. さらに, プロセス中の全てのスレッドも終了します. このことはどんな理由によるプロセ スの終了に関しても起こります. さらに, _exit() の呼出しによって終 了するスレッドは Cleanup ハンドラ (See section スレッド Cleanup.) を実行しません. また, Thread-Specific データのデストラクタも 実行しません. (See section Thread-Specific データの概要.)

PTLでは, これらの関数については何も処理していませんが, 既存のシステムコー ルで問題ないと思われます.

プロセスの終了待ち

int wait(int *stat_loc);
int waitpid(pid_t *pid, int *stat_loc, int options);

wait()waitpid() は, 呼びだしスレッドのみをブロックさ せることを除いて POSIX.1 と同様に働きます.

PTLでは, これらの関数については何も処理していません. プロセス全体がサス ペンドされます.

プロセスの終了ステータスの設定

#include <pthread.h>

int pthread_set_exit_status_np(int status);

この関数は, 全てのスレッドが終了した時のプロセスの終了ステータスを設定し ます. この関数が呼ばれなかった場合の終了ステータスは, 最後のスレッドがデ タッチされていれば 0, そうでなければ 1 となります.

この関数によって設定された終了ステータスは, exit() の呼び出しによ る終了ステータスには関係しません.

返り値は, 以前にこの関数によって設定されていたプロセスの終了ステータスの 値です. 初めての呼び出しのときには 0 が返ります.

シグナルのための関数

非同期シグナルの Wait

#include <signal.h>

int sigwait(sigset_t *set);

この関数は, set からペンディングされたシグナルを選び, そのシグナル を不可分にペンディングシグナル集合からクリアし, そのシグナルの番号を返し ます. もし, 呼びだし時に set 中のシグナルがペンディングされていな かった場合, スレッドはシグナルの少なくとも一つがペンディングされるまでサ スペンドされます. set 中のシグナルは, sigwait() の呼びだし 時にブロックされます.

複数のスレッドが同一のシグナルを Wait するために sigwait() を用い ている時にシグナルが到着すると, ただ一つのスレッドが sigwait() か らリターンします. どのスレッドが sigwait() からリターンするかどう かは不定です.

sigwait() はInterruption Pointです. (See section 割り込みポイント.)

@tindex{SIG_SIGWAIT_NP} シグナルを sigwait() で待ちたい場合, シグナルアクションを SIG_SIGWAIT_NP に設定することを勧めます. (See section シグナルの配送.) これはシグナルによって, sigwait() がリター ンし, スレッドが処理をしている間に, 次のシグナルが配送された場合の混 乱を避けることが出来ます.

SIGINT と SIGQUIT を待つコード

sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGQUIT);
signal(SIGINT, SIG_SIGWAIT_NP);
signal(SIGQUIT, SIG_SIGWAIT_NP);
while(1) {
  switch(sigwait(&set)) {
    case SIGINT:
      /* Process SIGINT */
      break;
    case SIGQUIT:
      /* Process SIGQUIT */
      break;
  }
}

シグナルの状態の取得と変更

#include <signal.h>

int sigaction(int sig, struct sigaction *act,
              struct sigaction *oact);
int sigprocmask(int how, sigset_t *set, sigset_t *oset);
int sigsuspend(sigset_t *mask);
int sigpending(sigset_t *set);
int pause(void);
sigaction
sigaction() は, シグナルを受け取った際のアクションを設定する ために用いられます. sigaction() によって指定されるシグナルハ ンドラ, 追加のシグナルマスク, フラグはプロセス中の全てのスレッドで共 有されます. 同一のシグナルに対して sigaction()sigwait() を並行に 用いる場合, sigwait() が優先します.
sigprocmask
sigprocmask() は呼びだしスレッドのシグナルマスクを設定, 取得 します.
sigsuspend
sigsuspend()set 中のシグナルの一つがスレッドへ非同 期に配送されるまで, 呼びだしスレッドだけをブロックすることを除いて, POSIX.1 の定義と同一です.
sigpending
sigpending() は, スレッドでペンディングされているシグナルと, プロセスでペンディングされているシグナルとの和を返すことを除いて, POSIX.1 の定義と同一です.
pause
pause() は, シグナルが配送され, シグナル捕捉関数が実行される まで, 呼びだしスレッドをブロックさせます.

シグナルマスクの操作

#include <signal.h>

int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set , int sig);
int sigdelset(sigset_t *set, int sig);
int sigismember(sigset_t *set, int sig);

これらの関数は, シグナルマスクを操作します. これらの関数は sigset_t 型の変数を操作するだけで, スレッドのシグナルマスクに は影響を与えません.

sigemptyset
sigemptyset()set で指定されたシグナルマスク中の全ての シグナルを0に初期化します.
sigfillset
sigfillset()set で指定されたシグナルマスク中の全ての シグナルを1に初期化します.
sigaddset
sigaddset()set で指定されたシグナルマスクに sig で指定したシグナルを追加します.
sigdelset
sigdelset()set で指定されたシグナルマスクから sig で指定したシグナルを削除します.
sigismember
sigismember()set で指定されたシグナルマスク中に sig で指定したシグナルがメンバに存在するかを返します.

大域ジャンプ

#include <setjmp.h>

void longjmp(jmp_buf env,int val);
void siglongjmp(sigjmp_buf env, int val);
void setjmp(jmp_buf env);
void sigsetjmp(sigjmp_buf env, int savemask);

longjmp(), siglongjmp() はそれぞれ setjmp(), sigsetjmp() によって初期化された環境へとジャンプします. jmp_buf, sigjmp_buf が呼びだしスレッドによって初期化され なかった場合の動作は未定義です.

スレッド間での longjmp(), siglongjmp() はできません (longjmperror() が呼ばれます)

setjmp() および savemask が非0の sigsetjmp は, 呼び だし時にスレッドのシグナルマスクを保存し, 対応する longjmp(), siglongjmp() によってシグナルマスクを復帰させます.

setjmp() および siglongjmp() は, setjmp() あるい は sigsetjmp() を発行してから後にプッシュされた Cleanup ハンド ラを全て実行します.

アラーム

unsigned int alarm(unsigned int second);

alarm() を呼び出すことによって, SIGALRM シグナルが, alarm() を呼び出したスレッドに非同期に配送されます.

スレッドの実行の遅延

unsigned int sleep(unsigned int second);
int nanosleep(const struct timespec *sleep, struct timespec *remain);
void usleep(unsigned int usecond);
sleep
sleep()second で指定した実時間での秒数が経過するか, 呼 びだしスレッドにシグナルが配送されるまで, 呼びだしスレッドをブロックさせ ます. 返り値は second の残り時間で, シグナルで割り込まれない限りは 0です.
nanosleep
nanosleep() は, ナノセコンド単位で時間を指定できることを除いて, sleep() と同一です(ただし, 精度は実装に依存します. ). sleep で指定した実時間での時間が経過するか, 呼びだしスレッドにシ グナルが配送されるまで, 呼びだしスレッドをブロックさせます. remain がNULLでなければ, remain の指す場所には sleep の残り時間が格納されます.
usleep
usleep() は, 後方互換性のために用意されています. 引数で指定した時 間(単位はマイクロ秒), 呼びだしスレッドはブロックします. ブロック中にシグ ナルが配送された場合でも, スリープは継続されます.

シグナルの送信

int raise(int sig);

raise() はプログラムから明示的にシグナルを生成するために用い ます. POSIX.4a ではこの関数の効果は, kill(getpid(), sig) と 同一です. 指定したシグナルは, シグナルの番号によらず, 非同期に生成 されます.

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

#include <signal.h>

int pthread_kill(pthread_t thread, int sig);

pthread_kill() は, 指定したスレッドへ非同期にシグナルを送る ために用います.

kill() と同じように, エラーチェックのために sig として0 を与えることが出来ます. この場合シグナルは実際には送られません.

キャンセルのための関数

スレッドのキャンセル

#include <pthread.h>

int pthread_cancel(pthread_t thread);

pthread_cancel() は, thread のキャンセルを要求します.

Interruptibility state の設定

#include <pthread.h>

int pthread_setintr(int state);
int pthread_setintrtype(int type);
pthread_setintr
pthread_setintr() は呼びだしスレッドのキャンセル許可フラグを state に設定し, 以前のキャンセル許可フラグを返します. state は PTHREAD_INTR_ENABLE, PTHREAD_INTR_DISABLE のいずれかで す. PTHREAD_INTR_ENABLE の時は state を設定した後, pthread_setintr() は割り込みポイントになります.
pthread_setintrtype
pthread_setintrtype() は呼びだしスレッドの キャンセルタイプを type に設定し, 以前のキャンセルタイプを返します. typePTHREAD_INTR_CONTROLLED, PTHREAD_INTR_ASYNCHRONOUS のいず れかです.

キャンセルのテスト

#include <pthread.h>

void pthread_testintr(void);
pthread_testintr
pthread_testintr() は呼びだしスレッドに割り込みポイントを作りま す. スレッドがこの関数を実行する前に, キャンセル要求がなされていて, キャ ンセル許可フラグが PTHREAD_INTR_ENABLE の場合, キャンセルが実行されま す. pthread_testintr() は, キャンセル許可フラグが PTHREAD_INTR_DISABLE の場合は, なんの効果もありません.

Cleanup ハンドラの設定

#include <pthread.h>

void pthread_cleanup_push(void (*routine)(void *arg), void *arg);
void pthread_cleanup_pop(int execute);
void pthread_cleanup_push_f_np(void (*routine)(void *arg), void *arg);
void pthread_cleanup_pop_f_np(int execute);
pthread_cleanup_push
pthread_cleanup_push()routine を呼び出しスレッドの cleanup スタックに push します. Cleanup ルーチンは以下の場合にスタック から pop され, 実行されます.
pthread_cleanup_pop
pthread_cleanup_pop() は, 呼びだしスレッドの cleanup スタックの トップからルーチンを削除します. execute が 0 でない場合は, 削除 するルーチンを実行します.
pthread_cleanup_push_f_np
pthread_cleanup_push() の関数版です.
pthread_cleanup_pop_f_np
pthread_cleanup_pop() の関数版です.

pthread_cleanup_push(), pthread_cleanup_pop() は高速化のた めマクロとして実装されています. このため, これらの関数は同一の lexical scope でペアとなって現れなければなりません (つまり, pthread_cleanup_push() は最初の文字が `{' で始まる文字列を導き, pthread_cleanup_pop() は最後の文字が `}' で終わる文字列を導くと いうことです). この制限がネックとなる場合には, 関数版の pthread_cleanup_push_f_np(), pthread_cleanup_pop_f_np() を 利用して下さい.

pthread_cleanup_push() でプッシュした Cleanup ハンドラを pthread_cleanlup_pop_f_np() でポップすることは構いません. (こ の場合でも, 対応する lexical scope に pthread_cleanup_pop() が存 在しなければなりません.)

マッチしない pthread_cleanup_push() (あるいは pthread_cleanup_push_f_np()) と pthread_cleanup_pop() (あ るいは pthread_cleanup_pop_f_np()) がマッチしていない時の longjmp(), siglongjmp() の呼出しの結果は, 未定義です. Cleanup ハンドラからの longjmp(), siglongjmp() の呼出しの 結果も未定義です.

ログのための関数

#include <pthread.h>

extern int pthread_log_np(const char *format, ...);

この関数を用いて, ログファイル(See section ログ機能について.)に, 任意の文字 列を出力することが可能です. format は, printf 形式のフォーマット 文字列で, 後に任意個数の引数が続きます.

リエントラント関数

この章では, リエントラント化された関数について述べます.

時間・時刻関数

#include <time.h>

struct tm *localtime_r(const time_t *clock, struct tm *result);
struct tm *gmtime_r(const time_t *clock, struct tm *result);
char *asctime_r(const struct tm *tm, char *buf, int buflen);
char *ctime_r(const time_t *clock, char *buf, int buflen);

これらの関数は, localtime(), gmtime(), asctime(), ctime() のスレッド対応版です. 引数のポインタの指す領域に返るよう に変更されています.

asctime_r(), ctime_r() は, 引数で指定したバッファのサイ ズが不足していると, errno = ERANGE としてヌルポインタを返します.

文字列関数

#include <string.h>

char *strtok_r(char *s, const char *sep, char **lasts);

strtok() のスレッド対応版です.

最初の呼び出しでは, s にヌル文字で終了する文字列, sep にヌ ル文字で終了するセパレータ文字の文字列, lasts に char へのポイン タのアドレスを渡します. strtok_r() は文字列 s 中の最初の トークンへのポインタを返します. その際, トークンの直後にヌル文字を置き, lasts の指すポインタをそのヌル文字の直後を指すように更新します.

以降の呼び出しでは, s にはヌルポインタを渡し, lasts は変更 されていてはなりません. strtok_r() は, 呼び出すごとに次のトーク ンを返します. トークンが無くなるとヌルポインタが返ります.

ヒープメモリ操作関数

PTLでは, 以下のヒープメモリ操作関数は, 内部で逐次的に実行され るようになっているため, スレッドから安全に呼ぶことが出来ます.

extern void *malloc(size_t size);
extern void *realloc(void *ptr, size_t size);
extern void *calloc(size_t nelem, size_t elmsize);
extern void free(void *ptr);

標準入出力ライブラリ(stdio)

PTLでは, 以下の標準入出力ライブラリの関数群をスレッド対応にして います. これらの関数を実行中は, 指定したストリーム(FILE*)に対応す るデスクリプタが Mutex を用いてロックされます.

#include <stdio.h>

fclose	fdopen	fflush	fgetc	fgets	fopen	fprintf	fputc	fputs
fread	freopen	fscanf	fseek	ftell	fwrite	getc	getchar	gets
getw	printf	putc	putchar	puts	putw	rewind	scanf	setbuf
setbuffer	setlinebuf	setvbuf	sprintf	sscanf	ungetc	vfprintf
vprintf

さらに, 以下の関数が追加されています.

#include <stdio.h>

void flockfile(FILE *file);
void funlockfile(FILE *file);
int getc_unlocked(FILE *file);
int getchar_unlocked();
int putc_unlocked(char c, FILE *file);
int putchar_unlocked(char c);

flockfile() は, ファイル構造体 file をロックし, 呼び出し スレッドが独占的に使えるようにします. funlockfile() はロックを 解除します. このロックは, ネストしていても構いません. つまり, 複数回 flockfile() を呼び出し, 同じ数だけ funlockfile() を呼び 出した場合, 最後の funlockfile() の呼び出しの時にロックが解除さ れます.

getc_unlocked(), getchar_unlocked(), putc_unlocked(), putchar_unlocked() は, ロックされたファ イル構造体に対して働きます. これらは, _unlocked の付かないバー ジョンに比べて, 高速に動作します. (マクロとして実装されています).

テンポラリファイルの作成

#include <stdio.h>

char *mktemp(char *template);
int mkstemp(char *template);
char *tmpnam(char *s);
char *tempnam(const char *dir, const char *prefix);
FILE *tmpfile();

これらはテンポラリファイルを扱うための関数です. 複数のスレッドがこれらの 関数を並行に呼び出しても, 比較的安全にテンポラリファイルを得ることが出来 ます.

詳細は, UNIX のオンラインマニュアルを参照してください.

これらの関数のうち, ファイル名を得るもの (mktemp(), tmpnam(), tempnam()) は安全ではありません. これらの関数は 同一プロセス内ではユニークなファイル名を生成しますが, ファイル名の生成と, そのファイルの create の間にタイムラグがあるため, 他のプロセスによってそ のファイル名が使用される可能性があります. これらの関数は, 自分自身のプロ セスID をファイル名に埋め込むので, このような可能性はほとんど無いと思わ れますが, 新しいアプリケーションでは, mkstemp(), tmpfile() の使用をお勧めします.

入出力のための関数

PTLでは, 特定のスレッドのI/O 操作によってプロセス全体がブロックしないよ うに, 代替の I/O 関数を用意しています. これらの関数では, I/O 操作が直ち に終わらない場合, 呼びだしスレッドのみがブロックします.

これは, UNIX の非ブロックIOを用いることによって実現されています. 現在 のところ, ユーザが fcntl() を用いて非ブロックフラグ (FNDELAY) を設定しても, 無視されます.

#include <sys/types.h>
#include <sys/socket.h>

int	accept(int fd, struct sockaddr *addr, int *addrlen);
int	connect(int fd, struct sockaddr *name, int *namelen);
int	read(int fd, char *buf, int nbytes);
int	readv(int fd, struct iovec* iov, int iovcnt);
int	write(int fd, char *buf, int nbytes);
int	writev(int fd, struct iovec* iov, int iovcnt);
int	send(int fd, char *msg, int len, int flags);
int	recv(int fd, char *buf, int len, int flags);
int	recvfrom(int fd, char *buf, int len, int flags,
                 struct sockaddr *from, int *fromlen);
int	recvmsg(int fd, struct msghdr *msg, int flags);

write(), writev(), read(), readv() は, 不 可分に実行される保証はありません. すなわち, 複数のスレッドが同一のファ イル記述子で平行して I/O を行った場合, 入出力が「混ざる」可能性があり ます.

#include <sys/types.h>
#include <sys/time.h>

int	select(int nfds, fd_set *readfds, fd_set *writefds,
               fd_set *exceptfds, struct timeval *timeout);

複数の並行に動作するスレッドが同一のファイルデスクリプタに対して select() した場合, デスクリプタが有効になると, select() 中 の全てのスレッドが select() からリターンします. 複数のスレッ ドが同一のデスクリプタに対して select() することは勧められま せん.


Go to the first, previous, next, last section, table of contents.