Versions Compared

Key

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

NuttX Tasking

What is an RTOS?

An RTOS as a library

NuttX, as with all RTOSs, is a collection of various features bundled as a library. It does not execute except when either (1) the application calls into the NuttX library code, or (2) an interrupt occurs. There is no meaningful way to represent an architecture that is implemented as a library of user managed functions with a diagram.

You can however, pick any subsystem of an RTOS and represent that in some fashion.

Kernel Threads



Wiki Markup
There are some RTOS functions that are implemented by internal threads \[to be provided].



The Scheduler

Schedulers and Operating Systems

An operating system is a complete environment for developing applications. One important component of an operating system is the scheduler: That logic that controls when tasks or threads execute. Actually, more than that; the scheduler really determines what a task or a thread is! Most tiny operating systems are really not operating “systems” in the sense of providing a complete operating environment. Rather these tiny operating systems consist really only of a scheduler. That is how important the scheduler is.

Task Control Block (TCB)

In NuttX a thread is any controllable sequence of instruction execution that has its own stack. Each task is represented by a data structure called a task control block or TCB. That data structure is defined in the header file include/nuttx/sched.h.

Task Lists

These TCBs are retained in lists. The state of a task is indicated both by the task_state field of the TCB and by a series of task lists. Although it is not always necessary, most of these lists are prioritized so that common list handling logic can be used (only the g_readytorun, the g_pendingtasks, and the g_waitingforsemaphore lists need to be prioritized).

...

(Reference nuttx/sched/sched/sched.h).

State Transition Diagram

The state of a thread can then be easily represented with this simple state transition diagram:



Wiki Markup
\[to be provided]



Scheduling Policies

In order to be a real-time OS, an RTOS must support SCHED_FIFO. That is, strict priority scheduling. The thread with the highest priority runs.... Period. The thread with the highest priority is always associated with the TCB at the head of the g_readytorun list.

NuttX supports one additional real-time scheduling policy: SCHED_RR. The RR stands for round-robin and this is sometimes called round-robin scheduling. In this case, NuttX supports timeslicing: If a task with SCHED_RR scheduling policy is running, then when each timeslice elapses, it will give up the CPU to the next task that is at the same priority. Note: (1) If there is only one task at this priority, SCHED_RR and SCHED_FIFO are the same, and (2) SCHED_FIFO tasks are never pre-empted in this way.

Task IDs

Each task is represented not only by a TCB but also by a numeric task ID. Given a task ID, the RTOS can find the TCB; given a TCB, the RTOS can find the task ID. So they are functionally equivalent. Only the task ID, however, is exposed at the RTOS/application interfaces.

NuttX Tasks

Processes vs. Threads

In larger system OS such as Windows or Linux, you will often hear the name process used to refer to threads managed by the OS. A process is more than a thread as we have been discussing so far. A process is a protected environment that hosts one or more threads. By environment we mean the set of resources set aside by the OS but in the case of the protected environment of the process we are specifically referring its address space.

...

However, NuttX was designed to support the more resource constrained, lower-end, deeply embedded MCUs. Those MCUs seldom have an MMU and, as a consequence, can never support processes as are supported by Windows and Linux. So NuttX does not support processes. NuttX will support an MMU but it will not use the MMU to support processes. NuttX operates only in a flat address space. (NuttX will use the MMU to control the instruction and data caches and to support protected memory regions).

NuttX Tasks and Task Resources

All RTOSs support the notion of a task. A task is the RTOS's moral equivalent of a process. Like a process, a task is a thread with an environment associated with it. This environment is like environment of the process but does not include a private address space. This environment is private and unique to a task. Each task has its own environment

...

In NuttX, a task is created using the interface task_create(). Reference: NuttX User Guide

The Pseudo File System and Device Drivers

A full discussion of the NuttX file system belongs elsewhere. But in order to talk about task resources, we also need to have a little knowledge of the NuttX file system.

...

Now that we have digressed a little to introduce the NuttX file system and device nodes, we can return to our discussion of task resources.

/dev/console and Standard Streams

There are three special cases of I/O: stdin, stdout, and stderr. These are type FILE* and correspond to file descriptors 0, 1, and 2 respectively. When the very first thread is created (called the IDLE thread), the special device node /dev/console is opened. /dev/console provides the stdin, stdout, and stderr for the initial task

Inheritance of the Task Environment and I/O Redirection

When one task creates a new task, that new task inherits the task resources of its parent. This includes all of the environment variables, file descriptors, and sockets (NOTE: This inheritance can be limited by special options in the NuttX configuration).

...

In the THTTPD server to redirect socket I/O to standard I/O for CGI tasks; in the Telnet server so that new tasks inherit the Telnet session.

Tasks vs. Pthreads

Systems like Linux also support POSIX pthreads. In the Linux environment, the process is created with one thread running in it. But by using interfaces like pthread_create(), you can create multiple threads that run and share the same process resources.

...

Note: These task resources are reference counted and will persist as long as a thread in the task group is still active.

Process IDs/task IDs/pthread IDs

The term process ID is standard (usually abbreviated as pid) and used to identify a task in NuttX. So, more technically, this number is a task ID as was described above. Pthreads are also described by a pthread_t ID. In NuttX, the {{pthread_}}t ID is also the same task ID.