'\" t
.\" Copyright (c) 2008 Linux Foundation, written by Michael Kerrisk
.\"     <mtk.manpages@gmail.com>
.\"
.\" SPDX-License-Identifier: Linux-man-pages-copyleft
.\"
.TH pthread_create 3 2024-12-13 "Linux man-pages 6.13"
.SH NAME
pthread_create \- create a new thread
.SH LIBRARY
POSIX threads library
.RI ( libpthread ,\~ \-lpthread )
.SH SYNOPSIS
.nf
.B #include <pthread.h>
.P
.BI "int pthread_create(pthread_t *restrict " thread ,
.BI "                   const pthread_attr_t *restrict " attr ,
.BI "                   typeof(void *(void *)) *" start_routine ,
.BI "                   void *restrict " arg );
.fi
.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 ();
.I arg
is passed as the sole argument of
.IR start_routine ().
.P
The new thread terminates in one of the following ways:
.IP \[bu] 3
It calls
.BR pthread_exit (3),
specifying an exit status value that is available to another thread
in the same process that calls
.BR pthread_join (3).
.IP \[bu]
It returns from
.IR start_routine ().
This is equivalent to calling
.BR pthread_exit (3)
with the value supplied in the
.I return
statement.
.IP \[bu]
It is canceled (see
.BR pthread_cancel (3)).
.IP \[bu]
Any of the threads in the process calls
.BR exit (3),
or the main thread performs a return from
.IR main ().
This causes the termination of all threads in the process.
.P
The
.I attr
argument points to a
.I pthread_attr_t
structure whose contents are used at thread creation time to
determine attributes for the new thread;
this structure is initialized using
.BR pthread_attr_init (3)
and related functions.
If
.I attr
is NULL,
then the thread is created with default attributes.
.P
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.
.P
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
.RB ( sigpending (2)).
The new thread does not inherit the creating thread's
alternate signal stack
.RB ( sigaltstack (2)).
.P
The new thread inherits the calling thread's floating-point environment
.RB ( fenv (3)).
.P
The initial value of the new thread's CPU-time clock is 0
(see
.BR pthread_getcpuclockid (3)).
.\" CLOCK_THREAD_CPUTIME_ID in clock_gettime(2)
.SS Linux-specific details
The new thread inherits copies of the calling thread's capability sets
(see
.BR capabilities (7))
and CPU affinity mask (see
.BR sched_setaffinity (2)).
.SH RETURN VALUE
On success,
.BR pthread_create ()
returns 0;
on error, it returns an error number, and the contents of
.I *thread
are undefined.
.SH ERRORS
.TP
.B EAGAIN
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 processes and threads for a real user ID,
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
.IR attr .
.TP
.\" FIXME . Test the following
.B EPERM
No permission to set the scheduling policy and parameters specified in
.IR attr .
.SH ATTRIBUTES
For an explanation of the terms used in this section, see
.BR attributes (7).
.TS
allbox;
lbx lb lb
l l l.
Interface	Attribute	Value
T{
.na
.nh
.BR pthread_create ()
T}	Thread safety	MT-Safe
.TE
.SH STANDARDS
POSIX.1-2008.
.SH HISTORY
POSIX.1-2001.
.SH NOTES
See
.BR pthread_self (3)
for further information on the thread ID returned in
.I *thread
by
.BR pthread_create ().
Unless real-time scheduling policies are being employed,
after a call to
.BR pthread_create (),
it is indeterminate which thread\[em]the caller or the new thread\[em]will
next execute.
.P
A thread may either be
.I joinable
or
.IR detached .
If a thread is joinable, then another thread can call
.BR pthread_join (3)
to wait for the thread to terminate and fetch its exit status.
Only when a terminated joinable thread has been joined are
the last of its resources released back to the system.
When a detached thread terminates,
its resources are automatically released back to the system:
it is not possible to join with the thread in order to obtain
its exit status.
Making a thread detached is useful for some types of daemon threads
whose exit status the application does not need to care about.
By default, a new thread is created in a joinable state, unless
.I attr
was set to create the thread in a detached state (using
.BR pthread_attr_setdetachstate (3)).
.P
Under the NPTL threading implementation, if the
.B RLIMIT_STACK
soft resource limit
.I at the time the program started
has any value other than "unlimited",
then it determines the default stack size of new threads.
Using
.BR pthread_attr_setstacksize (3),
the stack size attribute can be explicitly set in the
.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:
2 MB on most architectures; 4 MB on POWER and Sparc-64.
.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 EXAMPLES
The program below demonstrates the use of
.BR pthread_create (),
as well as a number of other functions in the pthreads API.
.P
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:
.P
.in +4n
.EX
.RB "$" " ulimit \-s"
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
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
.EE
.in
.P
In the next run, the program explicitly sets a stack size of 1\ MB (using
.BR pthread_attr_setstacksize (3))
for the created threads:
.P
.in +4n
.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
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
.EE
.in
.SS Program source
\&
.\" SRC BEGIN (pthread_create.c)
.EX
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
\&
#define handle_error_en(en, msg) \[rs]
        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
\&
#define handle_error(msg) \[rs]
        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;
\&
    printf("Thread %d: top of stack near %p; argv_string=%s\[rs]n",
           tinfo\->thread_num, (void *) &tinfo, tinfo\->argv_string);
\&
    uargv = strdup(tinfo\->argv_string);
    if (uargv == NULL)
        handle_error("strdup");
\&
    for (char *p = uargv; *p != \[aq]\[rs]0\[aq]; p++)
        *p = toupper(*p);
\&
    return uargv;
}
\&
int
main(int argc, char *argv[])
{
    int                 s, opt;
    void                *res;
    size_t              num_threads;
    ssize_t             stack_size;
    pthread_attr_t      attr;
    struct thread_info  *tinfo;
\&
    /* The "\-s" option specifies a stack size for our threads. */
\&
    stack_size = \-1;
    while ((opt = getopt(argc, argv, "s:")) != \-1) {
        switch (opt) {
        case \[aq]s\[aq]:
            stack_size = strtoul(optarg, NULL, 0);
            break;
\&
        default:
            fprintf(stderr, "Usage: %s [\-s stack\-size] arg...\[rs]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(*tinfo));
    if (tinfo == NULL)
        handle_error("calloc");
\&
    /* Create one thread for each command\-line argument. */
\&
    for (size_t 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 (size_t 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\[rs]n",
               tinfo[tnum].thread_num, (char *) res);
        free(res);      /* Free memory allocated by thread */
    }
\&
    free(tinfo);
    exit(EXIT_SUCCESS);
}
.EE
.\" SRC END
.SH SEE ALSO
.ad l
.nh
.BR getrlimit (2),
.BR pthread_attr_init (3),
.BR pthread_cancel (3),
.BR pthread_detach (3),
.BR pthread_equal (3),
.BR pthread_exit (3),
.BR pthread_getattr_np (3),
.BR pthread_join (3),
.BR pthread_self (3),
.BR pthread_setattr_default_np (3),
.BR pthreads (7)
