名 前
pthread_getattr_np − 作 成 さ れ た ス レ ッ ド の 属 性 を 取 得 す る
書 式
#define
_GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
−pthread で コ ン パ イ ル し て リ ン ク す る 。
説 明
pthread_getattr_np() 関 数 は 、 attr が 参 照 す る ス レ ッ ド 属 性 オ ブ ジ ェ ク ト を 初 期 化 し 、 そ の オ ブ ジ ェ ク ト に 実 行 中 の ス レ ッ ド thread の 実 際 の 属 性 値 を 格 納 し て 返 す 。 返 さ れ る 属 性 値 は 、 pthread_create(3) で ス レ ッ ド を 作 成 す る 際 に 使 わ れ た attr オ ブ ジ ェ ク ト で 渡 さ れ た 属 性 値 と 異 な る 場 合 が あ る 。 特 に 、 以 下 の 属 性 は 異 な る 場 合 が あ る 。
* |
detach state. join 可 能 な ス レ ッ ド は 作 成 後 に 自 分 自 身 を 切 り 離 す (detach す る ) こ と が で き る か ら で あ る 。 | ||
* |
ス タ ッ ク サ イ ズ 。 ス レ ッ ド の 実 装 に よ っ て 適 切 な 境 界 に 揃 え ら れ る 可 能 が あ る た め で あ る 。
* |
guard size. ス レ ッ ド の 実 装 に よ り ペ ー ジ サ イ ズ の 倍 数 に 切 り 上 げ ら れ た り 、 ア プ リ ケ ー シ ョ ン が 自 分 で ス タ ッ ク を 割 り 当 て る 場 合 に は 無 視 さ れ る (0 と し て 扱 わ れ る ) こ と が あ る か ら で あ る 。 |
さ ら に 、 ス レ ッ ド を 作 成 す る 際 に 使 用 さ れ た ス レ ッ ド 属 性 オ ブ ジ ェ ク ト で ス タ ッ ク ア ド レ ス が 設 定 さ れ て い な か っ た 場 合 、 返 さ れ た ス レ ッ ド 属 性 オ ブ ジ ェ ク ト で は ス レ ッ ド の 実 装 が そ の ス レ ッ ド に 割 り 当 て た 実 際 の ス タ ッ ク ア ド レ ス が 報 告 さ れ る 。
pthread_getattr_np() が 返 し た ス レ ッ ド 属 性 オ ブ ジ ェ ク ト が 必 要 な く な っ た 際 に は 、 pthread_attr_destroy(3) を 使 っ て そ の オ ブ ジ ェ ク ト を 破 棄 す べ き で あ る 。
返 り 値
成 功 す る と 、 こ の 関 数 は 0 を 返 す 。 エ ラ ー の 場 合 、 0 以 外 の エ ラ ー 番 号 を 返 す 。
エ ラ ー
ENOMEM メ モ リ ー が 十 分 に な か っ た 。 さ ら に 、 |
thread が メ イ ン ス レ ッ ド を 参 照 し て い る 場 合 に は 、 pthread_getattr_np() は 内 部 で 行 わ れ る 様 々 な 呼 び 出 し で の エ ラ ー で 失 敗 す る 可 能 性 が あ る 。 /proc/self/maps が オ ー プ ン で き な い 場 合 に は fopen(3) で エ ラ ー が 発 生 し 、 リ ソ ー ス 上 限 RLIMIT_STACK が サ ポ ー ト さ れ て い な い 場 合 に は getrlimit(2) で エ ラ ー が 発 生 す る 。
バ ー ジ ョ ン
こ の 関 数 は glibc バ ー ジ ョ ン 2.2.3 以 降 で 利 用 で き る 。
準 拠
こ の 関 数 は 非 標 準 の GNU に よ る 拡 張 で あ る 。 そ の た め 、 名 前 に "_np" (nonportable; 移 植 性 が な い ) と い う 接 尾 辞 が 付 い て い る 。
例
以 下 の プ ロ グ ラ ム は pthread_getattr_np() の 使 用 例 を 示 し た も の で あ る 。 こ の プ ロ グ ラ ム は 、 ス レ ッ ド を 作 成 し 、 そ れ か ら pthread_getattr_np() を 使 っ て そ の ス レ ッ ド の 属 性 guard size、 ス タ ッ ク ア ド レ ス 、 ス タ ッ ク サ イ ズ を 取 得 し 表 示 す る 。 コ マ ン ド ラ イ ン 引 き 数 で の 指 定 で 、 ス レ ッ ド を 作 成 す る 際 に 上 記 の 属 性 に デ フ ォ ル ト 値 以 外 の 値 を 設 定 す る こ と が で き る 。 下 記 の シ ェ ル の セ ッ シ ョ ン は こ の プ ロ グ ラ ム の 使 用 例 で あ る 。 最 初 の 実 行 例 は 、 デ フ ォ ル ト の 属 性 で ス レ ッ ド が 作 成 さ れ て い る (x86−32 シ ス テ ム 上 で 実 行 )。
$ ulimit
−s # No stack limit ==> default stack size is
2MB
unlimited
$ ./a.out
Attributes of created thread:
Guard size = 4096 bytes
Stack address = 0x40196000 (EOS = 0x40397000)
Stack size = 0x201000 (2101248) bytes 次 の
実 行 例 で は 、 guard
size が 指 定 さ れ た
場 合 、 guard size は シ
ス テ ム の ペ ー
ジ サ イ ズ の 倍
数 に 切 り 上 げ
ら れ る こ と が
分 か る (x86−32 で は
シ ス テ ム の ペ
ー ジ サ イ ズ は 4096
バ イ ト で あ る
)。
$ ./a.out
−g 4097
Thread attributes object after initializations:
Guard size = 4097 bytes
Stack address = (nil)
Stack size = 0x0 (0) bytes
Attributes of
created thread:
Guard size = 8192 bytes
Stack address = 0x40196000 (EOS = 0x40397000)
Stack size = 0x201000 (2101248) bytes 最 後
の 実 行 例 で は
、 プ ロ グ ラ ム
で ス レ ッ ド 用
の ス タ ッ ク を
手 動 で 割 り 当
て て い る 。 こ
の 場 合 に は 、 guard
size 属 性 は 無 視 さ
れ る 。
$ ./a.out
−g 4096 −s 0x8000 −a
Allocated thread stack at 0x804d000
Thread
attributes object after initializations:
Guard size = 4096 bytes
Stack address = 0x804d000 (EOS = 0x8055000)
Stack size = 0x8000 (32768) bytes
Attributes of
created thread:
Guard size = 0 bytes
Stack address = 0x804d000 (EOS = 0x8055000)
Stack size = 0x8000 (32768) bytes プ ロ
グ ラ ム の ソ ー
ス
#define _GNU_SOURCE /* To get
pthread_getattr_np() declaration */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define
handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while
(0)
static void
display_stack_related_attributes(pthread_attr_t *attr, char
*prefix)
{
int s;
size_t stack_size, guard_size;
void *stack_addr;
s =
pthread_attr_getguardsize(attr, &guard_size);
if (s != 0)
handle_error_en(s, "pthread_attr_getguardsize");
printf("%sGuard size = %d bytes\n", prefix,
guard_size);
s =
pthread_attr_getstack(attr, &stack_addr,
&stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_getstack");
printf("%sStack address = %p", prefix,
stack_addr);
if (stack_size > 0)
printf(" (EOS = %p)", (char *) stack_addr +
stack_size);
printf("\n");
printf("%sStack size = 0x%x (%d) bytes\n",
prefix, stack_size, stack_size); }
static void
display_thread_attributes(pthread_t thread, char *prefix)
{
int s;
pthread_attr_t attr;
s =
pthread_getattr_np(thread, &attr);
if (s != 0)
handle_error_en(s, "pthread_getattr_np");
display_stack_related_attributes(&attr, prefix);
s =
pthread_attr_destroy(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy"); }
static void *
/* Start function for thread we create */
thread_start(void *arg)
{
printf("Attributes of created thread:\n");
display_thread_attributes(pthread_self(),
"\t");
exit(EXIT_SUCCESS); /* Terminate all threads */ }
static void
usage(char *pname, char *msg)
{
if (msg != NULL)
fputs(msg, stderr);
fprintf(stderr, "Usage: %s [−s stack−size
[−a]]"
" [−g guard−size]\n", pname);
fprintf(stderr, "\t\t−a means program should
allocate stack\n");
exit(EXIT_FAILURE); }
static
pthread_attr_t * /* Get thread attributes from command line
*/
get_thread_attributes_from_cl(int argc, char *argv[],
pthread_attr_t *attrp)
{
int s, opt, allocate_stack;
long stack_size, guard_size;
void *stack_addr;
pthread_attr_t *ret_attrp = NULL; /* Set to attrp if we
initialize
a thread attributes object */
allocate_stack = 0;
stack_size = −1;
guard_size = −1;
while ((opt =
getopt(argc, argv, "ag:s:")) != −1) {
switch (opt) {
case 'a': allocate_stack = 1; break;
case 'g': guard_size = strtoul(optarg, NULL, 0); break;
case 's': stack_size = strtoul(optarg, NULL, 0); break;
default: usage(argv[0], NULL); } }
if
(allocate_stack && stack_size == −1)
usage(argv[0], "Specifying −a without −s
makes no sense\n");
if (argc >
optind)
usage(argv[0], "Extraneous command−line
arguments\n");
if (stack_size
>= 0 || guard_size > 0) {
ret_attrp = attrp;
s =
pthread_attr_init(attrp);
if (s != 0)
handle_error_en(s, "pthread_attr_init"); }
if (stack_size
>= 0) {
if (!allocate_stack) {
s = pthread_attr_setstacksize(attrp, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize"); }
else {
s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE),
stack_size);
if (s != 0)
handle_error_en(s, "posix_memalign");
printf("Allocated thread stack at %p\n\n",
stack_addr);
s =
pthread_attr_setstack(attrp, stack_addr, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize"); }
}
if (guard_size
>= 0) {
s = pthread_attr_setguardsize(attrp, guard_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
return ret_attrp; }
int
main(int argc, char *argv[])
{
int s;
pthread_t thr;
pthread_attr_t attr;
pthread_attr_t *attrp = NULL; /* Set to &attr if we
initialize
a thread attributes object */
attrp = get_thread_attributes_from_cl(argc, argv, &attr);
if (attrp !=
NULL) {
printf("Thread attributes object after
initializations:\n");
display_stack_related_attributes(attrp, "\t");
printf("\n"); }
s =
pthread_create(&thr, attrp, &thread_start, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
if (attrp !=
NULL) {
s = pthread_attr_destroy(attrp);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy"); }
pause(); /* Terminates when other thread calls exit() */ }
関 連 項 目
pthread_attr_getaffinity_np(3), pthread_attr_getdetachstate(3), pthread_attr_getguardsize(3), pthread_attr_getinheritsched(3), pthread_attr_getschedparam(3), pthread_attr_getschedpolicy(3), pthread_attr_getscope(3), pthread_attr_getstack(3), pthread_attr_getstackaddr(3), pthread_attr_getstacksize(3), pthread_attr_init(3), pthread_create(3), pthreads(7)
こ の 文 書 に つ い て
こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。