Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplClassicUserExt
0007  *
0008  * @brief This header file defines the User Extensions Manager API.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2009, 2021 embedded brains GmbH & Co. KG
0013  * Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR)
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 /*
0038  * This file is part of the RTEMS quality process and was automatically
0039  * generated.  If you find something that needs to be fixed or
0040  * worded better please post a report or patch to an RTEMS mailing list
0041  * or raise a bug report:
0042  *
0043  * https://www.rtems.org/bugs.html
0044  *
0045  * For information on updating and regenerating please refer to the How-To
0046  * section in the Software Requirements Engineering chapter of the
0047  * RTEMS Software Engineering manual.  The manual is provided as a part of
0048  * a release.  For development sources please refer to the online
0049  * documentation at:
0050  *
0051  * https://docs.rtems.org
0052  */
0053 
0054 /* Generated from spec:/rtems/userext/if/header */
0055 
0056 #ifndef _RTEMS_EXTENSION_H
0057 #define _RTEMS_EXTENSION_H
0058 
0059 #include <rtems/rtems/status.h>
0060 #include <rtems/rtems/types.h>
0061 #include <rtems/score/interr.h>
0062 #include <rtems/score/userextdata.h>
0063 
0064 #ifdef __cplusplus
0065 extern "C" {
0066 #endif
0067 
0068 /* Generated from spec:/rtems/userext/if/group */
0069 
0070 /**
0071  * @defgroup RTEMSAPIClassicUserExt User Extensions Manager
0072  *
0073  * @ingroup RTEMSAPIClassic
0074  *
0075  * @brief The User Extensions Manager allows the application developer to
0076  *   augment the executive by allowing them to supply extension routines which
0077  *   are invoked at critical system events.
0078  */
0079 
0080 /* Generated from spec:/rtems/userext/if/delete */
0081 
0082 /**
0083  * @ingroup RTEMSAPIClassicUserExt
0084  *
0085  * @brief Deletes the extension set.
0086  *
0087  * @param id is the extension set identifier.
0088  *
0089  * This directive deletes the extension set specified by ``id``.
0090  *
0091  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0092  *
0093  * @retval ::RTEMS_INVALID_ID There was no extension set associated with the
0094  *   identifier specified by ``id``.
0095  *
0096  * @par Notes
0097  * The ESCB for the deleted extension set is reclaimed by RTEMS.
0098  *
0099  * @par Constraints
0100  * @parblock
0101  * The following constraints apply to this directive:
0102  *
0103  * * The directive may be called from within device driver initialization
0104  *   context.
0105  *
0106  * * The directive may be called from within task context.
0107  *
0108  * * The directive may obtain and release the object allocator mutex.  This may
0109  *   cause the calling task to be preempted.
0110  *
0111  * * The calling task does not have to be the task that created the object.
0112  *   Any local task that knows the object identifier can delete the object.
0113  * @endparblock
0114  */
0115 rtems_status_code rtems_extension_delete( rtems_id id );
0116 
0117 /* Generated from spec:/rtems/userext/if/fatal */
0118 
0119 /**
0120  * @ingroup RTEMSAPIClassicUserExt
0121  *
0122  * @brief Fatal extensions are invoked when the system should terminate.
0123  *
0124  * @param source is the system termination source.  The source indicates the
0125  *   component which caused the system termination request, see
0126  *   ::rtems_fatal_source.  The system termination code may provide additional
0127  *   information related to the system termination request.
0128  *
0129  * @param always_set_to_false is a value equal to false.
0130  *
0131  * @param code is the system termination code.  This value must be interpreted
0132  *   with respect to the source.
0133  *
0134  * @par Notes
0135  * @parblock
0136  * The fatal extensions are invoked in extension forward order and with
0137  * maskable interrupts disabled.
0138  *
0139  * The fatal extension should be extremely careful with respect to the RTEMS
0140  * directives it calls.  Depending on the system termination source, the system
0141  * may be in an undefined and corrupt state.
0142  *
0143  * It is recommended to register fatal extensions through initial extension
0144  * sets, see @ref CONFIGURE_INITIAL_EXTENSIONS.
0145  * @endparblock
0146  */
0147 typedef User_extensions_fatal_extension rtems_fatal_extension;
0148 
0149 /* Generated from spec:/rtems/userext/if/fatal-code */
0150 
0151 /**
0152  * @ingroup RTEMSAPIClassicUserExt
0153  *
0154  * @brief This integer type represents system termination codes.
0155  *
0156  * This integer type is large enough to store a 32-bit integer or a pointer.
0157  *
0158  * @par Notes
0159  * The interpretation of a system termination code depends on the system
0160  * termination source, see ::rtems_fatal_source.
0161  */
0162 typedef Internal_errors_t rtems_fatal_code;
0163 
0164 /* Generated from spec:/rtems/userext/if/fatal-source */
0165 
0166 /**
0167  * @ingroup RTEMSAPIClassicUserExt
0168  *
0169  * @brief This enumeration represents system termination sources.
0170  *
0171  * @par Notes
0172  * The system termination code may provide additional information depending on
0173  * the system termination source, see ::rtems_fatal_code.
0174  */
0175 typedef Internal_errors_Source rtems_fatal_source;
0176 
0177 /* Generated from spec:/rtems/userext/if/ident */
0178 
0179 /**
0180  * @ingroup RTEMSAPIClassicUserExt
0181  *
0182  * @brief Identifies an extension set by the object name.
0183  *
0184  * @param name is the object name to look up.
0185  *
0186  * @param[out] id is the pointer to an ::rtems_id object.  When the directive
0187  *   call is successful, the object identifier of an object with the specified
0188  *   name will be stored in this object.
0189  *
0190  * This directive obtains an extension set identifier associated with the
0191  * extension set name specified in ``name``.
0192  *
0193  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0194  *
0195  * @retval ::RTEMS_INVALID_ADDRESS The ``id`` parameter was NULL.
0196  *
0197  * @retval ::RTEMS_INVALID_NAME The ``name`` parameter was 0.
0198  *
0199  * @retval ::RTEMS_INVALID_NAME There was no object with the specified name on
0200  *   the local node.
0201  *
0202  * @par Notes
0203  * @parblock
0204  * If the extension set name is not unique, then the extension set identifier
0205  * will match the first extension set with that name in the search order.
0206  * However, this extension set identifier is not guaranteed to correspond to
0207  * the desired extension set.
0208  *
0209  * The objects are searched from lowest to the highest index.  Only the local
0210  * node is searched.
0211  *
0212  * The extension set identifier is used with other extension related directives
0213  * to access the extension set.
0214  * @endparblock
0215  *
0216  * @par Constraints
0217  * @parblock
0218  * The following constraints apply to this directive:
0219  *
0220  * * The directive may be called from within device driver initialization
0221  *   context.
0222  *
0223  * * The directive will not cause the calling task to be preempted.
0224  * @endparblock
0225  */
0226 rtems_status_code rtems_extension_ident( rtems_name name, rtems_id *id );
0227 
0228 /* Generated from spec:/rtems/userext/if/table */
0229 
0230 /**
0231  * @ingroup RTEMSAPIClassicUserExt
0232  *
0233  * @brief The extensions table contains a set of extensions which may be
0234  *   registered in the system through the @ref CONFIGURE_INITIAL_EXTENSIONS
0235  *   application configuration option or the rtems_extension_create()
0236  *   directive.
0237  */
0238 typedef User_extensions_Table rtems_extensions_table;
0239 
0240 /* Generated from spec:/rtems/userext/if/create */
0241 
0242 /**
0243  * @ingroup RTEMSAPIClassicUserExt
0244  *
0245  * @brief Creates an extension set.
0246  *
0247  * @param name is the object name of the extension set.
0248  *
0249  * @param extension_table is the table with the extensions to be used by the
0250  *   extension set.
0251  *
0252  * @param[out] id is the pointer to an ::rtems_id object.  When the directive
0253  *   call is successful, the identifier of the created extension set will be
0254  *   stored in this object.
0255  *
0256  * This directive creates an extension set which resides on the local node.
0257  * The extension set has the user-defined object name specified in ``name``.
0258  * The assigned object identifier is returned in ``id``.  This identifier is
0259  * used to access the extension set with other extension set related
0260  * directives.
0261  *
0262  * The extension set is initialized using the extension table specified in
0263  * ``extension_table``.
0264  *
0265  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0266  *
0267  * @retval ::RTEMS_INVALID_NAME The ``name`` parameter was invalid.
0268  *
0269  * @retval ::RTEMS_INVALID_ADDRESS The ``extension_table`` parameter was NULL.
0270  *
0271  * @retval ::RTEMS_INVALID_ADDRESS The ``id`` parameter was NULL.
0272  *
0273  * @retval ::RTEMS_TOO_MANY There was no inactive object available to create an
0274  *   extension set.  The number of extension sets available to the application
0275  *   is configured through the @ref CONFIGURE_MAXIMUM_USER_EXTENSIONS
0276  *   application configuration option.
0277  *
0278  * @par Notes
0279  * @parblock
0280  * The user-provided extension table is not used after the return of the
0281  * directive.
0282  *
0283  * Each extension of the extension table is optional and may be NULL.  All
0284  * extensions except the task switch extension of the extension table are
0285  * atomically and immediately installed.  A task switch extension is separately
0286  * installed after the other extensions.  The extensions of the extension table
0287  * are invoked upon the next system event supporting an extension.
0288  *
0289  * An alternative to dynamically created extension sets are initial extensions,
0290  * see @ref CONFIGURE_INITIAL_EXTENSIONS.  Initial extensions are recommended
0291  * for extension sets which provide a fatal error extension.
0292  *
0293  * For control and maintenance of the extension set, RTEMS allocates a ESCB
0294  * from the local ESCB free pool and initializes it.
0295  * @endparblock
0296  *
0297  * @par Constraints
0298  * @parblock
0299  * The following constraints apply to this directive:
0300  *
0301  * * The directive may be called from within device driver initialization
0302  *   context.
0303  *
0304  * * The directive may be called from within task context.
0305  *
0306  * * The directive may obtain and release the object allocator mutex.  This may
0307  *   cause the calling task to be preempted.
0308  *
0309  * * The number of extension sets available to the application is configured
0310  *   through the @ref CONFIGURE_MAXIMUM_USER_EXTENSIONS application
0311  *   configuration option.
0312  * @endparblock
0313  */
0314 rtems_status_code rtems_extension_create(
0315   rtems_name                    name,
0316   const rtems_extensions_table *extension_table,
0317   rtems_id                     *id
0318 );
0319 
0320 /* Generated from spec:/rtems/userext/if/task-begin */
0321 
0322 /**
0323  * @ingroup RTEMSAPIClassicUserExt
0324  *
0325  * @brief Task begin extensions are invoked when a task begins execution.
0326  *
0327  * @param executing is the TCB of the executing thread.
0328  *
0329  * @par Notes
0330  * @parblock
0331  * The task begin extensions are invoked in extension forward order.
0332  *
0333  * Task begin extensions are invoked with thread dispatching enabled.  This
0334  * allows the use of dynamic memory allocation, creation of POSIX keys, and use
0335  * of C++ thread-local storage.  Blocking synchronization primitives are
0336  * allowed also.
0337  *
0338  * The task begin extensions are invoked before the global construction.
0339  *
0340  * The task begin extensions may be called as a result of a task restart
0341  * through rtems_task_restart().
0342  * @endparblock
0343  *
0344  * @par Constraints
0345  * @parblock
0346  * The following constraints apply to functions of this type:
0347  *
0348  * * Thread dispatching is enabled.
0349  *
0350  * * The executing thread is not the owner of the object allocator mutex.
0351  * @endparblock
0352  */
0353 typedef User_extensions_thread_begin_extension rtems_task_begin_extension;
0354 
0355 /* Generated from spec:/rtems/userext/if/task-create */
0356 
0357 /**
0358  * @ingroup RTEMSAPIClassicUserExt
0359  *
0360  * @brief Task create extensions are invoked when a task is created.
0361  *
0362  * @param executing is the TCB of the executing thread.  When the idle thread
0363  *   is created, the executing thread is equal to NULL.
0364  *
0365  * @param created is the TCB of the created thread.
0366  *
0367  * @return Returns true, if the task create extension was successful, otherwise
0368  *   false.
0369  *
0370  * @par Notes
0371  * @parblock
0372  * The task create extensions are invoked in extension forward order.
0373  *
0374  * The task create extensions are invoked after a new task has been completely
0375  * initialized, but before it is started.
0376  *
0377  * While normal tasks are created, the executing thread is the owner of the
0378  * object allocator mutex.  The object allocator mutex allows nesting, so the
0379  * normal memory allocation routines can be used allocate memory for the
0380  * created thread.
0381  *
0382  * If the task create extension returns false, then the task create operation
0383  * stops immediately and the entire task create operation will fail.  In this
0384  * case, all task delete extensions are invoked, see
0385  * ::rtems_task_delete_extension.
0386  * @endparblock
0387  *
0388  * @par Constraints
0389  * @parblock
0390  * The following constraints apply to functions of this type:
0391  *
0392  * * While the system is initialized, thread dispatching is disabled.
0393  *
0394  * * While the system is in the multitasking state, thread dispatching is
0395  *   enabled.
0396  *
0397  * * While an idle thread or another internal system thread is created, the
0398  *   object allocator mutex has no owner.
0399  *
0400  * * While a task is created by rtems_task_create(), the executing thread is
0401  *   the owner of the object allocator mutex.
0402  *
0403  * * While a task is constructed by rtems_task_construct(), the executing
0404  *   thread is the owner of the object allocator mutex.
0405  *
0406  * * While a task is created by pthread_create(), the executing thread is the
0407  *   owner of the object allocator mutex.
0408  * @endparblock
0409  */
0410 typedef User_extensions_thread_create_extension rtems_task_create_extension;
0411 
0412 /* Generated from spec:/rtems/userext/if/task-delete */
0413 
0414 /**
0415  * @ingroup RTEMSAPIClassicUserExt
0416  *
0417  * @brief Task delete extensions are invoked when a task is deleted.
0418  *
0419  * @param executing is the TCB of the executing thread.  If the idle thread is
0420  *   created and one of the initial task create extension fails, then the
0421  *   executing thread is equal to NULL.
0422  *
0423  * @param created is the TCB of the deleted thread.  The executing and deleted
0424  *   arguments are never equal.
0425  *
0426  * @par Notes
0427  * @parblock
0428  * The task delete extensions are invoked in extension reverse order.
0429  *
0430  * The task delete extensions are invoked by task create directives before an
0431  * attempt to allocate a TCB is made.
0432  *
0433  * If a task create extension failed, then a task delete extension may be
0434  * invoked without a previous invocation of the corresponding task create
0435  * extension of the extension set.
0436  * @endparblock
0437  *
0438  * @par Constraints
0439  * @parblock
0440  * The following constraints apply to functions of this type:
0441  *
0442  * * While the system is initialized, thread dispatching is disabled.
0443  *
0444  * * While the system is in the multitasking state, thread dispatching is
0445  *   enabled.
0446  *
0447  * * While an idle thread or another internal system thread is created, the
0448  *   object allocator mutex has no owner.
0449  *
0450  * * While a task is created by rtems_task_create(), the executing thread is
0451  *   the owner of the object allocator mutex.
0452  *
0453  * * While a task is constructed by rtems_task_construct(), the executing
0454  *   thread is the owner of the object allocator mutex.
0455  *
0456  * * While a task is created by pthread_create(), the executing thread is the
0457  *   owner of the object allocator mutex.
0458  * @endparblock
0459  */
0460 typedef User_extensions_thread_delete_extension rtems_task_delete_extension;
0461 
0462 /* Generated from spec:/rtems/userext/if/task-exitted */
0463 
0464 /**
0465  * @ingroup RTEMSAPIClassicUserExt
0466  *
0467  * @brief Task exitted extensions are invoked when a task entry returns.
0468  *
0469  * @param executing is the TCB of the executing thread.
0470  *
0471  * @par Notes
0472  * The task exitted extensions are invoked in extension forward order.
0473  *
0474  * @par Constraints
0475  * @parblock
0476  * The following constraints apply to functions of this type:
0477  *
0478  * * Thread dispatching is enabled.
0479  * @endparblock
0480  */
0481 typedef User_extensions_thread_exitted_extension rtems_task_exitted_extension;
0482 
0483 /* Generated from spec:/rtems/userext/if/task-restart */
0484 
0485 /**
0486  * @ingroup RTEMSAPIClassicUserExt
0487  *
0488  * @brief Task restart extensions are invoked when a task restarts.
0489  *
0490  * @param executing is the TCB of the executing thread.
0491  *
0492  * @param restarted is the TCB of the executing thread.  Yes, the executing
0493  *   thread.
0494  *
0495  * @par Notes
0496  * @parblock
0497  * The task restart extensions are invoked in extension forward order.
0498  *
0499  * The task restart extensions are invoked in the context of the restarted
0500  * thread right before the execution context is reloaded.  The thread stack
0501  * reflects the previous execution context.
0502  *
0503  * Thread restart and delete requests issued by restart extensions lead to
0504  * recursion.
0505  * @endparblock
0506  *
0507  * @par Constraints
0508  * @parblock
0509  * The following constraints apply to functions of this type:
0510  *
0511  * * Thread dispatching is enabled.
0512  *
0513  * * Thread life is protected.
0514  *
0515  * * The executing thread is not the owner of the object allocator mutex.
0516  * @endparblock
0517  */
0518 typedef User_extensions_thread_restart_extension rtems_task_restart_extension;
0519 
0520 /* Generated from spec:/rtems/userext/if/task-start */
0521 
0522 /**
0523  * @ingroup RTEMSAPIClassicUserExt
0524  *
0525  * @brief Task start extensions are invoked when a task was made ready for the
0526  *   first time.
0527  *
0528  * @param executing is the TCB of the executing thread.
0529  *
0530  * @param started is the TCB of the started thread.
0531  *
0532  * @par Notes
0533  * @parblock
0534  * The task start extensions are invoked in extension forward order.
0535  *
0536  * In SMP configurations, the thread may already run on another processor
0537  * before the task start extensions are actually invoked.  Task switch and task
0538  * begin extensions may run before or in parallel with the thread start
0539  * extension in SMP configurations, see ::rtems_task_switch_extension and
0540  * ::rtems_task_begin_extension.
0541  * @endparblock
0542  *
0543  * @par Constraints
0544  * @parblock
0545  * The following constraints apply to functions of this type:
0546  *
0547  * * Thread dispatching is disabled.
0548  * @endparblock
0549  */
0550 typedef User_extensions_thread_start_extension rtems_task_start_extension;
0551 
0552 /* Generated from spec:/rtems/userext/if/task-switch */
0553 
0554 /**
0555  * @ingroup RTEMSAPIClassicUserExt
0556  *
0557  * @brief Task switch extensions are invoked when a thread switch from an
0558  *   executing thread to a heir thread takes place.
0559  *
0560  * @param executing is the TCB of the executing thread.  In SMP configurations,
0561  *   this is the previously executing thread also known as the ancestor thread.
0562  *
0563  * @param heir is the TCB of the heir thread.  In SMP configurations, this is
0564  *   the executing thread.
0565  *
0566  * @par Notes
0567  * @parblock
0568  * The task switch extensions are invoked in extension forward order.
0569  *
0570  * The invocation conditions of the task switch extensions depend on whether
0571  * RTEMS was built with SMP support enabled or disabled.  A user must pay
0572  * attention to the differences to correctly implement a task switch extension.
0573  *
0574  * Where the system was built with SMP support disabled, the task switch
0575  * extensions are invoked before the context switch from the currently
0576  * executing thread to the heir thread.  The ``executing`` is a pointer to the
0577  * TCB of the currently executing thread. The ``heir`` is a pointer to the TCB
0578  * of the heir thread.  The context switch initiated through the multitasking
0579  * start is not covered by the task switch extensions.
0580  *
0581  * Where the system was built with SMP support enabled, the task switch
0582  * extensions are invoked after the context switch to the heir thread.  The
0583  * ``executing`` is a pointer to the TCB of the previously executing thread.
0584  * Despite the name, this is not the currently executing thread. The ``heir``
0585  * is a pointer to the TCB of the newly executing thread. This is the currently
0586  * executing thread. The context switches initiated through the multitasking
0587  * start are covered by the task switch extensions. The reason for the
0588  * differences to uniprocessor configurations is that the context switch may
0589  * update the heir thread of the processor.  The task switch extensions are
0590  * invoked with maskable interrupts disabled and with ownership of a
0591  * processor-specific SMP lock.  Task switch extensions may run in parallel on
0592  * multiple processors.  It is recommended to use thread-local or
0593  * processor-specific data structures for task switch extensions.  A global SMP
0594  * lock should be avoided for performance reasons, see
0595  * rtems_interrupt_lock_initialize().
0596  * @endparblock
0597  *
0598  * @par Constraints
0599  * @parblock
0600  * The following constraints apply to functions of this type:
0601  *
0602  * * Thread dispatching is disabled.
0603  *
0604  * * Where the system was built with SMP support enabled, maskable interrupts
0605  *   are disabled for the executing thread.
0606  * @endparblock
0607  */
0608 typedef User_extensions_thread_switch_extension rtems_task_switch_extension;
0609 
0610 /* Generated from spec:/rtems/userext/if/task-terminate */
0611 
0612 /**
0613  * @ingroup RTEMSAPIClassicUserExt
0614  *
0615  * @brief Task terminate extensions are invoked when a task terminates.
0616  *
0617  * @param executing is the TCB of the executing thread.  This is the
0618  *   terminating thread.
0619  *
0620  * @par Notes
0621  * @parblock
0622  * The task terminate extensions are invoked in extension reverse order.
0623  *
0624  * The task terminate extensions are invoked in the context of the terminating
0625  * thread right before the thread dispatch to the heir thread should take
0626  * place. The thread stack reflects the previous execution context.  The POSIX
0627  * cleanup and key destructors execute in this context.
0628  *
0629  * Thread restart and delete requests issued by terminate extensions lead to
0630  * recursion.
0631  * @endparblock
0632  *
0633  * @par Constraints
0634  * @parblock
0635  * The following constraints apply to functions of this type:
0636  *
0637  * * Thread dispatching is enabled.
0638  *
0639  * * Thread life is protected.
0640  *
0641  * * The executing thread is not the owner of the object allocator mutex.
0642  * @endparblock
0643  */
0644 typedef User_extensions_thread_terminate_extension rtems_task_terminate_extension;
0645 
0646 #ifdef __cplusplus
0647 }
0648 #endif
0649 
0650 #endif /* _RTEMS_EXTENSION_H */