[Previous] [Contents] [Next]

ThreadCreate(), ThreadCreate_r()

Create a new thread

Synopsis:

#include <sys/neutrino.h>

int ThreadCreate( 
          pid_t pid,
          void* (func)( void* ),
          void* arg,
          const struct _thread_attr* attr );

int ThreadCreate_r( 
          pid_t pid,
          void* (func)( void* ),
          void* arg,
          const struct _thread_attr* attr );

Library:

libc

Description:

The ThreadCreate() and ThreadCreate_r() functions are identical except in the way they indicate errors. See the Returns section for details.

These kernel calls create a new thread of execution, with attributes specified by attr, within the process specified by pid. If pid is zero, the current process is used.


Note: Only the Process Manager can create threads in another process.

If attr is NULL, default attributes are used. If attr isn't NULL the attributes provided are used. If attr is modified subsequent to the call, the created thread isn't affected. The attr argument contains at least the following members:

int flags
See below for a list of flags. The default flag is always zero.
size_t stacksize
The stack size of the thread stack defined in the stackaddr member. If stackaddr is NULL, then stacksize specifies the size of stack to dynamically allocate. If stacksize is zero, then 4096 bytes are assumed. The minimum allowed stacksize is defined by PTHREAD_STACK_MIN.
void* stackaddr
The address of a user-provided stack. The size of the stack is given by the stacksize member. If a non-NULL stackaddr is provided, it's the responsibility of the user to release the stack on thread death. If stackaddr is NULL, then the kernel dynamically allocates a stack on thread creation and automatically releases it on the thread's death.
void* (exitfunc)(void* status)
The address to return to if the thread function returns.
Note: The thread returns to exitfunc. That means that the status variable isn't passed as a normal parameter. Instead it appears in the return value position dictated by the CPU's calling convention (e.g. EAX on an x86, R3 on PPC, V0 on MIPS, ...). The exitfunc function provided normally has to have compiler- and CPU-specific manipulation to access the status data (pulling it from the return register location to a proper local variable). Alternatively, the exitfunc function could be written in assembly language for each CPU.

int policy
The scheduling policy as defined by the SchedSet() kernel call. This member is only used if the PTHREAD_EXPLICIT_SCHED flag is set. If you wish to inherit the policy but specify the scheduling parameters in the param member you can set the PTHREAD_EXPLICIT_SCHED flag and pass SCHED_NOCHANGE for policy.
struct sched_param param
The scheduling parameters as defined by the SchedSet() kernel call. This member is only used if the PTHREAD_EXPLICIT_SCHED flag is set.

The attr argument's flags member can be set to:

PTHREAD_CREATE_JOINABLE (default), PTHREAD_CREATE_DETACHED
If create joinable is specified, the thread goes into a zombie state when it terminates. It stays in this state until its exit status is retrieved or it's detached. If create detached is specified, the thread is created in the detached state and doesn't become a zombie. The use of the newly created thread ID by ThreadJoin() is an error.
PTHREAD_INHERIT_SCHED (default), PTHREAD_EXPLICIT_SCHED
If inherit scheduling is specified, the thread inherits the scheduling attributes of the creating thread. If explicit scheduling is specified, then the scheduling policy and parameters are taken from the policy and param members of attr.
PTHREAD_SCOPE_SYSTEM (default), PTHREAD_SCOPE_PROCESS
If system scheduling scope is specified, then the thread is scheduled against all threads in the system. Since QNX implements true microkernel threads that only have a system scope, it's an error to specify process scheduling scope.
PTHREAD_MULTISIG_ALLOW (default), PTHREAD_MULTISIG_DISALLOW
If PTHREAD_MULTISIG_ALLOW is specified, then if the thread dies because of an unblocked, uncaught signal, all threads are terminated, which terminates the process. If PTHREAD_MULTISIG_DISALLOW is specified, then only this thread is terminated. All other threads in the process are unaffected.
PTHREAD_CANCEL_DEFERRED (default), PTHREAD_CANCEL_ASYNCHRONOUS
If cancel deferred is specified, cancellation occurs only at cancellation points as defined by the ThreadCancel() call. If cancel asynchronous is specified then every opcode executed by the thread is considered a cancellation point. The POSIX and C library aren't asynchronous cancel safe.

The thread is created executing at func() with arg as its sole argument. If func() returns, it returns to the address defined in the exitfunc member of attr.

The signal state of the new thread is initialized as follows:

The new thread shares all resources of the process in which it's created. This includes memory, timers, channels and connections. The standard C library contains mutexes to make it thread-safe.

Each thread contains a thread local storage area for its private data. This area can be accessed using the global variable _TLS defined in <sys/neutrino.h> as a pointer. The kernel ensures that _TLS always points to the thread local storage for the thread that's running. The thread local storage is defined by the structure _thread_local_storage and contains at least the following members:

void* (exitfunc)(void *)
The exit function to call if the thread returns.
void* arg
The sole argument that was passed to the thread.
int* errptr
A pointer to a thread unique errno value. For the main thread this points to the global variable errno. For all other threads this points to the member errval in this structure.
int errval
A thread unique errno used by all threads but the main thread.
int flags
The thread flags used on thread creation in addition to runtime flags used for implementing thread cancellation.
pid_t pid
The process ID that contains the thread.
int tid
The thread ID of the thread.
int ppid
The parent process ID of the process that contains the thread.

Blocking states

These calls don't block.

Returns:

The only difference between these functions is the way they indicate errors:

ThreadCreate()
The thread ID of the newly created thread. If an error occurs, -1 is returned and errno is set.
ThreadCreate_r()
The thread ID of the newly created thread. This function does NOT set errno. If an error occurs, the negative of a value from the Errors section is returned.

Errors:

EAGAIN
All kernel thread objects are in use.
EFAULT
A fault occurred when the kernel tried to access the buffers provided.
EINVAL
Invalid scheduling policy or priority specified.
ENOTSUP
PTHREAD_SCOPE_PROCESS was requested. All kernel threads are PTHREAD_SCOPE_SYSTEM.
EPERM
The calling thread doesn't have sufficient permission to create a thread in another process. Only a thread with a process ID of 1 can create threads in other processes.
ESRCH
The process indicated by pid doesn't exist.

Classification:

QNX 6

Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes

Caveats:

The QNX interpretation of PTHREAD_STACK_MIN is enough memory to run a thread that does nothing:

void nothingthread( void )
{
    return;
}

See also:

ThreadCancel(), ThreadDestroy()


[Previous] [Contents] [Next]