mirror of
https://git.rtems.org/rtems-docs/
synced 2025-05-31 08:21:23 +08:00
593 lines
19 KiB
ReStructuredText
593 lines
19 KiB
ReStructuredText
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:: 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:: 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:: 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:: 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:: 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:: 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:: 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:: 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:: 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:: 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.
|
|
|
|
EXTENSION_CREATE - Create a extension set
|
|
-----------------------------------------
|
|
.. index:: create an extension set
|
|
|
|
**CALLING SEQUENCE:**
|
|
|
|
.. index:: rtems_extension_create
|
|
|
|
.. code:: c
|
|
|
|
rtems_status_code rtems_extension_create(
|
|
rtems_name name,
|
|
rtems_extensions_table \*table,
|
|
rtems_id \*id
|
|
);
|
|
|
|
**DIRECTIVE STATUS CODES:**
|
|
|
|
``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.
|
|
|
|
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:: c
|
|
|
|
rtems_status_code rtems_extension_ident(
|
|
rtems_name name,
|
|
rtems_id \*id
|
|
);
|
|
|
|
**DIRECTIVE STATUS CODES:**
|
|
|
|
``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.
|
|
|
|
EXTENSION_DELETE - Delete a extension set
|
|
-----------------------------------------
|
|
.. index:: delete an extension set
|
|
|
|
**CALLING SEQUENCE:**
|
|
|
|
.. index:: rtems_extension_delete
|
|
|
|
.. code:: c
|
|
|
|
rtems_status_code rtems_extension_delete(
|
|
rtems_id id
|
|
);
|
|
|
|
**DIRECTIVE STATUS CODES:**
|
|
|
|
``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.
|
|
|
|
.. COMMENT: COPYRIGHT (c) 1988-2015.
|
|
|
|
.. COMMENT: On-Line Applications Research Corporation (OAR).
|
|
|
|
.. COMMENT: All rights reserved.
|
|
|
|
.. COMMENT: TODO:
|
|
|
|
.. COMMENT: + Ensure all macros are documented.
|
|
|
|
.. COMMENT: + Verify which structures may actually be defined by a user
|
|
|
|
.. COMMENT: + Add Go configuration.
|
|
|
|
.. COMMENT: Questions:
|
|
|
|
.. COMMENT: + Should there be examples of defining your own
|
|
|
|
.. COMMENT: Device Driver Table, Init task table, etc.?
|
|
|
|
|