summaryrefslogtreecommitdiffstats
path: root/man3/pthread_create.3
diff options
context:
space:
mode:
Diffstat (limited to 'man3/pthread_create.3')
-rw-r--r--man3/pthread_create.3410
1 files changed, 410 insertions, 0 deletions
diff --git a/man3/pthread_create.3 b/man3/pthread_create.3
new file mode 100644
index 0000000..268bfa0
--- /dev/null
+++ b/man3/pthread_create.3
@@ -0,0 +1,410 @@
+'\" 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 2023-07-20 "Linux man-pages 6.05.01"
+.SH NAME
+pthread_create \- create a new thread
+.SH LIBRARY
+POSIX threads library
+.RI ( libpthread ", " \-lpthread )
+.SH SYNOPSIS
+.nf
+.B #include <pthread.h>
+.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
+.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 ().
+.PP
+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.
+.PP
+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.
+.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
+.RB ( sigpending (2)).
+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)).
+.\" 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
+.sp 1
+.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.
+.PP
+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)).
+.PP
+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.
+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 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
+.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
+.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
+.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 <unistd.h>
+\&
+#define handle_error_en(en, msg) \e
+ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
+\&
+#define handle_error(msg) \e
+ 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\en",
+ 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]\e0\[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...\en",
+ 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\en",
+ 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)