ThreadCreate(), ThreadCreate_r()

Create a 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 );

Arguments:

pid
The ID of the process that you want to create the thread in, or 0 to create the thread in the current process.
func
A pointer to the function that you want the thread to execute. The arg argument that you pass to ThreadCreate() is passed to func() as its sole argument. If func() returns, it returns to the address defined in the exitfunc member of attr.
arg
A pointer to any data that you want to pass to func.
attr
A pointer to a _thread_attr structure that specifies the attributes for the new thread, or NULL if you want to use the default attributes.

Note: If you modify the attributes after creating the thread, the thread isn't affected.

For more information, see Thread attributes,” below.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

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.

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


Note: Instead of using these kernel calls directly, consider calling pthread_create().

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.

Thread attributes

The _thread_attr structure pointed to by attr 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
NULL, or the address of a stack that you want the thread to use. Set the stacksize member to the size of the stack.

If you provide a non-NULL stackaddr, it's your responsibility to release the stack when the thread dies. 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. This 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, and so on).

The exitfunc function 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, you can write the exitfunc function in assembly language for each CPU.


int policy
The scheduling policy, as defined by the SchedSet() kernel call. This member is used only if you set the PTHREAD_EXPLICIT_SCHED flag. If you want the thread to inherit the policy, but you want to specify the scheduling parameters in the param member, set the PTHREAD_EXPLICIT_SCHED flag and set the policy member to SCHED_NOCHANGE.
struct sched_param param
A sched_param structure that specifies the scheduling parameters, as defined by the SchedSet() kernel call. This member is used only if you set the PTHREAD_EXPLICIT_SCHED flag.

You can set the attr argument's flags member to a combination of the following:

PTHREAD_CREATE_JOINABLE (default)
Put the thread into a zombie state when it terminates. It stays in this state until you retrieve its exit status or detach the thread.
PTHREAD_CREATE_DETACHED
Create the thread in the detached state; it doesn't become a zombie. You can't call ThreadJoin() for a detached thread.
PTHREAD_INHERIT_SCHED (default)
Use the scheduling attributes of the creating thread for the new thread.
PTHREAD_EXPLICIT_SCHED
Take the scheduling policy and parameters for the new thread from the policy and param members of attr.
PTHREAD_SCOPE_SYSTEM (default)
Schedule the thread against all threads in the system.
PTHREAD_SCOPE_PROCESS
Don't set this flag; the QNX Neutrino OS implements true microkernel threads that have only a system scope.
PTHREAD_MULTISIG_ALLOW (default)
If the thread dies because of an unblocked, uncaught signal, terminate all threads, and hence, the process.
PTHREAD_MULTISIG_DISALLOW
Terminate only this thread; all other threads in the process are unaffected.
PTHREAD_CANCEL_DEFERRED (default)
Cancellation occurs only at cancellation points as defined by ThreadCancel().
PTHREAD_CANCEL_ASYNCHRONOUS
Every opcode executed by the thread is considered a cancellation point. The POSIX and C library aren't asynchronous-cancel safe.

Signal state

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

Local storage for private data

Each thread contains a thread local storage area for its private data. You can get a pointer to this area by calling __tls() (defined in <sys/storage.h>).

The thread local storage is defined by the structure _thread_local_storage, which 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 that the thread uses if it isn't 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 ID of the process that contains the thread.
int tid
The thread's ID.

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, the function returns -1 and sets errno.
ThreadCreate_r()
The thread ID of the newly created thread. This function does NOT set errno. If an error occurs, the function returns the negative of a value from the Errors section.

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 Neutrino

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:

pthread_create(), sched_param, SchedSet(), ThreadCancel(), ThreadDestroy()