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.
For more information, see
Thread attributes,
below.
Note:
If you modify the attributes after creating the thread, the thread isn't affected.
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.
The ThreadCreate() and ThreadCreate_r()
functions are identical, except in the way they indicate errors.
See the Returns section for details.
Note:
- Only the Process Manager can create threads in another process.
- 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
- Zero or more of the following (the default of each pair of flags is always zero).
Joinable or detached:
- 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.
Scheduling inheritence:
- 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.
Scheduling scope:
- PTHREAD_SCOPE_SYSTEM (default) — schedule the thread against all threads in the system.
- PTHREAD_SCOPE_PROCESS — don't set this flag; the QNX Neutrino RTOS
implements true microkernel threads that have only a system scope.
Multisignalling:
- 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.
Cancellation:
- 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.
(QNX Neutrino 7.0.1 or later) Initial state:
- size_t __stacksize
- If __stackaddr isn't NULL, then __stacksize specifies
the size of the thread stack defined in __stackaddr.
If the stack size is less than PTHREAD_STACK_MIN, the call fails with an error of
EINVAL.
If __stackaddr is NULL, then __stacksize specifies
the minimum size of stack to dynamically allocate.
If you set __stacksize to zero, then a system-defined amount is used.
- 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, 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.
- unsigned __guardsize
- The amount of memory to use for the guard area of the thread's stack; for more information, see
pthread_attr_setguardsize()
- unsigned __prealloc
- The amount of the memory to preallocate for a thread's MAP_LAZY stack;
for more information, see
pthread_attr_setstackprealloc().
Signal state
The signal state of the new thread is initialized as follows:
- The signal mask is inherited from the creating thread.
- The set of pending signals is empty.
- The cancel state and type are PTHREAD_CANCEL_ENABLE
and PTHREAD_CANCEL_DEFERRED.
Local storage for private data
Each thread contains a thread local storage area for its private data.
User applications don't need to directly access this area, but
you can get a pointer to it by calling __tls().
The thread local storage is defined by the structure
_thread_local_storage.
Both of these are defined in <sys/storage.h>.
Blocking states
These calls don't block.
Returns:
The thread ID of the newly created thread.
If an error occurs:
- ThreadCreate() returns -1 and sets
errno.
- ThreadCreate_r() returns the negative of a value from the Errors section and
doesn't set errno.
Errors:
- EAGAIN
- All kernel thread objects are in use.
- EFAULT
- A fault occurred when the kernel tried to access the buffers provided.
- EINVAL
- The scheduling policy or priority was invalid, or the stack size is less than PTHREAD_STACK_MIN.
- 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 Neutrino interpretation of PTHREAD_STACK_MIN is enough memory
to run a thread that does nothing:
void nothingthread( void )
{
return;
}