diff options
Diffstat (limited to 'c-user/user_extensions.rst')
-rw-r--r-- | c-user/user_extensions.rst | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/c-user/user_extensions.rst b/c-user/user_extensions.rst new file mode 100644 index 0000000..664d70a --- /dev/null +++ b/c-user/user_extensions.rst @@ -0,0 +1,563 @@ +.. comment SPDX-License-Identifier: CC-BY-SA-4.0 + +.. COMMENT: COPYRIGHT (c) 1988-2008. +.. COMMENT: On-Line Applications Research Corporation (OAR). +.. COMMENT: All rights reserved. + +.. _User Extensions Manager: + +User Extensions Manager +####################### + +.. index:: user extensions + +Introduction +============ + +The RTEMS User Extensions Manager allows the application developer to augment +the executive by allowing them to supply extension routines which are invoked +at critical system events. The directives provided by the user extensions +manager are: + +- rtems_extension_create_ - Create an extension set + +- rtems_extension_ident_ - Get ID of an extension set + +- rtems_extension_delete_ - Delete an extension set + +Background +========== + +User extension routines are invoked when the following system events occur: + +- Task creation + +- Task initiation + +- Task reinitiation + +- Task deletion + +- Task context switch + +- Post task context switch + +- Task begin + +- Task exits + +- Fatal error detection + +These extensions are invoked as a function with arguments that are appropriate +to the system event. + +Extension Sets +-------------- +.. index:: extension set + +An extension set is defined as a set of routines which are invoked at each of +the critical system events at which user extension routines are invoked. +Together a set of these routines typically perform a specific functionality +such as performance monitoring or debugger support. RTEMS is informed of the +entry points which constitute an extension set via the following +structure:.. index:: rtems_extensions_table + +.. code-block:: c + + typedef struct { + rtems_task_create_extension thread_create; + rtems_task_start_extension thread_start; + rtems_task_restart_extension thread_restart; + rtems_task_delete_extension thread_delete; + rtems_task_switch_extension thread_switch; + rtems_task_begin_extension thread_begin; + rtems_task_exitted_extension thread_exitted; + rtems_fatal_extension fatal; + } rtems_extensions_table; + +RTEMS allows the user to have multiple extension sets active at the same time. +First, a single static extension set may be defined as the application's User +Extension Table which is included as part of the Configuration Table. This +extension set is active for the entire life of the system and may not be +deleted. This extension set is especially important because it is the only way +the application can provided a FATAL error extension which is invoked if RTEMS +fails during the initialize_executive directive. The static extension set is +optional and may be configured as NULL if no static extension set is required. + +Second, the user can install dynamic extensions using the +``rtems_extension_create`` directive. These extensions are RTEMS objects in +that they have a name, an ID, and can be dynamically created and deleted. In +contrast to the static extension set, these extensions can only be created and +installed after the initialize_executive directive successfully completes +execution. Dynamic extensions are useful for encapsulating the functionality +of an extension set. For example, the application could use extensions to +manage a special coprocessor, do performance monitoring, and to do stack bounds +checking. Each of these extension sets could be written and installed +independently of the others. + +All user extensions are optional and RTEMS places no naming restrictions on the +user. The user extension entry points are copied into an internal RTEMS +structure. This means the user does not need to keep the table after creating +it, and changing the handler entry points dynamically in a table once created +has no effect. Creating a table local to a function can save space in space +limited applications. + +Extension switches do not effect the context switch overhead if no switch +handler is installed. + +TCB Extension Area +------------------ +.. index:: TCB extension area + +RTEMS provides for a pointer to a user-defined data area for each extension set +to be linked to each task's control block. This set of pointers is an +extension of the TCB and can be used to store additional data required by the +user's extension functions. + +The TCB extension is an array of pointers in the TCB. The index into the table +can be obtained from the extension id returned when the extension is +created: + +.. index:: rtems extensions table index + +.. code-block:: c + + index = rtems_object_id_get_index(extension_id); + +The number of pointers in the area is the same as the number of user extension +sets configured. This allows an application to augment the TCB with +user-defined information. For example, an application could implement task +profiling by storing timing statistics in the TCB's extended memory area. When +a task context switch is being executed, the ``TASK_SWITCH`` extension could +read a real-time clock to calculate how long the task being swapped out has run +as well as timestamp the starting time for the task being swapped in. + +If used, the extended memory area for the TCB should be allocated and the TCB +extension pointer should be set at the time the task is created or started by +either the ``TASK_CREATE`` or ``TASK_START`` extension. The application is +responsible for managing this extended memory area for the TCBs. The memory +may be reinitialized by the ``TASK_RESTART`` extension and should be +deallocated by the ``TASK_DELETE`` extension when the task is deleted. Since +the TCB extension buffers would most likely be of a fixed size, the RTEMS +partition manager could be used to manage the application's extended memory +area. The application could create a partition of fixed size TCB extension +buffers and use the partition manager's allocation and deallocation directives +to obtain and release the extension buffers. + +Extensions +---------- + +The sections that follow will contain a description of each extension. Each +section will contain a prototype of a function with the appropriate calling +sequence for the corresponding extension. The names given for the C function +and its arguments are all defined by the user. The names used in the examples +were arbitrarily chosen and impose no naming conventions on the user. + +TASK_CREATE Extension +~~~~~~~~~~~~~~~~~~~~~ + +The TASK_CREATE extension directly corresponds to the ``rtems_task_create`` +directive. If this extension is defined in any static or dynamic extension set +and a task is being created, then the extension routine will automatically be +invoked by RTEMS. The extension should have a prototype similar to the +following: + +.. index:: rtems_task_create_extension +.. index:: rtems_extension + +.. code-block:: c + + bool user_task_create( + rtems_tcb *current_task, + rtems_tcb *new_task + ); + +where ``current_task`` can be used to access the TCB for the currently +executing task, and new_task can be used to access the TCB for the new task +being created. This extension is invoked from the ``rtems_task_create`` +directive after ``new_task`` has been completely initialized, but before it is +placed on a ready TCB chain. + +The user extension is expected to return the boolean value ``true`` if it +successfully executed and ``false`` otherwise. A task create user extension +will frequently attempt to allocate resources. If this allocation fails, then +the extension should return ``false`` and the entire task create operation will +fail. + +TASK_START Extension +~~~~~~~~~~~~~~~~~~~~ + +The ``TASK_START`` extension directly corresponds to the task_start directive. +If this extension is defined in any static or dynamic extension set and a task +is being started, then the extension routine will automatically be invoked by +RTEMS. The extension should have a prototype similar to the following: + +.. index:: rtems_task_start_extension + +.. code-block:: c + + void user_task_start( + rtems_tcb *current_task, + rtems_tcb *started_task + ); + +where current_task can be used to access the TCB for the currently executing +task, and started_task can be used to access the TCB for the dormant task being +started. This extension is invoked from the task_start directive after +started_task has been made ready to start execution, but before it is placed on +a ready TCB chain. + +TASK_RESTART Extension +~~~~~~~~~~~~~~~~~~~~~~ + +The ``TASK_RESTART`` extension directly corresponds to the task_restart +directive. If this extension is defined in any static or dynamic extension set +and a task is being restarted, then the extension should have a prototype +similar to the following: + +.. index:: rtems_task_restart_extension + +.. code-block:: c + + void user_task_restart( + rtems_tcb *current_task, + rtems_tcb *restarted_task + ); + +where current_task can be used to access the TCB for the currently executing +task, and restarted_task can be used to access the TCB for the task being +restarted. This extension is invoked from the task_restart directive after +restarted_task has been made ready to start execution, but before it is placed +on a ready TCB chain. + +TASK_DELETE Extension +~~~~~~~~~~~~~~~~~~~~~ + +The ``TASK_DELETE`` extension is associated with the task_delete directive. If +this extension is defined in any static or dynamic extension set and a task is +being deleted, then the extension routine will automatically be invoked by +RTEMS. The extension should have a prototype similar to the +following: + +.. index:: rtems_task_delete_extension + +.. code-block:: c + + void user_task_delete( + rtems_tcb *current_task, + rtems_tcb *deleted_task + ); + +where current_task can be used to access the TCB for the currently executing +task, and deleted_task can be used to access the TCB for the task being +deleted. This extension is invoked from the task_delete directive after the TCB +has been removed from a ready TCB chain, but before all its resources including +the TCB have been returned to their respective free pools. This extension +should not call any RTEMS directives if a task is deleting itself (current_task +is equal to deleted_task). + +TASK_SWITCH Extension +~~~~~~~~~~~~~~~~~~~~~ + +The ``TASK_SWITCH`` extension corresponds to a task context switch. If this +extension is defined in any static or dynamic extension set and a task context +switch is in progress, then the extension routine will automatically be invoked +by RTEMS. The extension should have a prototype similar to the following: + +.. index:: rtems_task_switch_extension + +.. code-block:: c + + void user_task_switch( + rtems_tcb *current_task, + rtems_tcb *heir_task + ); + +where current_task can be used to access the TCB for the task that is being +swapped out, and heir_task can be used to access the TCB for the task being +swapped in. This extension is invoked from RTEMS' dispatcher routine after the +current_task context has been saved, but before the heir_task context has been +restored. This extension should not call any RTEMS directives. + +TASK_BEGIN Extension +~~~~~~~~~~~~~~~~~~~~ + +The ``TASK_BEGIN`` extension is invoked when a task begins execution. It is +invoked immediately before the body of the starting procedure and executes in +the context in the task. This user extension have a prototype similar to the +following: + +.. index:: rtems_task_begin_extension + +.. code-block:: c + + void user_task_begin( + rtems_tcb *current_task + ); + +where current_task can be used to access the TCB for the currently executing +task which has begun. The distinction between the ``TASK_BEGIN`` and +TASK_START extension is that the ``TASK_BEGIN`` extension is executed in the +context of the actual task while the TASK_START extension is executed in the +context of the task performing the task_start directive. For most extensions, +this is not a critical distinction. + +TASK_EXITTED Extension +~~~~~~~~~~~~~~~~~~~~~~ + +The ``TASK_EXITTED`` extension is invoked when a task exits the body of the +starting procedure by either an implicit or explicit return statement. This +user extension have a prototype similar to the following: + +.. index:: rtems_task_exitted_extension + +.. code-block:: c + + void user_task_exitted( + rtems_tcb *current_task + ); + +where current_task can be used to access the TCB for the currently executing +task which has just exitted. + +Although exiting of task is often considered to be a fatal error, this +extension allows recovery by either restarting or deleting the exiting task. +If the user does not wish to recover, then a fatal error may be reported. If +the user does not provide a ``TASK_EXITTED`` extension or the provided handler +returns control to RTEMS, then the RTEMS default handler will be used. This +default handler invokes the directive fatal_error_occurred with the +``RTEMS_TASK_EXITTED`` directive status. + +FATAL Error Extension +~~~~~~~~~~~~~~~~~~~~~ + +The ``FATAL`` error extension is associated with the fatal_error_occurred +directive. If this extension is defined in any static or dynamic extension set +and the fatal_error_occurred directive has been invoked, then this extension +will be called. This extension should have a prototype similar to the +following: + +.. index:: rtems_fatal_extension + +.. code-block:: c + + void user_fatal_error( + Internal_errors_Source the_source, + bool is_internal, + uint32_t the_error + ); + +where the_error is the error code passed to the fatal_error_occurred +directive. This extension is invoked from the fatal_error_occurred directive. + +If defined, the user's ``FATAL`` error extension is invoked before RTEMS' +default fatal error routine is invoked and the processor is stopped. For +example, this extension could be used to pass control to a debugger when a +fatal error occurs. This extension should not call any RTEMS directives. + +Order of Invocation +------------------- + +When one of the critical system events occur, the user extensions are invoked +in either "forward" or "reverse" order. Forward order indicates that the +static extension set is invoked followed by the dynamic extension sets in the +order in which they were created. Reverse order means that the dynamic +extension sets are invoked in the opposite of the order in which they were +created followed by the static extension set. By invoking the extension sets +in this order, extensions can be built upon one another. At the following +system events, the extensions are invoked in forward order: + +#. Task creation + +#. Task initiation + +#. Task reinitiation + +#. Task deletion + +#. Task context switch + +#. Post task context switch + +#. Task begins to execute + +At the following system events, the extensions are invoked in reverse order: + +#. Task deletion + +#. Fatal error detection + +At these system events, the extensions are invoked in reverse order to insure +that if an extension set is built upon another, the more complicated extension +is invoked before the extension set it is built upon. For example, by invoking +the static extension set last it is known that the "system" fatal error +extension will be the last fatal error extension executed. Another example is +use of the task delete extension by the Standard C Library. Extension sets +which are installed after the Standard C Library will operate correctly even if +they utilize the C Library because the C Library's ``TASK_DELETE`` extension is +invoked after that of the other extensions. + +Operations +========== + +Creating an Extension Set +------------------------- + +The ``rtems_extension_create`` directive creates and installs an extension set +by allocating a Extension Set Control Block (ESCB), assigning the extension set +a user-specified name, and assigning it an extension set ID. Newly created +extension sets are immediately installed and are invoked upon the next system +even supporting an extension. + +Obtaining Extension Set IDs +--------------------------- + +When an extension set is created, RTEMS generates a unique extension set ID and +assigns it to the created extension set until it is deleted. The extension ID +may be obtained by either of two methods. First, as the result of an +invocation of the ``rtems_extension_create`` directive, the extension set ID is +stored in a user provided location. Second, the extension set ID may be +obtained later using the ``rtems_extension_ident`` directive. The extension +set ID is used by other directives to manipulate this extension set. + +Deleting an Extension Set +------------------------- + +The ``rtems_extension_delete`` directive is used to delete an extension set. +The extension set's control block is returned to the ESCB free list when it is +deleted. An extension set can be deleted by a task other than the task which +created the extension set. Any subsequent references to the extension's name +and ID are invalid. + +Directives +========== + +This section details the user extension manager's directives. A subsection is +dedicated to each of this manager's directives and describes the calling +sequence, related constants, usage, and status codes. + +.. _rtems_extension_create: + +EXTENSION_CREATE - Create a extension set +----------------------------------------- +.. index:: create an extension set + +**CALLING SEQUENCE:** + +.. index:: rtems_extension_create + +.. code-block:: c + + rtems_status_code rtems_extension_create( + rtems_name name, + rtems_extensions_table *table, + rtems_id *id + ); + +**DIRECTIVE STATUS CODES:** + +.. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - extension set created successfully + * - ``RTEMS_INVALID_NAME`` + - invalid extension set name + * - ``RTEMS_TOO_MANY`` + - too many extension sets created + +**DESCRIPTION:** + +This directive creates a extension set. The assigned extension set id is +returned in id. This id is used to access the extension set with other user +extension manager directives. For control and maintenance of the extension +set, RTEMS allocates an ESCB from the local ESCB free pool and initializes it. + +**NOTES:** + +This directive will not cause the calling task to be +preempted. + +.. _rtems_extension_ident: + +EXTENSION_IDENT - Get ID of a extension set +------------------------------------------- +.. index:: get ID of an extension set +.. index:: obtain ID of an extension set + +**CALLING SEQUENCE:** + +.. index:: rtems_extension_ident + +.. code-block:: c + + rtems_status_code rtems_extension_ident( + rtems_name name, + rtems_id *id + ); + +**DIRECTIVE STATUS CODES:** + +.. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - extension set identified successfully + * - ``RTEMS_INVALID_NAME`` + - extension set name not found + +**DESCRIPTION:** + +This directive obtains the extension set id associated with the extension set +name to be acquired. If the extension set name is not unique, then the +extension set id will match one of the extension sets with that name. However, +this extension set id is not guaranteed to correspond to the desired extension +set. The extension set id is used to access this extension set in other +extension set related directives. + +**NOTES:** + +This directive will not cause the running task to be preempted. + +.. _rtems_extension_delete: + +EXTENSION_DELETE - Delete a extension set +----------------------------------------- +.. index:: delete an extension set + +**CALLING SEQUENCE:** + +.. index:: rtems_extension_delete + +.. code-block:: c + + rtems_status_code rtems_extension_delete( + rtems_id id + ); + +**DIRECTIVE STATUS CODES:** + +.. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - extension set deleted successfully + * - ``RTEMS_INVALID_ID`` + - invalid extension set id + +**DESCRIPTION:** + +This directive deletes the extension set specified by ``id``. If the extension +set is running, it is automatically canceled. The ESCB for the deleted +extension set is reclaimed by RTEMS. + +**NOTES:** + +This directive will not cause the running task to be preempted. + +A extension set can be deleted by a task other than the task which created the +extension set. + +**NOTES:** + +This directive will not cause the running task to be preempted. |