diff options
Diffstat (limited to 'man3/pthread_create.3')
-rw-r--r-- | man3/pthread_create.3 | 410 |
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) |