Manpages

名 前

pthread_create − 新 し い ス レ ッ ド を 作 成 す る

書 式

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*
start_routine) (void *), void *arg);

−pthread を 付 け て コ ン パ イ ル と リ ン ク を 行 う 。

説 明

pthread_create() 関 数 は 、 呼 び 出 し た プ ロ セ ス 内 に 新 し い ス レ ッ ド を 作 成 す る 。 新 し い ス レ ッ ド の 実 行 は 、 start_routine() を 起 動 す る こ と で 開 始 さ れ る 。 start_routine() は 引 き 数 を 一 つ だ け 取 り 、 argstart_routine() の 引 き 数 と し て 渡 さ れ る 。 新 し く 作 成 さ れ た ス レ ッ ド は 、 以 下 の い ず れ か で 終 了 す る 。

* ス レ ッ ド が

pthread_exit(3) を 呼 び 出 す 。 pthread_exit(3) を 呼 び 出 す 際

に は 終 了 ス テ ー タ ス 値 を 指 定 す る 。 こ の 値 は pthread_join(3) を 呼 び 出 し た 同 じ プ ロ セ ス 内 の 別 の ス レ ッ ド で 参 照 で き る 。

* ス レ ッ ド が

start_routine() か ら 返 る 。 こ れ は 、 return 文 に 渡 し た 値 で

pthread_exit(3) を 呼 び 出 す の と 等 価 で あ る 。

* ス レ ッ ド が キ ャ ン セ ル さ れ る

(pthread_cancel(3) 参 照 )。

* プ ロ セ ス 内 の い ず れ か の ス レ ッ

ド で exit(3) が 呼 ば れ る か 、 メ イ ン ス レ ッ ド で main() 内 で return が 実 行 さ れ る 。 こ の 場 合 は 、 プ ロ セ ス 内 の 全 て の ス レ ッ ド が 終 了 さ れ る 。

attr 引 き 数 は pthread_attr_t 構 造 体 へ の ポ イ ン タ ー で あ り 、 pthread_attr_t 構 造 体 の 内 容 を 使 用 し て 、 ス レ ッ ド 作 成 時 に 新 し い ス レ ッ ド の 属 性 が 決 定 さ れ る 。 こ の 構 造 体 は pthread_attr_init(3) や 関 連 の 関 数 を 使 っ て 初 期 化 さ れ る 。 attr が NULL の 場 合 、 新 し い ス レ ッ ド は デ フ ォ ル ト の 属 性 で 作 成 さ れ る 。 成 功 し た 場 合 は 、 pthread_create() は 返 る 前 に 新 し い ス レ ッ ド の ID を thread が 指 す バ ッ フ ァ ー に 格 納 す る 。 こ の ID は 、 こ れ 以 降 に 他 の pthreads 関 数 の 呼 び 出 し で ス レ ッ ド を 参 照 す る の に 使 用 さ れ る 。 新 し い ス レ ッ ド は 、 ス レ ッ ド を 作 成 し た ス レ ッ ド の シ グ ナ ル マ ス ク (pthread_sigmask(3) 参 照 ) の コ ピ ー を 継 承 す る 。 新 し い ス レ ッ ド の 処 理 待 ち シ グ ナ ル (sigpending(2)) の 集 合 は 空 と な る 。 新 し い ス レ ッ ド は ス レ ッ ド を 作 成 し た ス レ ッ ド の 代 替 シ グ ナ ル ス タ ッ ク (sigaltstack(2)) を 継 承 し な い 。 新 し い ス レ ッ ド は 呼 び 出 し た ス レ ッ ド の 浮 動 小 数 点 環 境 (fenv(3)) を 継 承 す る 。 新 し い ス レ ッ ド の CPU 時 間 時 計 の 初 期 値 は 0 で あ る (pthread_getcpuclockid(3) 参 照 )。

Linux 固 有 の 詳 細 新 し い ス レ ッ ド は 、 呼 び 出 し た ス レ ッ ド の ケ ー パ ビ リ テ ィ セ ッ ト (capabilities(7) 参 照 ) と CPU affinity マ ス ク (sched_setaffinity(2) 参 照 ) の コ ピ ー を を 継 承 し な い 。

返 り 値

成 功 す る と 、 pthread_create() は 0 を 返 す 。 エ ラ ー の 場 合 は 、 エ ラ ー 番 号 が 返 さ れ 、 *thread の 内 容 は 不 定 で あ る 。

エ ラ ー

EAGAIN 別 の ス レ ッ ド を 作 成 す る の に 十 分 な リ ソ ー ス が な い 。

EAGAIN シ ス テ ム で 設 定 さ れ た ス レ ッ ド 数 の 上 限 に 達 し て い た 。 こ の エ ラ ー の 原 因 と な る 上 限 値 は い く つ か あ る 。 実 ユ ー ザ ー

ID 当 た り の プ ロ セ ス 数 と ス レ ッ ド 数 の 上 限 で あ る 、 ソ フ ト リ ソ ー ス 上 限 RLIMIT_NPROC に 達 し て い た (setrlimit(2) で 設 定 で き る )。 カ ー ネ ル の シ ス テ ム 全 体 の プ ロ セ ス と ス レ ッ ド の 数 の 上 限 値 で あ る /proc/sys/kernel/threads−max が 達 し て い た (proc(5) 参 照 )。 PID の 最 大 値 /proc/sys/kernel/pid_max に 達 し て い た (proc(5) 参 照 )。

EINVAL

attr で 指 定 さ れ た 設 定 が 不 正 で あ る 。

EPERM

attr に 指 定 さ れ た ス ケ ジ ュ ー リ ン グ ポ リ シ ー と パ ラ メ ー タ ー を 設 定 す る 許 可 が な い 。

準 拠

POSIX.1−2001.

注 意

pthread_create() が *thread で 返 す ス レ ッ ド ID に つ い て の 詳 し い 情 報 は pthread_self(3) を 参 照 の こ と 。 リ ア ル タ イ ム ス ケ ジ ュ ー リ ン グ ポ リ シ ー が 使 用 さ れ な い 限 り 、 pthread_create() の 呼 び 出 し 後 に 、 ど の ス レ ッ ド が —呼 び 出 し た ス レ ッ ド か 新 し い ス レ ッ ド か — 次 に 実 行 さ れ る か は 決 ま っ て い な い 。 ス レ ッ ド は join 可 能detached (切 り 離 さ れ た 状 態 ) の ど ち ら か に す る こ と が で き る 。 ス レ ッ ド が join 可 能 な 場 合 、 別 の ス レ ッ ド が pthread_join(3) を 使 っ て 終 了 し た ス レ ッ ド を 待 ち 、 終 了 ス テ ー タ ス を 取 得 す る こ と が で き る 。 終 了 し た join 可 能 な ス レ ッ ド は join さ れ た 場 合 に の み 、 そ の ス レ ッ ド の 最 後 に 残 っ た リ ソ ー ス が 解 放 さ れ シ ス テ ム に 戻 さ れ る 。 detached 状 態 の ス レ ッ ド が 終 了 す る と 、 そ の ス レ ッ ド の リ ソ ー ス は 自 動 的 に シ ス テ ム に 戻 さ れ る 。 detached 状 態 の ス レ ッ ド を join し て 、 そ の 終 了 ス テ ー タ ス を 取 得 す る こ と は で き な い 。 ス レ ッ ド を detached 状 態 に す る の は 、 そ の 終 了 ス テ ー タ ス を ア プ リ ケ ー シ ョ ン が 気 に す る 必 要 が な い あ る 種 の デ ー モ ン (daemon) ス レ ッ ド で は 有 用 で あ る 。 デ フ ォ ル ト で は 、 新 し い ス レ ッ ド は join 可 能 な 状 態 で 作 成 さ れ る 。 (pthread_attr_setdetachstate(3) を 使 っ て ) attr で ス レ ッ ド が detached 状 態 で 作 成 さ れ る よ う に 設 定 さ れ て い な い 限 り 、 join 可 能 な 状 態 で 作 成 さ れ る 。

Linux/x86−32 で は 、 新 し い ス レ ッ ド の デ フ ォ ル ト の ス タ ッ ク サ イ ズ は 2MB で あ る 。 NPTL ス レ ッ ド 実 装 の 下 で は 、 プ ロ グ ラ ム 開 始 時 の RLIMIT_STACK ソ フ ト リ ソ ー ス 上 限 が "unlimited" 以 外 の 場 合 、 そ の 値 が 新 し い ス レ ッ ド の デ フ ォ ル ト の ス タ ッ ク サ イ ズ と な る 。 pthread_attr_setstacksize(3) を 使 っ て 、 ス レ ッ ド を 作 成 す る 際 の attr 引 き 数 に 明 示 的 に ス タ ッ ク サ イ ズ 属 性 を 設 定 す る こ と で 、 デ フ ォ ル ト 値 以 外 の ス タ ッ ク サ イ ズ を 得 る こ と が で き る 。

バ グ

廃 止 予 定 の LinuxThreads 実 装 で は 、 プ ロ セ ス 内 の 各 ス レ ッ ド は 異 な る プ ロ セ ス ID を 持 つ 。 こ れ は POSIX ス レ ッ ド の 規 格 に 違 反 し て お り 、 他 の 多 く の 標 準 非 準 拠 の 点 の 原 因 に な っ て い る 。 pthreads(7) を 参 照 の こ と 。

以 下 の プ ロ グ ラ ム は 、 pthread_create() や pthreads API の 他 の い ろ い ろ な 関 数 の 使 用 例 を 示 し て い る 。 以 下 の 実 行 例 は 、 NPTL ス レ ッ ド 実 装 が 提 供 さ れ て い る シ ス テ ム で の も の で 、 ス タ ッ ク サ イ ズ が デ フ ォ ル ト 値 の "stack size" リ ソ ー ス 上 限 で 指 定 さ れ る 値 に な る 。

$ ulimit −s
8192 # The stack size limit is 8 MB (0x800000 bytes)
$ ./a.out hola salut servus
Thread 1: top of stack near 0xb7dd03b8; argv_string=hola
Thread 2: top of stack near 0xb75cf3b8; argv_string=salut
Thread 3: top of stack near 0xb6dce3b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS 次 の 実 行 例 で は 、 プ ロ グ ラ ム 内 で 、 作 成 さ れ る ス レ ッ ド に 対 し て (pthread_attr_setstacksize(3) を 使 っ て 1MB の ス タ ッ ク サ イ ズ を 明 示 的 に 設 定 し て い る 。

$ ./a.out −s 0x100000 hola salut servus
Thread 1: top of stack near 0xb7d723b8; argv_string=hola
Thread 2: top of stack near 0xb7c713b8; argv_string=salut
Thread 3: top of stack near 0xb7b703b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS プ ロ グ ラ ム の ソ ー ス

#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>

#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)

struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
int thread_num; /* Application−defined thread # */
char *argv_string; /* From command−line argument */ };

/* Thread start function: display address near top of our stack,
and return upper−cased copy of argv_string */

static void *
thread_start(void *arg)
{
struct thread_info *tinfo = arg;
char *uargv, *p;

printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo−>thread_num, &p, tinfo−>argv_string);

uargv = strdup(tinfo−>argv_string);
if (uargv == NULL)
handle_error("strdup");

for (p = uargv; *p != '\0'; p++)
*p = toupper(*p);

return uargv; }

int
main(int argc, char *argv[])
{
int s, tnum, opt, num_threads;
struct thread_info *tinfo;
pthread_attr_t attr;
int stack_size;
void *res;

/* The "−s" option specifies a stack size for our threads */

stack_size = −1;
while ((opt = getopt(argc, argv, "s:")) != −1) {
switch (opt) {
case 's':
stack_size = strtoul(optarg, NULL, 0);
break;

default:
fprintf(stderr, "Usage: %s [−s stack−size] arg...\n",
argv[0]);
exit(EXIT_FAILURE); } }

num_threads = argc − optind;

/* Initialize thread creation attributes */

s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");

if (stack_size > 0) {
s = pthread_attr_setstacksize(&attr, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize"); }

/* Allocate memory for pthread_create() arguments */

tinfo = calloc(num_threads, sizeof(struct thread_info));
if (tinfo == NULL)
handle_error("calloc");

/* Create one thread for each command−line argument */

for (tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].argv_string = argv[optind + tnum];

/* The pthread_create() call stores the thread ID into
corresponding element of tinfo[] */

s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &tinfo[tnum]);
if (s != 0)
handle_error_en(s, "pthread_create"); }

/* Destroy the thread attributes object, since it is no
longer needed */

s = pthread_attr_destroy(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy");

/* Now join with each thread, and display its returned value */

for (tnum = 0; tnum < num_threads; tnum++) {
s = pthread_join(tinfo[tnum].thread_id, &res);
if (s != 0)
handle_error_en(s, "pthread_join");

printf("Joined with thread %d; returned value was %s\n",
tinfo[tnum].thread_num, (char *) res);
free(res); /* Free memory allocated by thread */ }

free(tinfo);
exit(EXIT_SUCCESS); }

関 連 項 目

getrlimit(2), pthread_attr_init(3), pthread_cancel(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_getattr_np(3), pthread_join(3), pthread_self(3), pthreads(7)

こ の 文 書 に つ い て

こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。