Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Tasks vs. Threads FAQ

Q: What is the difference between a thread and a task in Nuttx?

A: Tasks and threads in NuttX try to emulate processes and threads in the standard Unix environment: I think of a process as a "container" of resources that are shared by the threads that execute within the context of the process.

...

NuttX tasks and threads are discussed in much more detail in the NuttX Tasking article.

Q: When would I want to use a task? When would I want to use a thread?

A: Threads are very light weight; the memory cost for the thread is the cost of the task control block plus the size of the stack. That is perhaps 0.8-2KB, depending mostly on the configured stack size.

...

Normally, each major block of functionality is implemented with a separate task. With each of those _task group_s, however, you may also want several helper threads to implement asynchronous and concurrent behaviors.

Q: How do signals work in a task group with many pthreads?

A: The behavior of signals in the multi-thread task group is complex. NuttX emulates a process model with task group_s and follows the POSIX rules for signalling behavior. Normally when you signal the _task group you would signal using the task ID of the main task that created the group (in practice, a different task should not know the IDs of the internal threads created within the task group); that ID is remembered by the task group (even if the main task thread exits).

...

You can control which thread receives the signal by controlling the signal mask.
You can, for example, create a single thread whose sole purpose it is to catch a particular signal and respond to it: Simply block the signal in the main task; then the signal will be blocked in all of the pthreads in the group too. In the one "signal processing" pthread, enable the blocked signal. This thread will then be only thread that will receive the signal.

Q: How do atexit() and on_exit() work with task groups?

A: atexit() and on_exit() callbacks must be registered using the task ID of the main task (which makes sense since pthreads do not have task IDs of type pid_t).
The callback is not necessarily made when the task thread exits; the atexit() and on_exit() callbacks will be executed when the task group terminates, that is, when the final thread of the task group terminates.

Q: How does waitpid() work with task groups?

A: In a single-thread task group, waitpid() will wait until the single, main thread of the task group exits (i.e., the one created by task_start()). This is the intuitive behavior. But the behavior may be less intuitive for multi-threaded task groups. In a multi-threaded task group waitpid() will wait until every thread in the task group exits. Nothing special happens when the main thread of the task group exits.

Q: What are privileged threads? How are threads handled differently when NuttX is built as a Kernel

NuttX supports a build mode where it is built as a monolithic kernel. This mode is selected with the configuration option CONFIG_BUILD_PROTECTED=y and is currently only supported for a few architectures. When used this way, NuttX is built as a separate kernel mode "blob" and the applications are built as another separate user mode "blob". The kernel runs in kernel mode and the applications run in user mode (with the MPU restricting user mode accesses). Access to the kernel from the user blob is only via system calls (SVCalls).

...