7.3. Operations#

7.3.1. Creating Tasks#

The rtems_task_create directive creates a task by allocating a task control block, assigning the task a user-specified name, allocating it a stack and floating point context area, setting a user-specified initial priority, setting a user-specified initial mode, and assigning it a task ID. Newly created tasks are initially placed in the dormant state. All RTEMS tasks execute in the most privileged mode of the processor.

7.3.2. Obtaining Task IDs#

When a task is created, RTEMS generates a unique task ID and assigns it to the created task until it is deleted. The task ID may be obtained by either of two methods. First, as the result of an invocation of the rtems_task_create directive, the task ID is stored in a user provided location. Second, the task ID may be obtained later using the rtems_task_ident directive. The task ID is used by other directives to manipulate this task.

7.3.3. Starting and Restarting Tasks#

The rtems_task_start directive is used to place a dormant task in the ready state. This enables the task to compete, based on its current priority, for the processor and other system resources. Any actions, such as suspension or change of priority, performed on a task prior to starting it are nullified when the task is started.

With the rtems_task_start directive the user specifies the task’s starting address and argument. The argument is used to communicate some startup information to the task. As part of this directive, RTEMS initializes the task’s stack based upon the task’s initial execution mode and start address. The starting argument is passed to the task in accordance with the target processor’s calling convention.

The rtems_task_restart directive restarts a task at its initial starting address with its original priority and execution mode, but with a possibly different argument. The new argument may be used to distinguish between the original invocation of the task and subsequent invocations. The task’s stack and control block are modified to reflect their original creation values. Although references to resources that have been requested are cleared, resources allocated by the task are NOT automatically returned to RTEMS. A task cannot be restarted unless it has previously been started (i.e. dormant tasks cannot be restarted). All restarted tasks are placed in the ready state.

7.3.4. Suspending and Resuming Tasks#

The rtems_task_suspend directive is used to place either the caller or another task into a suspended state. The task remains suspended until a rtems_task_resume directive is issued. This implies that a task may be suspended as well as blocked waiting either to acquire a resource or for the expiration of a timer.

The rtems_task_resume directive is used to remove another task from the suspended state. If the task is not also blocked, resuming it will place it in the ready state, allowing it to once again compete for the processor and resources. If the task was blocked as well as suspended, this directive clears the suspension and leaves the task in the blocked state.

Suspending a task which is already suspended or resuming a task which is not suspended is considered an error. The rtems_task_is_suspended can be used to determine if a task is currently suspended.

7.3.5. Delaying the Currently Executing Task#

The rtems_task_wake_after directive creates a sleep timer which allows a task to go to sleep for a specified count of clock ticks. The task is blocked until the count of clock ticks has elapsed, at which time the task is unblocked. A task calling the rtems_task_wake_after directive with a delay of RTEMS_YIELD_PROCESSOR ticks will yield the processor to any other ready task of equal or greater priority and remain ready to execute.

The rtems_task_wake_when directive creates a sleep timer which allows a task to go to sleep until a specified date and time. The calling task is blocked until the specified date and time has occurred, at which time the task is unblocked.

7.3.6. Changing Task Priority#

The rtems_task_set_priority directive is used to obtain or change the current priority of either the calling task or another task. If the new priority requested is RTEMS_CURRENT_PRIORITY or the task’s actual priority, then the current priority will be returned and the task’s priority will remain unchanged. If the task’s priority is altered, then the task will be scheduled according to its new priority.

The rtems_task_restart directive resets the priority of a task to its original value.

7.3.7. Changing Task Mode#

The rtems_task_mode directive is used to obtain or change the current execution mode of the calling task. A task’s execution mode is used to enable preemption, timeslicing, ASR processing, and to set the task’s interrupt level.

The rtems_task_restart directive resets the mode of a task to its original value.

7.3.8. Task Deletion#

RTEMS provides the rtems_task_delete directive to allow a task to delete itself or any other task. This directive removes all RTEMS references to the task, frees the task’s control block, removes it from resource wait queues, and deallocates its stack as well as the optional floating point context. The task’s name and ID become inactive at this time, and any subsequent references to either of them is invalid. In fact, RTEMS may reuse the task ID for another task which is created later in the application. A specialization of rtems_task_delete is rtems_task_exit which deletes the calling task.

Unexpired delay timers (i.e. those used by rtems_task_wake_after and rtems_task_wake_when) and timeout timers associated with the task are automatically deleted, however, other resources dynamically allocated by the task are NOT automatically returned to RTEMS. Therefore, before a task is deleted, all of its dynamically allocated resources should be deallocated by the user. This may be accomplished by instructing the task to delete itself rather than directly deleting the task. Other tasks may instruct a task to delete itself by sending a “delete self” message, event, or signal, or by restarting the task with special arguments which instruct the task to delete itself.

7.3.9. Setting Affinity to a Single Processor#

On some embedded applications targeting SMP systems, it may be beneficial to lock individual tasks to specific processors. In this way, one can designate a processor for I/O tasks, another for computation, etc.. The following illustrates the code sequence necessary to assign a task an affinity for processor with index processor_index.

#include <rtems.h>
#include <assert.h>

void pin_to_processor(rtems_id task_id, int processor_index)
{
    rtems_status_code sc;
    cpu_set_t         cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(processor_index, &cpuset);
    sc = rtems_task_set_affinity(task_id, sizeof(cpuset), &cpuset);
    assert(sc == RTEMS_SUCCESSFUL);
}

It is important to note that the cpuset is not validated until the rtems_task_set_affinity call is made. At that point, it is validated against the current system configuration.

7.3.10. Transition Advice for Removed Notepads#

Task notepads and the associated directives TASK_GET_NOTE - Get task notepad entry and TASK_SET_NOTE - Set task notepad entry were removed in RTEMS 5.1. These were never thread-safe to access and subject to conflicting use of the notepad index by libraries which were designed independently.

It is recommended that applications be modified to use services which are thread safe and not subject to issues with multiple applications conflicting over the key (e.g. notepad index) selection. For most applications, POSIX Keys should be used. These are available in all RTEMS build configurations. It is also possible that thread-local storage (TLS) is an option for some use cases.

7.3.11. Transition Advice for Removed Task Variables#

Task notepads and the associated directives TASK_VARIABLE_ADD - Associate per task variable, TASK_VARIABLE_GET - Obtain value of a per task variable and TASK_VARIABLE_DELETE - Remove per task variable were removed in RTEMS 5.1. Task variables must be replaced by POSIX Keys or thread-local storage (TLS). POSIX Keys are available in all configurations and support value destructors. For the TLS support consult the RTEMS CPU Architecture Supplement.