.\" Copyright (c) 2008 Linux Foundation, written by Michael Kerrisk
.\" <mtk.manpages@gmail.com>
.\"
-.\" Permission is granted to make and distribute verbatim copies of this
-.\" manual provided the copyright notice and this permission notice are
-.\" preserved on all copies.
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
.\"
-.\" Permission is granted to copy and distribute modified versions of this
-.\" manual under the conditions for verbatim copying, provided that the
-.\" entire resulting derived work is distributed under the terms of a
-.\" permission notice identical to this one.
-.\"
-.\" Since the Linux kernel and libraries are constantly changing, this
-.\" manual page may be incorrect or out-of-date. The author(s) assume no
-.\" responsibility for errors or omissions, or for damages resulting from
-.\" the use of the information contained herein. The author(s) may not
-.\" have taken the same level of care in the production of this manual,
-.\" which is licensed free of charge, as they might when working
-.\" professionally.
-.\"
-.\" Formatted or processed versions of this manual, if unaccompanied by
-.\" the source, must acknowledge the copyright and authors of this work.
-.\"
-.TH PTHREAD_CREATE 3 2012-08-03 "Linux" "Linux Programmer's Manual"
+.TH PTHREAD_CREATE 3 2021-03-22 "Linux man-pages (unreleased)" "Linux Programmer's Manual"
.SH NAME
pthread_create \- create a new thread
+.SH LIBRARY
+POSIX threads library
+.RI ( libpthread ", " \-lpthread )
.SH SYNOPSIS
.nf
.B #include <pthread.h>
-
-.BI "int pthread_create(pthread_t *" thread ", const pthread_attr_t *" attr ,
-.BI " void *(*" start_routine ") (void *), void *" arg );
+.PP
+.BI "int pthread_create(pthread_t *restrict " thread ,
+.BI " const pthread_attr_t *restrict " attr ,
+.BI " void *(*" start_routine ")(void *),"
+.BI " void *restrict " arg );
.fi
-.sp
-Compile and link with \fI\-pthread\fP.
.SH DESCRIPTION
The
.BR pthread_create ()
function starts a new thread in the calling process.
The new thread starts execution by invoking
.IR start_routine ();
-.IR arg
+.I arg
is passed as the sole argument of
.IR start_routine ().
-
+.PP
The new thread terminates in one of the following ways:
.IP * 2
It calls
.I attr
is NULL,
then the thread is created with default attributes.
-
+.PP
Before returning, a successful call to
.BR pthread_create ()
stores the ID of the new thread in the buffer pointed to by
.IR thread ;
this identifier is used to refer to the thread
in subsequent calls to other pthreads functions.
-
+.PP
The new thread inherits a copy of the creating thread's signal mask
.RB ( pthread_sigmask (3)).
The set of pending signals for the new thread is empty
The new thread does not inherit the creating thread's
alternate signal stack
.RB ( sigaltstack (2)).
-
+.PP
The new thread inherits the calling thread's floating-point environment
.RB ( fenv (3)).
-
+.PP
The initial value of the new thread's CPU-time clock is 0
(see
.BR pthread_getcpuclockid (3)).
.BR pthread_create ()
returns 0;
on error, it returns an error number, and the contents of
-.IR *thread
+.I *thread
are undefined.
.SH ERRORS
.TP
.B EAGAIN
-Insufficient resources to create another thread,
-or a system-imposed limit on the number of threads was encountered.
-The latter case may occur in two ways:
-the
-.BR RLIMIT_NPROC
+Insufficient resources to create another thread.
+.TP
+.B EAGAIN
+.\" NOTE! The following should match the description in fork(2)
+A system-imposed limit on the number of threads was encountered.
+There are a number of limits that may trigger this error: the
+.B RLIMIT_NPROC
soft resource limit (set via
.BR setrlimit (2)),
-which limits the number of process for a real user ID,
+which limits the number of processes and threads for a real user ID,
was reached;
-or the kernel's system-wide limit on the number of threads,
-.IR /proc/sys/kernel/threads-max ,
-was reached.
+the kernel's system-wide limit on the number of processes and threads,
+.IR /proc/sys/kernel/threads\-max ,
+was reached (see
+.BR proc (5));
+or the maximum number of PIDs,
+.IR /proc/sys/kernel/pid_max ,
+was reached (see
+.BR proc (5)).
.TP
.B EINVAL
Invalid settings in
.B EPERM
No permission to set the scheduling policy and parameters specified in
.IR attr .
-.SH CONFORMING TO
-POSIX.1-2001.
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.ad l
+.nh
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface Attribute Value
+T{
+.BR pthread_create ()
+T} Thread safety MT-Safe
+.TE
+.hy
+.ad
+.sp 1
+.SH STANDARDS
+POSIX.1-2001, POSIX.1-2008.
.SH NOTES
See
.BR pthread_self (3)
for further information on the thread ID returned in
-.IR *thread
+.I *thread
by
.BR pthread_create ().
Unless real-time scheduling policies are being employed,
.BR pthread_create (),
it is indeterminate which thread\(emthe caller or the new thread\(emwill
next execute.
-
+.PP
A thread may either be
.I joinable
or
.I attr
was set to create the thread in a detached state (using
.BR pthread_attr_setdetachstate (3)).
-
-.\" FIXME . Perhaps some of the following detail should be in
-.\" a future pthread_attr_setstacksize(3) page.
-On Linux/x86-32, the default stack size for a new thread is 2 megabytes.
+.PP
Under the NPTL threading implementation, if the
-.BR RLIMIT_STACK
+.B RLIMIT_STACK
soft resource limit
-.IR "at the time the program started"
+.I at the time the program started
has any value other than "unlimited",
then it determines the default stack size of new threads.
Using
.I attr
argument used to create a thread,
in order to obtain a stack size other than the default.
+If the
+.B RLIMIT_STACK
+resource limit is set to "unlimited",
+a per-architecture value is used for the stack size.
+Here is the value for a few architectures:
+.RS
+.TS
+allbox;
+lb lb
+l r.
+Architecture Default stack size
+i386 2 MB
+IA-64 32 MB
+PowerPC 4 MB
+S/390 2 MB
+Sparc-32 2 MB
+Sparc-64 4 MB
+x86_64 2 MB
+.TE
+.RE
.SH BUGS
In the obsolete LinuxThreads implementation,
each of the threads in a process has a different process ID.
This is in violation of the POSIX threads specification,
and is the source of many other nonconformances to the standard; see
.BR pthreads (7).
-.SH EXAMPLE
+.SH EXAMPLES
The program below demonstrates the use of
.BR pthread_create (),
as well as a number of other functions in the pthreads API.
-
+.PP
In the following run,
on a system providing the NPTL threading implementation,
the stack size defaults to the value given by the
"stack size" resource limit:
-
+.PP
.in +4n
-.nf
+.EX
.RB "$" " ulimit \-s"
-8192 # The stack size limit is 8 MB (0x80000 bytes)
+8192 # The stack size limit is 8 MB (0x800000 bytes)
.RB "$" " ./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
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS
-.fi
+.EE
.in
-
-In the next run, the program explicitly sets a stack size of 1MB (using
+.PP
+In the next run, the program explicitly sets a stack size of 1\ MB (using
.BR pthread_attr_setstacksize (3))
for the created threads:
-
+.PP
.in +4n
-.nf
+.EX
.RB "$" " ./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
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS
-.fi
+.EE
.in
.SS Program source
\&
-.nf
+.EX
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
-#define handle_error_en(en, msg) \\
+#define handle_error_en(en, msg) \e
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
-#define handle_error(msg) \\
+#define handle_error(msg) \e
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct thread_info { /* Used as argument to thread_start() */
};
/* Thread start function: display address near top of our stack,
- and return upper\-cased copy of argv_string */
+ and return upper\-cased copy of argv_string. */
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = arg;
- char *uargv, *p;
+ char *uargv;
- printf("Thread %d: top of stack near %p; argv_string=%s\\n",
- tinfo\->thread_num, &p, tinfo\->argv_string);
+ printf("Thread %d: top of stack near %p; argv_string=%s\en",
+ tinfo\->thread_num, (void *) &tinfo, tinfo\->argv_string);
uargv = strdup(tinfo\->argv_string);
if (uargv == NULL)
handle_error("strdup");
- for (p = uargv; *p != \(aq\\0\(aq; p++)
+ for (char *p = uargv; *p != \(aq\e0\(aq; p++)
*p = toupper(*p);
return uargv;
int
main(int argc, char *argv[])
{
- int s, tnum, opt, num_threads;
- struct thread_info *tinfo;
+ int s, opt, num_threads;
pthread_attr_t attr;
- int stack_size;
+ ssize_t stack_size;
void *res;
- /* The "\-s" option specifies a stack size for our threads */
+ /* The "\-s" option specifies a stack size for our threads. */
stack_size = \-1;
while ((opt = getopt(argc, argv, "s:")) != \-1) {
break;
default:
- fprintf(stderr, "Usage: %s [\-s stack-size] arg...\\n",
+ fprintf(stderr, "Usage: %s [\-s stack\-size] arg...\en",
argv[0]);
exit(EXIT_FAILURE);
}
num_threads = argc \- optind;
- /* Initialize thread creation attributes */
+ /* Initialize thread creation attributes. */
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
- /* Allocate memory for pthread_create() arguments */
+ /* Allocate memory for pthread_create() arguments. */
- tinfo = calloc(num_threads, sizeof(struct thread_info));
+ struct thread_info *tinfo = calloc(num_threads, sizeof(*tinfo));
if (tinfo == NULL)
handle_error("calloc");
- /* Create one thread for each command\-line argument */
+ /* Create one thread for each command\-line argument. */
- for (tnum = 0; tnum < num_threads; tnum++) {
+ for (int 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[] */
+ corresponding element of tinfo[]. */
s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &tinfo[tnum]);
}
/* Destroy the thread attributes object, since it is no
- longer needed */
+ 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 */
+ /* Now join with each thread, and display its returned value. */
- for (tnum = 0; tnum < num_threads; tnum++) {
+ for (int 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",
+ printf("Joined with thread %d; returned value was %s\en",
tinfo[tnum].thread_num, (char *) res);
free(res); /* Free memory allocated by thread */
}
free(tinfo);
exit(EXIT_SUCCESS);
}
-.fi
+.EE
.SH SEE ALSO
.ad l
.nh
.BR pthread_getattr_np (3),
.BR pthread_join (3),
.BR pthread_self (3),
+.BR pthread_setattr_default_np (3),
.BR pthreads (7)