[Prev] [Contents] [Next]

pthread_create()--Create a Thread

Syntax

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);
Threadsafe: Yes
Signal Safe: Yes

The pthread_create() function creates a thread with the specified attributes and runs the C function start_routine in the thread with the single pointer argument specified. The new thread may, but will not always, begin running before pthread_create() returns. If pthread_create() completes successfully, the Pthread handle is stored in the contents of the location referred to by thread.

If the start_routine returns normally, the effect will as if there was an implicit call to pthread_exit() using the return value of start_routine as the status. The function passed as start_routine should correspond to the following C function prototype:

void *threadStartRoutinName(void *);
If the thread attributes object represented by attr is modified later, the newly created thread is not affected. If attr is NULL, the default thread attributes are used.

With these declarations and initialization:

pthread_t t;
void *foo(void *);
pthread_attr_t attr;
pthread_attr_init(&pta);
The following three thread creation mechanisms are functionally equivalent:

rc = pthread_create(&t, NULL, foo, NULL);

rc = pthread_create(&t, &attr, foo, NULL);
The cancelation state of the new thread is PTHREAD_CANCEL_ENABLE, the cancelation type of the new thread is PTHREAD_CANCEL_DEFERRED.

The signal information maintained in the new thread will be as follows:

If you attempt to create a thread in a job that is not capable of starting threads, pthread_create() will fail with the EBUSY error. If you attempt to create a thread from a location in which thread creation is not allowed, pthread_create() will fail with the EBUSY error. See the pthread_getpthreadoption_np() function, option PTHREAD_OPTION_THREAD_CAPABLE_NP, for details on how to determine if thread creation is currently allowed in your process.

In the OS/400 implementation, the initial thread is special. Termination of the initial thread via pthread_exit() or any other thread termination mechanism will terminate the entire process.

The AS/400 implementation does not set a hard limit on the number of threads that can be created. PTHREAD_THREADS_MAX macro is implemented as a function call, and will return different values depending on the administrative setting of the maximum number of threads for the process. The default is NO MAX and has the numeric value of 2147483647 (0x7FFFFFFF). Realistically, the number of threads is limited by the amount of storage available to the job.

Currently, thread creation is not allowed after process termination has been started. For example, after a call to exit(), destructors for C++ static objects, functions registered with atexit() or CEE4RAGE() will be allowed to run. If these functions attempt to create a thread, pthread_create() will fail with the EBUSY error. Similar failures occur if other mechanisms are used to call pthread_create() after process termination has started.

Usage Notes

  1. If you attempt to create a thread in a job that is not capable of starting threads or for some other reason, thread creation is not allowed, pthread_create() will fail with the EBUSY error.
  2. For the best performance during thread creation, you should always pthread_join() or pthread_detach() a thread. This allows resources to be reclaimed or reused when the a thread terminates.
  3. The AS/400 implementation of threads allows the user ID to be changed on a per-thread basis. If, at the time the application creates the first thread, the application has not associated a process user identity with the job, the system will use the identity of the current user to set the process user identity for the job. The process user identity is used by some operating system support when operations that require authorization checks are done against a multi-threaded job from outside that job. The application can set the process user identity using the setpuid() API. See the setpuid() API documentation for more details.

Parameters

thread
(Output) Pthread handle to the created thread.
attr
(Input) The thread attributes object containing the attributes to be associated with the newly created thread. If NULL the default thread attributes are used.
start_routine
(Input) The function to be run as the new threads start routine.
arg
(Input) An address for the argument for the threads start routine.

Authorities and Locks

None.

Return Value

0
pthread_create() was successful.
value
pthread_create() was not successful. value is set to indicate the error condition.

Error Conditions

If pthread_create() was not successful, the error condition returned usually indicates one of the following errors. Under some conditions, the value returned could indicate an error other than those listed here.

[EINVAL]
The value specified for the argument is not correct.
[EAGAIN]
The system didn't have enough resources to create another thread or the maximum number of threads for this job has been reached
[EBUSY]
The system cannot allow thread creation in this process at this time.

Related Information

Example

#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include "check.h"

typedef struct {
  int   value;
  char  string[128];
} thread_parm_t;

void *threadfunc(void *parm)
{
  thread_parm_t *p = (thread_parm_t *)parm;
  printf("%s, parm = %d\n", p->string, p->value);
  free(p);
  return NULL;
}

int main(int argc, char **argv)
{
  pthread_t             thread;
  int                   rc=0;
  pthread_attr_t        pta;
  thread_parm_t        *parm=NULL;

  printf("Enter Testcase - %s\n", argv[0]);

  printf("Create a thread attributes object\n");
  rc = pthread_attr_init(&pta);
  checkResults("pthread_attr_init()\n", rc);

  /* Create 2 threads using default attributes in different ways */
  printf("Create thread using the NULL attributes\n");
  /* Set up multiple parameters to pass to the thread */
  parm = malloc(sizeof(thread_parm_t));
  parm->value = 5;
  strcpy(parm->string, "Inside secondary thread");
  rc = pthread_create(&thread, NULL, threadfunc, (void *)parm);
  checkResults("pthread_create(NULL)\n", rc);

  printf("Create thread using the default attributes\n");
  /* Set up multiple parameters to pass to the thread */
  parm = malloc(sizeof(thread_parm_t));
  parm->value = 77;
  strcpy(parm->string, "Inside secondary thread");
  rc = pthread_create(&thread, &pta, threadfunc, (void *)parm);
  checkResults("pthread_create(&pta)\n", rc);

  printf("Destroy thread attributes object\n");
  rc = pthread_attr_destroy(&pta);
  checkResults("pthread_attr_destroy()\n", rc);

  /* sleep() isn't a very robust way to wait for the thread */
  sleep(5);

  printf("Main completed\n");
  return 0;
}

Output

Enter Testcase - QP0WTEST/TPCRT0
Create a thread attributes object
Create thread using the NULL attributes
Create thread using the default attributes
Destroy thread attributes object
Inside secondary thread, parm = 77
Inside secondary thread, parm = 5
Main completed



[Prev] [Contents] [Next]
Copyright © 1998, IBM Corporation. All rights reserved.
Comments? Contact
rchthrds@us.ibm.com