この章は, ライブラリのリファレンスマニュアルです.
#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 シグナルの状態の継承. を参照して下さい.
#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 シグナルの配送.)
#include <pthread.h> pthread_t pthread_self(void);
pthread_self()
は, この関数を呼び出したスレッドのIDを返します.
#include <pthread.h> int pthread_equal(pthread_t t1, pthread_t t2);
この関数はスレッド ID t1 と t2 を比較し, 同一のスレッド ならば非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()
によるスレッドの生成の際に利用されます.
#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
pthread_mutexattr_setpshared
pthread_mutexattr_getprotocol
pthread_mutexattr_getprotocol()
は attr の Mutex プ
ロトコル (See section プライオリティの逆転の回避.) を取得します.
pthread_mutexattr_setprotocol
pthread_mutexattr_setprotocol()
は attr に Mutex プ
ロトコルを設定します.
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
を返します.
#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 を破棄した場合の動作は未定義です. #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 をロックします.
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()
は Mutex のシーリングを返します.
pthread_mutex_setprio_ceiling()
は, Mutex をロックし, Mutex の
シーリングを変更し, Mutex を開放します.
もし, pthread_mutex_setprio_ceiling()
が失敗した場合, 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 が破棄されるまで有効な名前を指しています. #include <pthread.h> int pthread_mutex_waiters_np(pthread_mutex_t mutex);
この関数は, mutex でブロックしているスレッドの数を返します. この 返り値は, mutex がロックされている時のみ信頼できます.
#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
pthread_condattr_setpshared
#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 を破棄した場合の動作
は未定義です. #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 でブロックしているスレッドが存在しなけば何の効果もありませ
ん.
#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 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 がロックされている場合のみ信頼できます.
#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でない場合, その値を引数としてデストラクタ関数が呼ばれます. スレッ ドが終了する際に複数のデストラクタが存在した場合, デストラクタの呼ば れる順序は不定です.
#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
pthread_attr_setinheritsched
pthread_attr_getinheritsched
pthread_attr_setprio
pthread_attr_getprio
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 のどのスケジュー
リング属性も変更されません.
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 が返ります.
#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 のキャンセルを要求します.
#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 に設定し, 以前のキャンセルタイプを返します. type は
PTHREAD_INTR_CONTROLLED
, PTHREAD_INTR_ASYNCHRONOUS
のいず
れかです. #include <pthread.h> void pthread_testintr(void);
pthread_testintr
pthread_testintr()
は呼びだしスレッドに割り込みポイントを作りま
す. スレッドがこの関数を実行する前に, キャンセル要求がなされていて, キャ
ンセル許可フラグが PTHREAD_INTR_ENABLE
の場合, キャンセルが実行されま
す. pthread_testintr()
は, キャンセル許可フラグが
PTHREAD_INTR_DISABLE
の場合は, なんの効果もありません.
#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_exit()
の呼びだし)
pthread_cleanup_pop()
を 0 でない引数で呼び出
す
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);
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.