]> git.ipfire.org Git - thirdparty/man-pages.git/blobdiff - man3/pthread_create.3
All pages: Replace the 4th argument to .TH by "Linux man-pages (unreleased)"
[thirdparty/man-pages.git] / man3 / pthread_create.3
index 8c6e7bbb97aa9e459dd016b98204a299685a28c2..8a894b329a2a0843d3cea16cdcc199d7c5e89f42 100644 (file)
@@ -1,48 +1,33 @@
 .\" 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
@@ -81,14 +66,14 @@ 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
@@ -96,10 +81,10 @@ 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)).
@@ -115,23 +100,30 @@ On success,
 .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
@@ -141,13 +133,30 @@ 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,
@@ -155,7 +164,7 @@ after a call to
 .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
@@ -175,14 +184,11 @@ 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)).
-
-.\" 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
@@ -191,26 +197,46 @@ 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 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
@@ -218,15 +244,15 @@ 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
-.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 1MB (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
@@ -234,11 +260,11 @@ 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
-.fi
+.EE
 .in
 .SS Program source
 \&
-.nf
+.EX
 #include <pthread.h>
 #include <string.h>
 #include <stdio.h>
@@ -247,10 +273,10 @@ Joined with thread 3; returned value was SERVUS
 #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() */
@@ -260,22 +286,22 @@ 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;
@@ -284,13 +310,12 @@ thread_start(void *arg)
 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) {
@@ -300,7 +325,7 @@ main(int argc, char *argv[])
             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);
         }
@@ -308,7 +333,7 @@ main(int argc, char *argv[])
 
     num_threads = argc \- optind;
 
-    /* Initialize thread creation attributes */
+    /* Initialize thread creation attributes. */
 
     s = pthread_attr_init(&attr);
     if (s != 0)
@@ -320,20 +345,20 @@ main(int argc, char *argv[])
             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]);
@@ -342,20 +367,20 @@ main(int argc, char *argv[])
     }
 
     /* 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 */
     }
@@ -363,7 +388,7 @@ main(int argc, char *argv[])
     free(tinfo);
     exit(EXIT_SUCCESS);
 }
-.fi
+.EE
 .SH SEE ALSO
 .ad l
 .nh
@@ -376,4 +401,5 @@ main(int argc, char *argv[])
 .BR pthread_getattr_np (3),
 .BR pthread_join (3),
 .BR pthread_self (3),
+.BR pthread_setattr_default_np (3),
 .BR pthreads (7)