---
name: "pthread_create"
section: "3"
platform: "linux"
package: "man-pages"
version: "6.19-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux", "freebsd", "macos"]
url: "https://new.carta.tech/pthread_create"
---

# pthread\_create(3)

create a new thread

## NAME

pthread\_create - create a new thread

## LIBRARY

POSIX threads library (*libpthread*, *-lpthread*)

## SYNOPSIS

```
#include <pthread.h>
```

**int pthread\_create(pthread\_t \*restrict** *thread***,**                    **const pthread\_attr\_t \*\_Nullable restrict** *attr***,**                    **typeof(void \*(void \*\_Nullable)) \****start\_routine***,**                    **void \*\_Nullable restrict** *arg***);**

## DESCRIPTION

The **pthread\_create**() function starts a new thread in the calling process. The new thread starts execution by invoking *start\_routine*(); *arg* is passed as the sole argument of *start\_routine*().

The new thread terminates in one of the following ways:

- •

  It calls [**pthread\_exit**(3)](/pthread_exit/3.md), specifying an exit status value that is available to another thread in the same process that calls [**pthread\_join**(3)](/pthread_join/3.md).

- •

  It returns from *start\_routine*(). This is equivalent to calling [**pthread\_exit**(3)](/pthread_exit/3.md) with the value supplied in the *return* statement.

- •

  It is canceled (see [**pthread\_cancel**(3)](/pthread_cancel/3.md)).

- •

  Any of the threads in the process calls [**exit**(3)](/exit/3.md), or the main thread performs a return from *main*(). This causes the termination of all threads in the process.

The *attr* argument points to a *pthread\_attr\_t* structure whose contents are used at thread creation time to determine attributes for the new thread; this structure is initialized using [**pthread\_attr\_init**(3)](/pthread_attr_init/3.md) and related functions. If *attr* is NULL, then the thread is created with default attributes.

Before returning, a successful call to **pthread\_create**() stores the ID of the new thread in the buffer pointed to by *thread*; this identifier is used to refer to the thread in subsequent calls to other pthreads functions.

The new thread inherits a copy of the creating thread's signal mask ([**pthread\_sigmask**(3)](/pthread_sigmask/3.md)). The set of pending signals for the new thread is empty ([**sigpending**(2)](/sigpending/2.md)). The new thread does not inherit the creating thread's alternate signal stack ([**sigaltstack**(2)](/sigaltstack/2.md)).

The new thread inherits the calling thread's floating-point environment ([**fenv**(3)](/fenv/3.md)).

The initial value of the new thread's CPU-time clock is 0 (see [**pthread\_getcpuclockid**(3)](/pthread_getcpuclockid/3.md)).

### Linux-specific details

The new thread inherits copies of the calling thread's capability sets (see [**capabilities**(7)](/capabilities/7.md)) and CPU affinity mask (see [**sched\_setaffinity**(2)](/sched_setaffinity/2.md)).

## RETURN VALUE

On success, **pthread\_create**() returns 0; on error, it returns an error number, and the contents of *\*thread* are undefined.

## ERRORS

- **EAGAIN**

  Insufficient resources to create another thread.

- **EAGAIN**

  A system-imposed limit on the number of threads was encountered. There are a number of limits that may trigger this error: the **RLIMIT\_NPROC** soft resource limit (set via [**setrlimit**(2)](/setrlimit/2.md)), 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, */proc/sys/kernel/threads-max*, was reached (see [**proc**(5)](/proc/5.md)); or the maximum number of PIDs, */proc/sys/kernel/pid\_max*, was reached (see [**proc**(5)](/proc/5.md)).

- **EINVAL**

  Invalid settings in *attr*.

- **EPERM**

  No permission to set the scheduling policy and parameters specified in *attr*.

## ATTRIBUTES

For an explanation of the terms used in this section, see [**attributes**(7)](/attributes/7.md).

| | | |
| --- | --- | --- |
| **Interface** | **Attribute** | **Value** |
| **pthread\_create**() | Thread safety | MT-Safe |

## STANDARDS

POSIX.1-2008.

## HISTORY

POSIX.1-2001.

## NOTES

See [**pthread\_self**(3)](/pthread_self/3.md) for further information on the thread ID returned in *\*thread* by **pthread\_create**(). Unless real-time scheduling policies are being employed, after a call to **pthread\_create**(), it is indeterminate which thread—the caller or the new thread—will next execute.

A thread may either be *joinable* or *detached*. If a thread is joinable, then another thread can call [**pthread\_join**(3)](/pthread_join/3.md) 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 *attr* was set to create the thread in a detached state (using [**pthread\_attr\_setdetachstate**(3)](/pthread_attr_setdetachstate/3.md)).

Under the NPTL threading implementation, if the **RLIMIT\_STACK** soft resource limit *at the time the program started* has any value other than "unlimited", then it determines the default stack size of new threads. Using [**pthread\_attr\_setstacksize**(3)](/pthread_attr_setstacksize/3.md), the stack size attribute can be explicitly set in the *attr* argument used to create a thread, in order to obtain a stack size other than the default. If the **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.

## 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 [**pthreads**(7)](/pthreads/7.md).

## EXAMPLES

The program below demonstrates the use of **pthread\_create**(), as well as a number of other functions in the pthreads API.

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:

```
$ ulimit -s
8192            # The stack size limit is 8 MB (0x800000 bytes)
$ ./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
```

In the next run, the program explicitly sets a stack size of 1 MB (using [**pthread\_attr\_setstacksize**(3)](/pthread_attr_setstacksize/3.md)) for the created threads:

```
$ ./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
```

### Program source

```
#include <ctype.h>
#include <err.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
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\n",
           tinfo->thread_num, (void *) &tinfo, tinfo->argv_string);
    uargv = strdup(tinfo->argv_string);
    if (uargv == NULL)
        err(EXIT_FAILURE, "strdup");
    for (char *p = uargv; *p != '\0'; 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 's':
            stack_size = strtoul(optarg, NULL, 0);
            break;
        default:
            fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }
    }
    num_threads = argc - optind;
    /* Initialize thread creation attributes.  */
    s = pthread_attr_init(&attr);
    if (s != 0)
        errc(EXIT_FAILURE, s, "pthread_attr_init");
    if (stack_size > 0) {
        s = pthread_attr_setstacksize(&attr, stack_size);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
    }
    /* Allocate memory for pthread_create() arguments.  */
    tinfo = calloc(num_threads, sizeof(*tinfo));
    if (tinfo == NULL)
        err(EXIT_FAILURE, "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)
            errc(EXIT_FAILURE, s, "pthread_create");
    }
    /* Destroy the thread attributes object, since it is no
       longer needed.  */
    s = pthread_attr_destroy(&attr);
    if (s != 0)
        errc(EXIT_FAILURE, 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)
            errc(EXIT_FAILURE, s, "pthread_join");
        printf("Joined with thread %d; returned value was %s\n",
               tinfo[tnum].thread_num, (char *) res);
        free(res);      /* Free memory allocated by thread */
    }
    free(tinfo);
    exit(EXIT_SUCCESS);
}
```

## SEE ALSO

[**getrlimit**(2)](/getrlimit/2.md), [**pthread\_attr\_init**(3)](/pthread_attr_init/3.md), [**pthread\_cancel**(3)](/pthread_cancel/3.md), [**pthread\_detach**(3)](/pthread_detach/3.md), [**pthread\_equal**(3)](/pthread_equal/3.md), [**pthread\_exit**(3)](/pthread_exit/3.md), [**pthread\_getattr\_np**(3)](/pthread_getattr_np/3.md), [**pthread\_join**(3)](/pthread_join/3.md), [**pthread\_self**(3)](/pthread_self/3.md), [**pthread\_setattr\_default\_np**(3)](/pthread_setattr_default_np/3.md), [**pthreads**(7)](/pthreads/7.md)
