Threads and processes

Updated: October 26, 2022

When building an application (realtime, embedded, graphical, or otherwise), the developer may want several algorithms within the application to execute concurrently. This concurrency is achieved by using the POSIX thread model, which defines a process as containing one or more threads of execution.

A thread can be thought of as the minimum “unit of execution,” the unit of scheduling and execution in the microkernel. A process, on the other hand, can be thought of as a “container” for threads, defining the “address space” within which threads will execute. A process will always contain at least one thread.

Depending on the nature of the application, threads might execute independently with no need to communicate between the algorithms (unlikely), or they may need to be tightly coupled, with high-bandwidth communications and tight synchronization. To assist in this communication and synchronization, the QNX Neutrino RTOS provides a rich variety of IPC and synchronization services.

The following pthread_* (POSIX Threads) library calls don't involve any microkernel thread calls:

The following table lists the POSIX thread calls that have a corresponding microkernel thread call:
Note: The pthread_* calls may have more functionalities implemented in the C library that are not provided by the kernel calls. Unless there are special circumstances, use pthread_* calls instead of kernel calls.
POSIX call Microkernel call Description
pthread_create() ThreadCreate() Create a new thread of execution
pthread_exit() ThreadDestroy() Destroy a thread
pthread_detach() ThreadDetach() Detach a thread so it doesn't need to be joined
pthread_join() ThreadJoin() Join a thread waiting for its exit status
pthread_cancel() ThreadCancel() Cancel a thread at the next cancellation point
N/A ThreadCtl() Change a thread's QNX Neutrino-specific thread characteristics
pthread_mutex_init() SyncTypeCreate() Create a mutex
pthread_mutex_destroy() SyncDestroy() Destroy a mutex
pthread_mutex_lock() SyncMutexLock() Lock a mutex
pthread_mutex_trylock() SyncMutexLock() Conditionally lock a mutex
pthread_mutex_unlock() SyncMutexUnlock() Unlock a mutex
pthread_cond_init() SyncTypeCreate() Create a condition variable
pthread_cond_destroy() SyncDestroy() Destroy a condition variable
pthread_cond_wait() SyncCondvarWait() Wait on a condition variable
pthread_cond_signal() SyncCondvarSignal() Signal a condition variable
pthread_cond_broadcast() SyncCondvarSignal() Broadcast a condition variable
pthread_getschedparam() SchedGet() Get the scheduling parameters and policy of a thread
pthread_setschedparam(), pthread_setschedprio() SchedSet() Set the scheduling parameters and policy of a thread
pthread_sigmask() SignalProcmask() Examine or set a thread's signal mask
pthread_kill() SignalKill() Send a signal to a specific thread

The OS can be configured to provide a mix of threads and processes (as defined by POSIX). Each process is MMU-protected from each other, and each process may contain one or more threads that share the process's address space.

The environment you choose affects not only the concurrency capabilities of the application, but also the IPC and synchronization services the application might make use of.

Note: Even though the common term “IPC” refers to communicating processes, we use it here to describe the communication between threads, whether they're within the same process or separate processes.

For information about processes and threads from the programming point of view, see the Processes and Threads chapter of Getting Started with QNX Neutrino, and the Programming Overview and Processes chapters of the QNX Neutrino Programmer's Guide.