Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       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 以降で利用できる。

属性

       この節で使用されている用語の説明については、 attributes(7) を参照。

       ┌─────────────────────┬───────────────┬─────────┐
       │インターフェース属性      │
       ├─────────────────────┼───────────────┼─────────┤
       │pthread_getattr_np() │ Thread safety │ MT-Safe │
       └─────────────────────┴───────────────┴─────────┘

準拠

       この関数は非標準の  GNU による拡張である。 そのため、名前に "_np" (nonportable; 移植性がな
       い) という接尾辞が 付いている。

       以下のプログラムは pthread_getattr_np() の使用例を示したものである。  このプログラムは、ス
       レッドを作成し、それから  pthread_getattr_np()  を使ってそのスレッドの属性 guard size、 ス
       タックアドレス、スタックサイズを取得し表示する。  コマンドライン引数での指定で、スレッドを
       作成する際に  上記の属性にデフォルト値以外の値を設定することができる。  下記のシェルのセッ
       ションはこのプログラムの使用例である。

       最初の実行例は、デフォルトの属性でスレッドが作成されている (x86-32 システム上で実行)。

           $ ulimit -s      # No stack limit ==> default stack size is 2 MB
           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          = %zu 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          = %#zx (%zu) 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;
           size_t 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 プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。