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

第 3 章 スレッドの属性

前章では、デフォルト属性を使ったスレッド生成の基礎について説明しました。この章では、スレッド生成時における属性の設定方法を説明します。

属性オブジェクト

属性は、デフォルトのスレッド作成動作とは異なる動作を指定するための手段を提供します。pthread_create(3C) でスレッドを生成する場合、または同期変数を初期化する場合は、属性オブジェクトを指定できます。通常は、デフォルトで間に合います。

属性オブジェクトはプログラマからは「不透明」なため、代入によって直接変更できません。各オブジェクト型を初期化、設定、または削除するための関数のセットが用意されています。

いったん初期化して設定した属性は、プロセス全体に適用されます。属性を使用するための望ましいやり方は、必要なすべての状態の指定をプログラム実行の初期の段階で一度に設定することです。そうすれば、必要に応じて適切な属性オブジェクトを参照できます。

属性オブジェクトを使用することには、主に次の 2 つの利点があります。

属性オブジェクトの取り扱いで注意を要するのは、プロセス終了時です。オブジェクトが初期化されるときにメモリーが割り当てられます。このメモリーをシステムに戻す必要があります。pthread 規格には、属性オブジェクトを削除する関数呼び出しが用意されています。

pthreads 関数を使用すると、スレッド属性オブジェクトを操作できます。これらの関数は、次の各節で説明されています。

属性の初期化

オブジェクト属性をデフォルト値に初期化するには、pthread_attr_init(3C) を使用します。その記憶領域は、実行中にスレッドシステムによって割り当てられます。

pthread_attr_init の構文

int pthread_attr_init(pthread_attr_t *tattr);
#include <pthread.h>

pthread_attr_t tattr;
int ret;

/* initialize an attribute to the default value */
ret = pthread_attr_init(&tattr);

表 3–1 は、属性 (tattr) のデフォルト値の一覧です。

表 3–1 tattr のデフォルト属性値

属性 

値 

結果 

scope

PTHREAD_SCOPE_PROCESS

新しいスレッドはプロセス内のほかのスレッドと競合します。 

detachstate

PTHREAD_CREATE_JOINABLE

スレッドの終了後に終了状態とスレッド ID が保存されます。

stackaddr

NULL

新しいスレッドはシステムによって割り当てられたスタックアドレスを持ちます。 

stacksize

新しいスレッドはシステムによって定義されたスタックサイズを持ちます。 

priority

新しいスレッドは優先順位 0 を持ちます。 

inheritsched

PTHREAD_EXPLICIT_SCHED

新しいスレッドは親スレッドのスケジューリング優先順位を継承しません。 

schedpolicy

SCHED_OTHER

新しいスレッドは、従来の Solaris タイムシェアリング (TS) スケジューリングクラスを使用します。 

guardsize

PAGESIZE

スタックオーバーフローの保護。 


注 –

inheritsched 属性のデフォルト値は、将来の Solaris リリースでは PTHREAD_EXPLICIT_SCHED から PTHREAD_INHERIT_SCHED に変更される可能性があります。この変更によって問題が発生する可能性を避けるために、デフォルト値を受け入れるのではなく、pthread_attr_setinheritsched() を呼び出して inheritsched 属性を希望する値に設定するようにしてください。


pthread_attr_init の戻り値

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


ENOMEM

説明:

メモリーが不足し、スレッド属性オブジェクトを初期化できないときに返されます。

属性の削除

初期化時に割り当てられた記憶領域を削除するには、pthread_attr_destroy(3C) を使用します。その属性オブジェクトは無効になります。

pthread_attr_destroy の構文

int pthread_attr_destroy(pthread_attr_t *tattr);
#include <pthread.h>

pthread_attr_t tattr;
int ret;

/* destroy an attribute */
ret = pthread_attr_destroy(&tattr); 

pthread_attr_destroy の戻り値

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


EINVAL

説明:

tattr の値が無効です。

切り離し状態の設定

スレッドを切り離された状態 (PTHREAD_CREATE_DETACHED) として生成すると、そのスレッドが終了するとすぐに、そのスレッド識別子とその他のリソースを再利用できます。呼び出しスレッドがスレッドの終了を待機しない場合は、pthread_attr_setdetachstate(3C) を使用してください。

pthread_attr_setdetachstate(3C) の構文

int pthread_attr_setdetachstate(pthread_attr_t *tattr,int detachstate);
#include <pthread.h> 
pthread_attr_t tattr; 
int ret; 
/* set the thread detach state */
ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);

PTHREAD_CREATE_JOINABLE により、スレッドが切り離されていない状態で生成された場合、アプリケーションはこのスレッドの完了を待機します。つまり、プログラムはスレッド上で pthread_join() を実行します。

スレッドが切り離された状態で生成されたか切り離されていない状態で生成されたかに関係なく、すべてのスレッドが終了するまでプロセスは終了しません。処理途中で main() から復帰することによって生じるプロセスの終了については、「スレッド終了処理の完了」を参照してください。


注 –

明示的な同期によって阻止されなければ、そのスレッドの生成元が pthread_create() から復帰する前に、新たに生成される切り離されたスレッドが終了し、そのスレッド識別子が別の新しいスレッドに割り当てられることがあります。


切り離されていないスレッドには、終了後にほかのスレッドが終了待ちを行う必要があります。そうしないと、このスレッドのリソースが新しいスレッドに解放されず、メモリーリークが発生することになります。終了待ちを行うつもりがない場合は、スレッド作成時に切り離されたスレッドとして作成してください。


例 3–1 切り離されたスレッドの生成

#include <pthread.h>

pthread_attr_t tattr;
pthread_t tid;
void *start_routine;
void arg
int ret;

/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
ret = pthread_attr_setdetachstate (&tattr,PTHREAD_CREATE_DETACHED);
ret = pthread_create (&tid, &tattr, start_routine, arg);

pthread_attr_setdetachstate の戻り値

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


EINVAL

説明:

detachstate または tattr の値が無効です。

切り離し状態の取得

スレッドの生成状態 (切り離された状態または切り離されていない状態) を取得するには、pthread_attr_getdetachstate(3C) を使用します。

pthread_attr_getdetachstate の構文

int pthread_attr_getdetachstate(const pthread_attr_t *tattr, int *detachstate;
#include <pthread.h> 
pthread_attr_t tattr; 
int detachstate; 
int ret; 
/* get detachstate of thread */ 
ret = pthread_attr_getdetachstate (&tattr, &detachstate);

pthread_attr_getdetachstate の戻り値

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


EINVAL

説明:

detachstate の値が NULL か、tattr の値が無効です。

スタックガードのサイズの設定

attr オブジェクトの guardsize (ガードサイズ) を設定するには、pthread_attr_setguardsize(3C) を使用します。

pthread_attr_setguardsize(3C) の構文

#include <pthread.h> 
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

guardsize 属性をアプリケーションで使用する目的は、次の 2 つです。

guardsize 引数は、スタックポインタのオーバーフローを防ぐためのものです。スレッドのスタックがガードとともに作成された場合、実装はスタックのオーバーフローの終わりに追加のメモリーを割り当てます。この追加メモリーは、スタックポインタのスタックオーバーフローに対するバッファーとして動作します。このバッファーにアプリケーションがオーバーフローすると、スレッドに SIGSEGV シグナルが配信されるなどのエラーが発生します。

guardsize が 0 の場合は、attr を使って作成したスレッドにはガード領域が含まれません。guardsize が 0 よりも大きい場合は、少なくとも guardsize バイトのガード領域が、attr を使って作成した各スレッドに割り当てられます。デフォルトでは、スレッドは実装で定義された 1 バイト以上のガード領域を持ちます。

準拠実装では、guardsize に含まれる値を、設定可能なシステム変数 PAGESIZE の倍数に切り上げることが認められています。sys/mman.hPAGESIZE を参照してください。実装が guardsize の値を PAGESIZE の倍数に切り上げる場合は、attr を指定して pthread_attr_getguardsize() を呼び出すと、guardsize には前回 pthread_attr_setguardsize() を呼び出したときに指定されたガードサイズが使用されます。

pthread_attr_setguardsize の戻り値

pthread_attr_setguardsize() は、以下の場合に失敗します。


EINVAL

説明:

引数 attr が無効であるか、引数 guardsize が無効であるか、あるいは guardsize に無効な値が含まれています。

スタックガードのサイズの取得

attr オブジェクトの guardsize (ガードサイズ) を取得するには、pthread_attr_getguardsize(3C) を使用します。

pthread_attr_getguardsize の構文

#include <pthread.h>

int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, 
size_t  *restrict guardsize);

準拠実装では、guardsize に含まれる値を、設定可能なシステム変数 PAGESIZE の倍数に切り上げることが認められています。sys/mman.hPAGESIZE を参照してください。実装が guardsize の値を PAGESIZE の倍数に切り上げる場合は、attr を指定して pthread_attr_getguardsize() を呼び出すと、guardsize には前回 pthread_attr_setguardsize() を呼び出したときに指定されたガードサイズが使用されます。

pthread_attr_getguardsize の戻り値

pthread_attr_getguardsize() は、以下の場合に失敗します。


EINVAL

説明:

引数 attr が無効であるか、引数 guardsize が無効であるか、あるいは guardsize に無効な値が含まれています。

スコープの設定

スレッド PTHREAD_SCOPE_SYSTEM または PTHREAD_SCOPE_PROCESS の競合スコープを確立するには、pthread_attr_setscope(3C) を使用します。PTHREAD_SCOPE_SYSTEM スレッドは、システム内のすべてのスレッドと競合します。PTHREAD_SCOPE_PROCESS スレッドは、同じプロセス内のほかのスレッドと競合します。


注 –

結合スレッドと非結合スレッドの両方とも、指定されたプロセス内でのみアクセスできます。


pthread_attr_setscope の構文

int pthread_attr_setscope(pthread_attr_t *tattr,int scope);
#include <pthread.h>

pthread_attr_t tattr;
int ret;

/* bound thread */
ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);

/* unbound thread */
ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);

この例には、3 つの関数呼び出しがあります。 1 つめは属性を初期化する呼び出し、2 つめはデフォルト属性を変更する呼び出し、3 つめは pthread を生成する呼び出しです。

#include <pthread.h>

pthread_attr_t attr;
pthread_t tid;
void *start_routine(void *);
void *arg;
int ret;

/* initialized with default attributes */
ret = pthread_attr_init (&tattr);

ret =  pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
ret = pthread_create (&tid, &tattr, start_routine, arg);

pthread_attr_setscope の戻り値

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


EINVAL

説明:

tattr に設定しようとした値は無効です。

スコープの取得

スレッドスコープを取得するには、pthread_attr_getscope(3C) を使用します。

pthread_attr_getscope の構文

int pthread_attr_getscope(pthread_attr_t *restrict tattr, int *restrict scope);
#include <pthread.h>

pthread_attr_t tattr;
int scope;
int ret;

/* get scope of thread */
ret = pthread_attr_getscope(&tattr, &scope);

pthread_attr_getscope の戻り値

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


EINVAL

説明:

scope の値が NULL か、tattr の値が無効です。

スレッドの多重度の設定

pthread_setconcurrency(3C) は、標準規格に準拠するための関数です。アプリケーションは、この関数を使用して、スレッドライブラリに目標多重度を通知します。()Solaris 9 リリースに実装されているスレッドでは、このインタフェースは無効です。実行可能スレッドはすべて LWP に接続されます。

pthread_setconcurrency の構文

#include <pthread.h>

int pthread_setconcurrency(int new_level);

pthread_setconcurrency の戻り値

pthread_setconcurrency() は、次の条件で失敗します。


EINVAL

説明:

new_level で指定された値が負の値です。


EAGAIN

説明:

new_level で指定された値を使用するとシステムリソースの容量を超えます。

スレッドの多重度の取得

pthread_getconcurrency(3C) は、pthread_setconcurrency() を前回呼び出したときに設定された値を返します。

pthread_getconcurrency の構文

#include <pthread.h>

int pthread_getconcurrency(void);

pthread_setconcurrency() 関数が以前に呼び出されていない場合は、 pthread_getconcurrency() は 0 を返します。

pthread_getconcurrency の戻り値

pthread_getconcurrency() は常に、pthread_setconcurrency () を前回呼び出したときに設定された多重度を返します。pthread_setconcurrency() が呼び出されたことがない場合は、pthread_getconcurrency() は 0 を返します。

スケジューリングポリシーの設定

スケジューリングポリシーを設定するには、pthread_attr_setschedpolicy(3C) を使用します。POSIX 規格ではスケジューリングポリシーの値として、SCHED_FIFO (先入れ先出し)、SCHED_RR (ラウンドロビン)、SCHED_OTHER (実装で定義) を規定しています。Solaris OS の場合、SCHED_OTHER スレッドは、従来のタイムシェアリング (TS) スケジューリングクラスで実行されます。

pthread_attr_setschedpolicy(3C) の構文

int pthread_attr_setschedpolicy(pthread_attr_t *tattr, int policy);
#include <pthread.h> 
pthread_attr_t tattr; 
int policy; 
int ret; 

/* set the scheduling policy to SCHED_OTHER */ 
ret = pthread_attr_setschedpolicy(&tattr, SCHED_OTHER);

SCHED_FIFOSCHED_RR は POSIX 標準では任意とされており、リアルタイムスレッドについてのみサポートされています。

スケジューリングの詳細については、「スレッドのスケジューリング」を参照してください。

pthread_attr_setschedpolicy の戻り値

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


EINVAL

説明:

tattr に設定しようとした値は無効です。


ENOTSUP

説明:

サポートされていない属性値を設定しようとしました。

スケジューリングポリシーの取得

スケジューリングポリシーを取得するには、pthread_attr_getschedpolicy(3C) を使用します。

pthread_attr_getschedpolicy の構文

int pthread_attr_getschedpolicy(pthread_attr_t *restrict tattr,
            int *restrict policy);
#include <pthread.h> 
pthread_attr_t tattr; 
int policy; 
int ret; 

/* get scheduling policy of thread */ 
ret = pthread_attr_getschedpolicy (&tattr, &policy); 

pthread_attr_getschedpolicy の戻り値

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


EINVAL

説明:

policy の値が NULL か、tattr の値が無効です。

継承スケジューリングポリシーの設定

継承スケジューリングポリシーを設定するには、pthread_attr_setinheritsched(3C) を使用します。

pthread_attr_setinheritsched の構文

int pthread_attr_setinheritsched(pthread_attr_t *tattr, int inheritsched);
#include <pthread.h> 
pthread_attr_t tattr; 
int inheritsched; 
int ret; 

/* use  creating thread's scheduling policy and priority*/ 
ret = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);

inheritsched の値が PTHREAD_INHERIT_SCHED の場合は、生成スレッドのスケジューリングポリシーおよび優先順位が、作成されたスレッドのために使用されます。属性構造内のスケジューリングポリシーおよび優先順位は無視されます。inheritsched の値が PTHREAD_EXPLICIT_SCHED の場合は、属性構造のスケジューリングポリシーおよび優先順位が、作成されたスレッドのために使用されます。この場合、呼び出し元は、pthread_create() が成功するための十分な特権を持っている必要があります。

pthread_attr_setinheritsched の戻り値

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


EINVAL

説明:

tattr に設定しようとした値は無効です。

継承スケジューリングポリシーの取得

pthread_attr_getinheritsched(3C) は、属性構造に含まれている inheritsched 属性を返します。

pthread_attr_getinheritsched の構文

int pthread_attr_getinheritsched(pthread_attr_t *restrict tattr
       int *restrict inheritsched);
#include <pthread.h> 
pthread_attr_t tattr; 
int inheritsched; 
int ret; 
 
ret = pthread_attr_getinheritsched (&tattr, &inheritsched); 

pthread_attr_getinheritsched の戻り値

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


EINVAL

説明:

inherit の値が NULL か、tattr の値が無効です。

スケジューリングパラメータの設定

pthread_attr_setschedparam(3C) は、スケジューリングパラメータを設定します。

pthread_attr_setschedparam の構文

int pthread_attr_setschedparam(pthread_attr_t *restrict tattr,
         const struct sched_param *restrict param);
#include <pthread.h> 
pthread_attr_t tattr; 
int ret; 
int newprio; 
sched_param param; 
newprio = 30; 
/* set the priority; others are unchanged */ 
param.sched_priority = newprio; 
/* set the new scheduling param */ 
ret = pthread_attr_setschedparam (&tattr, &param); 

スケジューリングパラメータは param 構造体で定義します。ただし、サポートされるのは優先順位のパラメータだけです。

pthread_attr_setschedparam の戻り値

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


EINVAL

説明:

param の値が NULL か、tattr の値が無効です。

pthread の優先順位は、次のいずれかの方法で管理できます。

スケジューリングパラメータの取得

pthread_attr_getschedparam(3C) は、pthread_attr_setschedparam() で定義されたスケジューリングパラメータを返します。

pthread_attr_getschedparam の構文

int pthread_attr_getschedparam(pthread_attr_t *restrict tattr, 
       const struct sched_param *restrict param);
#include <pthread.h> 
pthread_attr_t attr; 
struct sched_param param; 
int ret; 
/* get the existing scheduling param */ 
ret = pthread_attr_getschedparam (&tattr, &param);

指定の優先順位をもつスレッドを生成する

スレッドを生成する前に優先順位属性を設定できます。子スレッドは、sched_param 構造体で指定された新しい優先順位で生成されます。この構造体にはその他のスケジューリング情報も含まれます。

優先順位を設定したスレッドの生成例

例 3–2 は、親スレッドとは異なった優先順位を持つ子スレッドを生成する例です。


例 3–2 優先順位を設定したスレッドの生成

#include <pthread.h>
#include <sched.h>

pthread_attr_t tattr;
pthread_t tid;
int ret;
int newprio = 20;
sched_param param;

/* initialized with default attributes */
ret = pthread_attr_init (&tattr);

/* safe to get existing scheduling param */
ret = pthread_attr_getschedparam (&tattr, &param);

/* set the priority; others are unchanged */
param.sched_priority = newprio;

/* setting the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, &param);

/* specify explicit scheduling */
ret = pthread_attr_setinheritsched (&tattr, PTHREAD_EXPLICIT_SCHED);

/* with new priority specified */
ret = pthread_create (&tid, &tattr, func, arg); 

pthread_attr_getschedparam の戻り値

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


EINVAL

説明:

param の値が NULL か、tattr の値が無効です。

スタックについて

通常、スレッドスタックはページ境界で始まります。指定したサイズはいずれも次のページ境界まで切り上げられます。アクセス権のないページはスタックのオーバーフローの最後に付加されます。このため、ほとんどのスタックオーバーフローで、違反したスレッドに SIGSEGV シグナルが送られるようになります。呼び出し側で割り当てられたスレッドスタックは、そのまま使用されます。

スタックを指定するときは、スレッドを PTHREAD_CREATE_JOINABLE として生成する必要があります。このスタックは、そのスレッドに対する pthread_join(3C) 呼び出しが終了まで解放できません。これは、スレッドが終了するまで、そのスレッドのスタックを解放できないからです。こうしたスレッドが確実に終了したことを確認するには、pthread_join(3C) を使用します。

スレッドへのスタック空間の割り当て

通常、スレッドにスタック空間を割り当てる必要はありません。システムは、各スレッドのスタックに対して、1M バイト (32 ビットシステムの場合) または 2M バイト (64 ビットシステムの場合) の仮想メモリーを割り当てます。スワップ空間は予約されません。システムは、mmap()MAP_NORESERVE オプションを使って割り当てを行います。

システムによって生成されたスレッドスタックは、それぞれレッドゾーンを持っています。システムはレッドゾーンとして、スタックオーバーフローを捕捉するためのページをスタックのオーバーフローの最後に付加します。このページは無効で、アクセスされるとメモリーフォルトになります。レッドゾーンは、自動的に割り当てられるすべてのスタックに付加されます。これは、そのサイズがアプリケーションで指定されたかデフォルトのサイズであるかに関係なく行われます。


注 –

実行時のスタック要件はライブラリ呼び出しや動的リンクによって異なります。したがって、指定したスタックがライブラリの呼び出しと動的リンクに必要な実行時要件を確実に満たすようにしなければなりません。


スタックとスタックサイズの一方または両方を指定するのが適正である場合はまれです。専門家であっても、適切なサイズを指定したかどうかを判断するのは困難です。ABI 準拠のプログラムでも、スタックサイズを静的に判定することはできません。スタックサイズは、プログラムが実行される、それぞれの実行環境に左右されます。

独自のスタックを構築する

スレッドスタックのサイズを指定するときは、呼び出される関数に必要な割り当てを計算してください。これには、呼び出し手続きで必要とされる量、局所変数、情報構造体が含まれます。

デフォルトスタックと少し違うスタックが必要になることがあります。たとえば、スレッドでデフォルトスタックサイズを超えるスタック空間が必要になる場合です。また、少しわかりにくいケースですが、デフォルトスタックが大きすぎる場合もあります。何千ものスレッドを生成する場合、デフォルトスタックでは合計サイズが数 G バイトにもなるため、仮想メモリーが足りず、それだけのスタック空間を扱えない可能性があります。

スタックサイズの上限は明らかであることが多いのですが、下限はどうでしょうか。スタックにプッシュされるスタックフレームを、その局所変数などを含めて、すべて扱えるだけのスタック空間が必要です。

スタックサイズの絶対最小値を取得するには、マクロ PTHREAD_STACK_MIN を呼び出します。マクロ PTHREAD_STACK_MIN は、NULL 手続きを実行するスレッドに必要な量のスタック空間を返します。実用的なスレッドに必要なスタック空間は最小スタックサイズより大きいので、スタックサイズを小さくするときは十分注意してください。

スタックサイズの設定

pthread_attr_setstacksize(3C) は、スレッドのスタックサイズを設定します。

pthread_attr_setstacksize の構文

int pthread_attr_setstacksize(pthread_attr_t *tattr, size_t size);
#include <pthread.h> 
#include <limits.h>
pthread_attr_t tattr; 
size_t size; 
int ret; 
size = (PTHREAD_STACK_MIN + 0x4000); 
/* setting a new size */ 
ret = pthread_attr_setstacksize(&tattr, size);

size 属性は、システムが割り当てるスタックのサイズ (バイト数) を定義します。このサイズ (size) は、システムで定義された最小のスタックサイズを下回ってはいけません。詳細については、「スタックについて」を参照してください。

size には、新しいスレッドが使用するスタックのバイト数が含まれます。size の値が 0 ならば、デフォルトのサイズが使われます。通常は 0 を指定してください。

PTHREAD_STACK_MIN は、スレッドを起動する上で必要なスタック空間の量です。このスタック空間には、アプリケーションコードを実行するための、スレッドルーチンの要求量は考慮されていません。


例 3–3 スタックサイズの設定の例

#include <pthread.h>
#include <limits.h>

pthread_attr_t tattr;
pthread_t tid;
int ret;

size_t size = PTHREAD_STACK_MIN + 0x4000;

/* initialized with default attributes */
ret = pthread_attr_init(&tattr);

/* setting the size of the stack also */
ret = pthread_attr_setstacksize(&tattr, size);

/* only size specified in tattr*/
ret = pthread_create(&tid, &tattr, start_routine, arg); 

pthread_attr_setstacksize の戻り値

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


EINVAL

説明:

size の値が PTHREAD_STACK_MIN より小さいか、またはシステムの制限を超過しているか、または tattr が無効です。

スタックサイズの取得

pthread_attr_getstacksize(3C) は、pthread_attr_setstacksize() で設定されたスタックサイズを返します。

pthread_attr_getstacksize の構文

int pthread_attr_getstacksize(pthread_attr_t *restrict tattr, size_t *restrict size);
#include <pthread.h> 
pthread_attr_t tattr; 
size_t size; 
int ret; 
/* getting the stack size */ 
ret = pthread_attr_getstacksize(&tattr, &size);

pthread_attr_getstacksize の戻り値

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


EINVAL

説明:

tattr または size が無効です。

スタックアドレスとサイズの設定

pthread_attr_setstack(3C) は、スタックアドレスとサイズを設定します。

pthread_attr_setstack(3C) の構文

int pthread_attr_setstack(pthread_attr_t *tattr,void *stackaddr, size_t stacksize);
#include <pthread.h> 
#include <limits.h>
pthread_attr_t tattr; 
void *base; 
size_t size; 
int ret; 
base = (void *) malloc(PTHREAD_STACK_MIN + 0x4000); 
/* setting a new address and size */ 
ret = pthread_attr_setstack(&tattr, base,PTHREAD_STACK_MIN + 0x4000);

stackaddr 属性は、スレッドのスタックのベースを定義します。stacksize 属性は、スタックサイズを指定します。stackaddr にデフォルトの NULL 以外が設定された場合、そのスタックはそのアドレスで初期化されます。このとき、スタックサイズは stacksize とみなされます。

base には、新しいスレッドが使用するスタックのアドレスが含まれます。baseNULL の場合、pthread_create(3C) は新しいスレッドに stacksize バイト以上のスタックを割り当てます。

pthread_attr_setstack(3C) の戻り値

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


EINVAL

説明:

base または tattr の値が正しくありません。stacksize の値が PTHREAD_STACK_MIN 未満です。

次の例は、独自のスタックアドレスとサイズを指定してスレッドを生成する方法を示します。

#include <pthread.h>

pthread_attr_t tattr;
pthread_t tid;
int ret;
void *stackbase;
size_t size;

/* initialized with default attributes */
ret = pthread_attr_init(&tattr);

/* setting the base address and size of the stack */
ret = pthread_attr_setstack(&tattr, stackbase,size);

/* address and size specified */
ret = pthread_create(&tid, &tattr, func, arg);

スタックアドレスとサイズの取得

pthread_attr_getstack(3C) は、pthread_attr_setstack() によって設定されたスレッドスタックアドレスおよびサイズを返します。

pthread_attr_getstack の構文

int pthread_attr_getstack(pthread_attr_t *restrict tattr,
         void **restrict stackaddr, size_t *restrict stacksize);
#include <pthread.h>

pthread_attr_t tattr;
void *base;
size_t size;
int ret;

/* getting a stack address and size */
ret = pthread_attr_getstack (&tattr
, &base, &size); 

pthread_attr_getstack の戻り値

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


EINVAL

説明:

tattr の値が不正です。