Manpages

名 前

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/ に 書 か れ て い る 。