diff options
Diffstat (limited to 'cpukit/score/include/rtems/score')
45 files changed, 10276 insertions, 0 deletions
diff --git a/cpukit/score/include/rtems/score/.cvsignore b/cpukit/score/include/rtems/score/.cvsignore new file mode 100644 index 0000000000..d9ecd15e8c --- /dev/null +++ b/cpukit/score/include/rtems/score/.cvsignore @@ -0,0 +1 @@ +cpuopts.h diff --git a/cpukit/score/include/rtems/score/address.h b/cpukit/score/include/rtems/score/address.h new file mode 100644 index 0000000000..034d905d32 --- /dev/null +++ b/cpukit/score/include/rtems/score/address.h @@ -0,0 +1,43 @@ +/** + * @file rtems/score/address.h + * + * This include file contains the information required to manipulate + * physical addresses. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_ADDRESS_H +#define _RTEMS_SCORE_ADDRESS_H + +/** + * @defgroup ScoreAddress Address Handler + * + * This handler encapsulates functionality which abstracts address + * manipulation in a portable manner. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/address.inl> + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/apiext.h b/cpukit/score/include/rtems/score/apiext.h new file mode 100644 index 0000000000..c51bcc7b6e --- /dev/null +++ b/cpukit/score/include/rtems/score/apiext.h @@ -0,0 +1,133 @@ +/** + * @file rtems/score/apiext.h + * + * This is the API Extensions Handler. + */ + +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_APIEXT_H +#define _RTEMS_SCORE_APIEXT_H + +/** + * @defgroup ScoreAPIExtension API Extension Handler + * + * This handler encapsulates functionality which provides mechanisms for the + * SuperCore to perform API specific actions without there beingg + * "up-references" from the SuperCore to APIs. If these referencesg + * were allowed in the implementation, the cohesion would be too high + * and adding an API would be more difficult. The SuperCore is supposed + * to be largely independent of any API. + */ +/**@{*/ + +#include <rtems/score/chain.h> +#include <rtems/score/thread.h> + +#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + /** + * This type defines the prototype of the Predriver Hook. + */ + typedef void (*API_extensions_Predriver_hook)(void); +#endif + +/** + * This type defines the prototype of the Postdriver Hook. + */ +typedef void (*API_extensions_Postdriver_hook)(void); + +/** + * This type defines the prototype of the Postswitch Hook. + */ +typedef void (*API_extensions_Postswitch_hook)( + Thread_Control * + ); + +/** + * The control structure which defines the points at which an API + * can add an extension to the system initialization thread. + */ +typedef struct { + /** This field allows this structure to be used with the Chain Handler. */ + Chain_Node Node; + #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + /** + * This field is the callout invoked during RTEMS initialization after + * RTEMS data structures are initialized before device driver initialization + * has occurred. + * + * @note If this field is NULL, no extension is invoked. + */ + API_extensions_Predriver_hook predriver_hook; + #endif + /** + * This field is the callout invoked during RTEMS initialization after + * RTEMS data structures and device driver initialization has occurred + * but before multitasking is initiated. + * + * @note If this field is NULL, no extension is invoked. + */ + API_extensions_Postdriver_hook postdriver_hook; + /** + * This field is the callout invoked during each context switch + * in the context of the heir thread. + * + * @note If this field is NULL, no extension is invoked. + */ + API_extensions_Postswitch_hook postswitch_hook; +} API_extensions_Control; + +/** + * This is the list of API extensions to the system initialization. + */ +SCORE_EXTERN Chain_Control _API_extensions_List; + +/** @brief Initialize the API Extensions Handler + * + * This routine initializes the API extension handler. + */ +void _API_extensions_Initialization( void ); + +/** @brief Add Extension Set to the Active Set + * + * This routine adds an extension to the active set of API extensions. + * + * @param[in] the_extension is the extension set to add. + */ +void _API_extensions_Add( + API_extensions_Control *the_extension +); + +#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + /** @brief Execute all Pre-Driver Extensions + * + * This routine executes all of the predriver callouts. + */ + void _API_extensions_Run_predriver( void ); +#endif + +/** @brief Execute all Post-Driver Extensions + * + * This routine executes all of the postdriver callouts. + */ +void _API_extensions_Run_postdriver( void ); + +/** @brief Execute all Post Context Switch Extensions + * + * This routine executes all of the post context switch callouts. + */ +void _API_extensions_Run_postswitch( void ); + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/apimutex.h b/cpukit/score/include/rtems/score/apimutex.h new file mode 100644 index 0000000000..691f60b709 --- /dev/null +++ b/cpukit/score/include/rtems/score/apimutex.h @@ -0,0 +1,116 @@ +/** + * @file + * + * @ingroup ScoreAPIMutex + * + * @brief API Mutex Handler API. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_APIMUTEX_H +#define _RTEMS_SCORE_APIMUTEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup ScoreAPIMutex API Mutex Handler + * + * @ingroup Score + * + * @brief Provides routines to ensure mutual exclusion on API level. + * + * @{ + */ + +#include <rtems/score/coremutex.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> + +/** + * @brief Control block used to manage each API mutex. + */ +typedef struct { + /** + * @brief Allows each API Mutex to be a full-fledged RTEMS object. + */ + Objects_Control Object; + + /** + * Contains the SuperCore mutex information. + */ + CORE_mutex_Control Mutex; +} API_Mutex_Control; + +/** + * @brief Information control block used to manage this class of objects. + */ +SCORE_EXTERN Objects_Information _API_Mutex_Information; + +/** + * @brief Performs the initialization necessary for this handler. + * + * The value @a maximum_mutexes is the maximum number of API mutexes that may + * exist at any time. + */ +void _API_Mutex_Initialization( uint32_t maximum_mutexes ); + +/** + * @brief Allocates an API mutex from the inactive set and returns it in + * @a mutex. + */ +void _API_Mutex_Allocate( API_Mutex_Control **mutex ); + +/** + * @brief Acquires the specified API mutex @a mutex. + */ +void _API_Mutex_Lock( API_Mutex_Control *mutex ); + +/** + * @brief Releases the specified API mutex @a mutex. + */ +void _API_Mutex_Unlock( API_Mutex_Control *mutex ); + +/** @} */ + +/** + * @defgroup ScoreAllocatorMutex RTEMS Allocator Mutex + * + * @ingroup ScoreAPIMutex + * + * @brief Protection for all memory allocations and deallocations in RTEMS. + * + * When the APIs all use this for allocation and deallocation protection, then + * this possibly should be renamed and moved to a higher level in the + * hierarchy. + * + * @{ + */ + +SCORE_EXTERN API_Mutex_Control *_RTEMS_Allocator_Mutex; + +#define _RTEMS_Lock_allocator() \ + _API_Mutex_Lock( _RTEMS_Allocator_Mutex ) + +#define _RTEMS_Unlock_allocator() \ + _API_Mutex_Unlock( _RTEMS_Allocator_Mutex ) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/basedefs.h b/cpukit/score/include/rtems/score/basedefs.h new file mode 100644 index 0000000000..b956806313 --- /dev/null +++ b/cpukit/score/include/rtems/score/basedefs.h @@ -0,0 +1,175 @@ +/** + * @file + * + * @ingroup Score + * + * @brief Basic definitions. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * Copyright (c) 2010 embedded brains GmbH. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_BASEDEFS_H +#define _RTEMS_BASEDEFS_H + +#include <rtems/score/cpuopts.h> + +#ifndef ASM + #include <stddef.h> + #include <stdbool.h> + #include <stdint.h> +#endif + +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef FALSE + #define FALSE 0 +#endif + +#if TRUE == FALSE + #error "TRUE equals FALSE" +#endif + +/** + * The following ensures that all data is declared in the space + * of the initialization routine for either the Initialization Manager + * or the initialization file for the appropriate API. It is + * referenced as "external" in every other file. + */ +#ifdef SCORE_INIT +#undef SCORE_EXTERN +#define SCORE_EXTERN +#else +#undef SCORE_EXTERN +#define SCORE_EXTERN extern +#endif + +/** + * The following ensures that all data is declared in the space + * of the initialization routine for either the Initialization Manager + * or the initialization file for the appropriate API. It is + * referenced as "external" in every other file. + */ +#ifdef SAPI_INIT +#undef SAPI_EXTERN +#define SAPI_EXTERN +#else +#undef SAPI_EXTERN +#define SAPI_EXTERN extern +#endif + +/** + * The following ensures that all data is declared in the space + * of the initialization routine for either the Initialization Manager + * or the initialization file for the appropriate API. It is + * referenced as "external" in every other file. + */ +#ifdef RTEMS_API_INIT +#undef RTEMS_EXTERN +#define RTEMS_EXTERN +#else +#undef RTEMS_EXTERN +#define RTEMS_EXTERN extern +#endif + +/** + * The following ensures that all data is declared in the space + * of the initialization routine for either the Initialization Manager + * or the initialization file for the appropriate API. It is + * referenced as "external" in every other file. + */ +#ifdef POSIX_API_INIT +#undef POSIX_EXTERN +#define POSIX_EXTERN +#else +#undef POSIX_EXTERN +#define POSIX_EXTERN extern +#endif + +/** + * The following (in conjunction with compiler arguments) are used + * to choose between the use of static inline functions and macro + * functions. The static inline implementation allows better + * type checking with no cost in code size or execution speed. + */ +#ifdef __GNUC__ +# define RTEMS_INLINE_ROUTINE static __inline__ +#else +# define RTEMS_INLINE_ROUTINE static inline +#endif + +/** + * The following macro is a compiler specific way to ensure that memory + * writes are not reordered around certian points. This specifically can + * impact interrupt disable and thread dispatching critical sections. + */ +#ifdef __GNUC__ + #define RTEMS_COMPILER_MEMORY_BARRIER() __asm__ volatile("" ::: "memory") +#else + #define RTEMS_COMPILER_MEMORY_BARRIER() +#endif + +/** + * The following macro is a compiler specific way to indicate that + * the method will NOT return to the caller. This can assist the + * compiler in code generation and avoid unreachable paths. This + * can impact the code generated following calls to + * rtems_fatal_error_occurred and _Internal_error_Occurred. + */ +#ifdef __GNUC__ + #define RTEMS_COMPILER_NO_RETURN_ATTRIBUTE \ + __attribute__ ((noreturn)) +#else + #define RTEMS_COMPILER_NO_RETURN_ATTRIBUTE +#endif + +/** + * The following defines a compiler specific attribute which informs + * the compiler that the method has no effect except the return value + * and that the return value depends only on parameters and/or global + * variables. + */ +#ifdef __GNUC__ + #define RTEMS_COMPILER_PURE_ATTRIBUTE \ + __attribute__ ((pure)) +#else + #define RTEMS_COMPILER_PURE_ATTRIBUTE +#endif + +/** + * Instructs the compiler to issue a warning whenever a variable or function + * with this attribute will be used. + */ +#ifdef __GNUC__ + #define RTEMS_COMPILER_DEPRECATED_ATTRIBUTE \ + __attribute__ ((deprecated)) +#else + #define RTEMS_COMPILER_DEPRECATED_ATTRIBUTE +#endif + +#ifndef ASM + #ifdef RTEMS_DEPRECATED_TYPES + typedef bool boolean; + typedef float single_precision; + typedef double double_precision; + #endif + + /** + * XXX: Eventually proc_ptr needs to disappear!!! + */ + typedef void * proc_ptr; +#endif + +#endif /* _RTEMS_BASEDEFS_H */ diff --git a/cpukit/score/include/rtems/score/bitfield.h b/cpukit/score/include/rtems/score/bitfield.h new file mode 100644 index 0000000000..43f8fd09c4 --- /dev/null +++ b/cpukit/score/include/rtems/score/bitfield.h @@ -0,0 +1,106 @@ +/** + * @file rtems/score/bitfield.h + * + * This include file contains all bit field manipulation routines. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_BITFIELD_H +#define _RTEMS_SCORE_BITFIELD_H + +/** + * @defgroup ScoreBitfield Bitfield Handler + * + * This handler encapsulates functionality that is used to manipulate the + * priority bitfields used to lookup which priority has the highest + * priority ready to execute thread. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE ) + +/** + * This table is used by the generic bitfield routines to perform + * a highly optimized bit scan without the use of special CPU + * instructions. + */ +#ifndef SCORE_INIT +extern const unsigned char __log2table[256]; +#else +const unsigned char __log2table[256] = { + 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#endif + +/** + * This routine returns the @a _bit_number of the first bit set + * in the specified value. The correspondence between @a _bit_number + * and actual bit position is processor dependent. The search for + * the first bit set may run from most to least significant bit + * or vice-versa. + * + * @param[in] _value is the value to bit scan. + * @param[in] _bit_number is the position of the first bit set. + * + * @note This routine is used when the executing thread is removed + * from the ready state and, as a result, its performance has a + * significant impact on the performance of the executive as a whole. + * + * @note This routine must be a macro because if a CPU specific version + * is used it will most likely use inline assembly. + */ +#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE ) +#define _Bitfield_Find_first_bit( _value, _bit_number ) \ + _CPU_Bitfield_Find_first_bit( _value, _bit_number ) +#else +#define _Bitfield_Find_first_bit( _value, _bit_number ) \ + { \ + register uint32_t __value = (uint32_t) (_value); \ + register const unsigned char *__p = __log2table; \ + \ + if ( __value < 0x100 ) \ + (_bit_number) = (Priority_bit_map_Control)( __p[ __value ] + 8 ); \ + else \ + (_bit_number) = (Priority_bit_map_Control)( __p[ __value >> 8 ] ); \ + } +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/chain.h b/cpukit/score/include/rtems/score/chain.h new file mode 100644 index 0000000000..187a466c90 --- /dev/null +++ b/cpukit/score/include/rtems/score/chain.h @@ -0,0 +1,258 @@ +/** + * @file + * + * @ingroup ScoreChain + * + * @brief Chain Handler API. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_CHAIN_H +#define _RTEMS_SCORE_CHAIN_H + +/** + * @defgroup ScoreChain Chain Handler + * + * @ingroup Score + * + * The Chain Handler is used to manage sets of entities. This handler + * provides two data structures. The Chain Node data structure is included + * as the first part of every data structure that will be placed on + * a chain. The second data structure is Chain Control which is used + * to manage a set of Chain Nodes. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/address.h> + +/** + * @typedef Chain_Node + * + * This type definition promotes the name for the Chain Node used by + * all RTEMS code. It is a separate type definition because a forward + * reference is required to define it. See @ref Chain_Node_struct for + * detailed information. + */ +typedef struct Chain_Node_struct Chain_Node; + +/** + * @struct Chain_Node_struct + * + * This is used to manage each element (node) which is placed + * on a chain. + * + * @note Typically, a more complicated structure will use the + * chain package. The more complicated structure will + * include a chain node as the first element in its + * control structure. It will then call the chain package + * with a pointer to that node element. The node pointer + * and the higher level structure start at the same address + * so the user can cast the pointers back and forth. + * + */ +struct Chain_Node_struct { + /** This points to the node after to this one on this chain. */ + Chain_Node *next; + /** This points to the node immediate prior to this one on this chain. */ + Chain_Node *previous; +}; + +/** + * @struct Chain_Control + * + * This is used to manage a chain. A chain consists of a doubly + * linked list of zero or more nodes. + * + * @note This implementation does not require special checks for + * manipulating the first and last elements on the chain. + * To accomplish this the @a Chain_Control structure is + * treated as two overlapping @ref Chain_Node structures. + */ +typedef union { + struct { + Chain_Node Node; + Chain_Node *fill; + } Head; + + struct { + Chain_Node *fill; + Chain_Node Node; + } Tail; +} Chain_Control; + +/** + * @brief Chain initializer for an empty chain with designator @a name. + */ +#define CHAIN_INITIALIZER_EMPTY(name) \ + { { { &(name).Tail.Node, NULL }, &(name).Head.Node } } + +/** + * @brief Chain definition for an empty chain with designator @a name. + */ +#define CHAIN_DEFINE_EMPTY(name) \ + Chain_Control name = CHAIN_INITIALIZER_EMPTY(name) + +/** + * @brief Initialize a Chain Header + * + * This routine initializes @a the_chain structure to manage the + * contiguous array of @a number_nodes nodes which starts at + * @a starting_address. Each node is of @a node_size bytes. + * + * @param[in] the_chain specifies the chain to initialize + * @param[in] starting_address is the starting address of the array + * of elements + * @param[in] number_nodes is the numebr of nodes that will be in the chain + * @param[in] node_size is the size of each node + */ +void _Chain_Initialize( + Chain_Control *the_chain, + void *starting_address, + size_t number_nodes, + size_t node_size +); + +/** + * @brief Extract the specified node from a chain + * + * This routine extracts @a the_node from the chain on which it resides. + * It disables interrupts to ensure the atomicity of the + * extract operation. + * + * @arg the_node specifies the node to extract + */ +void _Chain_Extract( + Chain_Node *the_node +); + +/** + * @brief Obtain the first node on a chain + * + * This function removes the first node from @a the_chain and returns + * a pointer to that node. If @a the_chain is empty, then NULL is returned. + * + * @return This method returns a pointer a node. If a node was removed, + * then a pointer to that node is returned. If @a the_chain was + * empty, then NULL is returned. + * + * @note It disables interrupts to ensure the atomicity of the get operation. + */ +Chain_Node *_Chain_Get( + Chain_Control *the_chain +); + +/** + * @brief Insert a node on a chain + * + * This routine inserts @a the_node on a chain immediately following + * @a after_node. + * + * @note It disables interrupts to ensure the atomicity + * of the extract operation. + */ +void _Chain_Insert( + Chain_Node *after_node, + Chain_Node *the_node +); + +/** + * @brief Append a node on the end of a chain + * + * This routine appends @a the_node onto the end of @a the_chain. + * + * @note It disables interrupts to ensure the atomicity of the + * append operation. + */ +void _Chain_Append( + Chain_Control *the_chain, + Chain_Node *the_node +); + +/** + * @brief Append a node and check if the chain was empty before. + * + * This routine appends the_node onto the end of the_chain. + * + * @param[in] the_chain is the chain to be operated upon. + * @param[in] the_node is the node to be appended. + * + * @note It disables interrupts to ensure the atomicity of the append + * operation. + * + * @retval true The chain was empty before. + * @retval false The chain contained at least one node before. + */ +bool _Chain_Append_with_empty_check( + Chain_Control *the_chain, + Chain_Node *the_node +); + +/** + * @brief Prepend a node and check if the chain was empty before. + * + * This routine prepends the_node onto the front of the_chain. + * + * @param[in] the_chain is the chain to be operated upon. + * @param[in] the_node is the node to be prepended. + * + * @note It disables interrupts to ensure the atomicity of the append + * operation. + * + * @retval true The chain was empty before. + * @retval false The chain contained at least one node before. + */ +bool _Chain_Prepend_with_empty_check( + Chain_Control *the_chain, + Chain_Node *the_node +); + +/** + * @brief Get the first node and check if the chain is empty afterwards. + * + * This function removes the first node from the_chain and returns + * a pointer to that node in @a the_node. If the_chain is empty, then NULL is + * returned. + * + * @param[in] the_chain is the chain to attempt to get the first node from. + * @param[out] the_node is the first node on the chain or NULL if the chain is + * empty. + * + * @note It disables interrupts to ensure the atomicity of the append + * operation. + * + * @retval true The chain is empty now. + * @retval false The chain contains at least one node now. + */ +bool _Chain_Get_with_empty_check( + Chain_Control *the_chain, + Chain_Node **the_node +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/chain.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/context.h b/cpukit/score/include/rtems/score/context.h new file mode 100644 index 0000000000..34baf32669 --- /dev/null +++ b/cpukit/score/include/rtems/score/context.h @@ -0,0 +1,180 @@ +/** + * @file rtems/score/context.h + * + * This include file contains all information about each thread's context. + */ + +/* + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_CONTEXT_H +#define _RTEMS_SCORE_CONTEXT_H + +/** + * @defgroup ScoreContext Context Handler + * + * This handler encapsulates functionality which abstracts thread context + * management in a portable manner. + * + * The context switch needed variable is contained in the per cpu + * data structure. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/cpu.h> + +/** + * @brief Size of Floating Point Context Area + * + * This constant defines the number of bytes required + * to store a full floating point context. + */ +#define CONTEXT_FP_SIZE CPU_CONTEXT_FP_SIZE + +/** + * @brief Initialize Context Area + * + * This routine initializes @a _the_context such that the stack + * pointer, interrupt level, and entry point are correct for the + * thread's initial state. + * + * @param[in] _the_context will be initialized + * @param[in] _stack is the lowest physical address of the thread's + * context + * @param[in] _size is the size in octets of the thread's context + * @param[in] _isr is the ISR enable level for this thread + * @param[in] _entry is this thread's entry point + * @param[in] _is_fp is set to true if this thread has floating point + * enabled + */ +#define _Context_Initialize(_the_context, _stack, _size, _isr, _entry, _is_fp) \ + _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) + +/** + * This macro is invoked from _Thread_Handler to do whatever CPU + * specific magic is required that must be done in the context of + * the thread when it starts. + * + * If the CPU architecture does not require any magic, then this + * macro is empty. + */ + +#if defined(_CPU_Context_Initialization_at_thread_begin) + #define _Context_Initialization_at_thread_begin() \ + _CPU_Context_Initialization_at_thread_begin() +#else + #define _Context_Initialization_at_thread_begin() +#endif + +/** + * @brief Perform Context Switch + * + * This routine saves the current context into the @a _executing + * context record and restores the context specified by @a _heir. + * + * @param[in] _executing is the currently executing thread's context + * @param[in] _heir is the context of the thread to be switched to + */ +#define _Context_Switch( _executing, _heir ) \ + _CPU_Context_switch( _executing, _heir ) + +/** + * @brief Restart Currently Executing Thread + * + * This routine restarts the calling thread by restoring its initial + * stack pointer and returning to the thread's entry point. + * + * @param[in] _the_context is the context of the thread to restart + */ +#define _Context_Restart_self( _the_context ) \ + _CPU_Context_Restart_self( _the_context ) + +#if defined(RTEMS_SMP) +/* + * @brief Switch to First Task on Secondary Core + * + * This routine is only used to switch to the first task on a + * secondary core in an SMP configuration. Since the switch + * to the first task is done from an interrupt handler, this + * may be different from simply restarting the currently running + * task. + * + * @param[in] _the_context is the context of the first thread to + * run on this core + */ +#define _Context_Switch_to_first_task_smp( _the_context ) \ + _CPU_Context_switch_to_first_task_smp( _the_context ) +#endif + +/** + * @brief Return Starting Address of Floating Point Context + * + * This function returns the starting address of the floating + * point context save area. It is assumed that the are reserved + * for the floating point save area is large enough. + * + * @param[in] _base is lowest physical address of the floating point + * context save area. + * @param[in] _offset is the offset into the floating point area + * + * @return the initial FP context pointer + */ +#define _Context_Fp_start( _base, _offset ) \ + _CPU_Context_Fp_start( (_base), (_offset) ) + +/** + * @brief Initialize Floating Point Context Area + * + * This routine initializes the floating point context save + * area to contain an initial known state. + * + * @param[in] _fp_area is the base address of the floating point + * context save area to initialize. + */ +#define _Context_Initialize_fp( _fp_area ) \ + _CPU_Context_Initialize_fp( _fp_area ) + +/** + * @brief Restore Floating Point Context Area + * + * This routine restores the floating point context contained + * in the @a _fp area. It is assumed that the current + * floating point context has been saved by a previous invocation + * of @a _Context_Save_fp. + * + * @param[in] _fp points to the floating point context area to restore. + */ +#define _Context_Restore_fp( _fp ) \ + _CPU_Context_restore_fp( _fp ) + +/** + * @brief Save Floating Point Context Area + * + * This routine saves the current floating point context + * in the @a _fp area. + * + * @param[in] _fp points to the floating point context area to restore. + */ +#define _Context_Save_fp( _fp ) \ + _CPU_Context_save_fp( _fp ) + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/copyrt.h b/cpukit/score/include/rtems/score/copyrt.h new file mode 100644 index 0000000000..8c418abd7c --- /dev/null +++ b/cpukit/score/include/rtems/score/copyrt.h @@ -0,0 +1,42 @@ +/** + * @file rtems/score/copyrt.h + * + * This include file contains the copyright notice for RTEMS + * which is included in every binary copy of the executive. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_COPYRT_H +#define _RTEMS_SCORE_COPYRT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This is the copyright string for RTEMS. + */ +#ifdef SCORE_INIT +const char _Copyright_Notice[] = +"COPYRIGHT (c) 1989-2008.\n\ +On-Line Applications Research Corporation (OAR).\n"; +#else +extern const char _Copyright_Notice[]; +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/corebarrier.h b/cpukit/score/include/rtems/score/corebarrier.h new file mode 100644 index 0000000000..05ec152487 --- /dev/null +++ b/cpukit/score/include/rtems/score/corebarrier.h @@ -0,0 +1,202 @@ +/** + * @file rtems/score/corebarrier.h + * + * This include file contains all the constants and structures associated + * with the Barrier Handler. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_COREBARRIER_H +#define _RTEMS_SCORE_COREBARRIER_H + +/** + * @defgroup ScoreBarrier Barrier Handler + * + * This handler encapsulates functionality which provides the foundation + * Barrier services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/priority.h> +#include <rtems/score/watchdog.h> + +/** + * The following type defines the callout which the API provides + * to support global/multiprocessor operations on barriers. + */ +typedef void ( *CORE_barrier_API_mp_support_callout )( + Thread_Control *, + Objects_Id + ); + +/** + * Flavors of barriers. + */ +typedef enum { + /** This specifies that the barrier will automatically release when + * the user specified number of threads have arrived at the barrier. + */ + CORE_BARRIER_AUTOMATIC_RELEASE, + /** This specifies that the user will have to manually release the barrier + * in order to release the waiting threads. + */ + CORE_BARRIER_MANUAL_RELEASE +} CORE_barrier_Disciplines; + +/** + * Core Barrier handler return statuses. + */ +typedef enum { + /** This status indicates that the operation completed successfully. */ + CORE_BARRIER_STATUS_SUCCESSFUL, + /** This status indicates that the barrier is configured for automatic + * release and the caller tripped the automatic release. The caller + * thus did not block. + */ + CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED, + /** This status indicates that the thread was blocked waiting for an + * operation to complete and the barrier was deleted. + */ + CORE_BARRIER_WAS_DELETED, + /** This status indicates that the calling task was willing to block + * but the operation was unable to complete within the time allotted + * because the resource never became available. + */ + CORE_BARRIER_TIMEOUT +} CORE_barrier_Status; + +/** + * @brief Core Barrier Last Status + * + * This is the last status value. + */ +#define CORE_BARRIER_STATUS_LAST CORE_BARRIER_TIMEOUT + +/** + * The following defines the control block used to manage the + * attributes of each barrier. + */ +typedef struct { + /** This field indicates whether the barrier is automatic or manual. + */ + CORE_barrier_Disciplines discipline; + /** This element indicates the number of threads which must arrive at the + * barrier to trip the automatic release. + */ + uint32_t maximum_count; +} CORE_barrier_Attributes; + +/** + * The following defines the control block used to manage each + * barrier. + */ +typedef struct { + /** This field is the Waiting Queue used to manage the set of tasks + * which are blocked waiting for the barrier to be released. + */ + Thread_queue_Control Wait_queue; + /** This element is the set of attributes which define this instance's + * behavior. + */ + CORE_barrier_Attributes Attributes; + /** This element contains the current number of thread waiting for this + * barrier to be released. */ + uint32_t number_of_waiting_threads; +} CORE_barrier_Control; + +/** + * This routine initializes the barrier based on the parameters passed. + * + * @param[in] the_barrier is the barrier to initialize + * @param[in] the_barrier_attributes define the behavior of this instance + */ +void _CORE_barrier_Initialize( + CORE_barrier_Control *the_barrier, + CORE_barrier_Attributes *the_barrier_attributes +); + +/** + * This routine wait for the barrier to be released. If the barrier + * is set to automatic and this is the appropriate thread, then it returns + * immediately. Otherwise, the calling thread is blocked until the barrier + * is released. + * + * @param[in] the_barrier is the barrier to wait for + * @param[in] id is the id of the object being waited upon + * @param[in] wait is true if the calling thread is willing to wait + * @param[in] timeout is the number of ticks the calling thread is willing + * to wait if @a wait is true. + * @param[in] api_barrier_mp_support is the routine to invoke if the + * thread unblocked is remote + * + * @note Status is returned via the thread control block. + */ +void _CORE_barrier_Wait( + CORE_barrier_Control *the_barrier, + Objects_Id id, + bool wait, + Watchdog_Interval timeout, + CORE_barrier_API_mp_support_callout api_barrier_mp_support +); + +/** + * This routine manually releases the barrier. All of the threads waiting + * for the barrier will be readied. + * + * @param[in] the_barrier is the barrier to surrender + * @param[in] id is the id of the object for a remote unblock + * @param[in] api_barrier_mp_support is the routine to invoke if the + * thread unblocked is remote + * + * @return the number of unblocked threads + */ +uint32_t _CORE_barrier_Release( + CORE_barrier_Control *the_barrier, + Objects_Id id, + CORE_barrier_API_mp_support_callout api_barrier_mp_support +); + +/** + * This routine assists in the deletion of a barrier by flushing the + * associated wait queue. + * + * @param[in] _the_barrier is the barrier to flush + * @param[in] _remote_extract_callout is the routine to invoke if the + * thread unblocked is remote + * @param[in] _status is the status to be returned to the unblocked thread + */ +#define _CORE_barrier_Flush( _the_barrier, _remote_extract_callout, _status) \ + _Thread_queue_Flush( \ + &((_the_barrier)->Wait_queue), \ + (_remote_extract_callout), \ + (_status) \ + ) + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/corebarrier.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/coremsg.h b/cpukit/score/include/rtems/score/coremsg.h new file mode 100644 index 0000000000..4a93f6de25 --- /dev/null +++ b/cpukit/score/include/rtems/score/coremsg.h @@ -0,0 +1,451 @@ +/** + * @file rtems/score/coremsg.h + * + * This include file contains all the constants and structures associated + * with the Message queue Handler. + */ + +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_COREMSG_H +#define _RTEMS_SCORE_COREMSG_H + +/** + * @defgroup ScoreMessageQueue Message Queue Handler + * + * This handler encapsulates functionality which provides the foundation + * Message Queue services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#include <limits.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/priority.h> +#include <rtems/score/watchdog.h> + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY +#endif + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION +#endif + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Message Queue MP Callback Prototype + * + * The following type defines the callout which the API provides + * to support global/multiprocessor operations on message_queues. + */ +typedef void ( *CORE_message_queue_API_mp_support_callout )( + Thread_Control *, + Objects_Id + ); + +/** + * @brief Message Buffer Contents Management Structure + * + * The following defines the data types needed to manipulate + * the contents of message buffers. + * + * @note The buffer field is normally longer than a single uint32_t + * but since messages are variable length we just make a ptr to 1. + */ +typedef struct { + /** This field is the size of this message. */ + size_t size; + /** This field contains the actual message. */ + uint32_t buffer[1]; +} CORE_message_queue_Buffer; + +/** + * @brief Message Structure + * + * The following records define the organization of a message + * buffer. + */ +typedef struct { + /** This element allows this structure to be placed on chains. */ + Chain_Node Node; + #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY) + /** This field is the priority of this message. */ + int priority; + #endif + /** This field points to the contents of the message. */ + CORE_message_queue_Buffer Contents; +} CORE_message_queue_Buffer_control; + +/** + * @brief Message Queue Blocking Disciplines + * + * This enumerated types defines the possible blocking disciplines + * for a message queue. + */ +typedef enum { + /** This value indicates that blocking tasks are in FIFO order. */ + CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO, + /** This value indicates that blocking tasks are in priority order. */ + CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY +} CORE_message_queue_Disciplines; + +/** + * @brief Message Priority for Appending + * + * This is the priority constant used when appending messages onto + * a message queue. + */ +#define CORE_MESSAGE_QUEUE_SEND_REQUEST INT_MAX + +/** + * @brief Message Priority for Prepending + * + * This is the priority constant used when prepending messages onto + * a message queue. + */ +#define CORE_MESSAGE_QUEUE_URGENT_REQUEST INT_MIN + +/** + * @brief Message Insertion Operation Types + * + * The following type details the modes in which a message + * may be submitted to a message queue. The message may be posted + * in a send or urgent fashion. + * + * @note All other values are message priorities. Numerically smaller + * priorities indicate higher priority messages. + */ +typedef int CORE_message_queue_Submit_types; + +/** + * @brief Core Message Queue Return Statuses + * + * This enumerated type defines the possible set of Core Message + * Queue handler return statuses. + */ +typedef enum { + /** This value indicates the operation completed sucessfully. */ + CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL, + /** This value indicates that the message was too large for this queue. */ + CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE, + /** This value indicates that there are too many messages pending. */ + CORE_MESSAGE_QUEUE_STATUS_TOO_MANY, + /** This value indicates that a receive was unsuccessful. */ + CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED, + /** This value indicates that a blocking send was unsuccessful. */ + CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT, + /** This value indicates that the message queue being blocked upon + * was deleted while the thread was waiting. + */ + CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED, + /** This value indicates that the thread had to timeout while waiting + * to receive a message because one did not become available. + */ + CORE_MESSAGE_QUEUE_STATUS_TIMEOUT, + /** This value indicates that a blocking receive was unsuccessful. */ + CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT +} CORE_message_queue_Status; + +/** + * @brief Core Message Queue Last Status + * + * This is the last status value. + */ +#define CORE_MESSAGE_QUEUE_STATUS_LAST CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT + +/** + * @brief Message Queue Attributes Type + * + * The following defines the control block used to manage the + * attributes of each message queue. + */ +typedef struct { + /** This field specifies the order in which blocking tasks will be ordered. */ + CORE_message_queue_Disciplines discipline; +} CORE_message_queue_Attributes; + +#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION) + /** + * @brief Message Queue Notification Callback Prototype + * + * The following defines the type for a Notification handler. A + * notification handler is invoked when the message queue makes a + * 0->1 transition on pending messages. + */ + typedef void (*CORE_message_queue_Notify_Handler)( void * ); +#endif + +/** + * @brief Core Message Queue Control Structure + * + * The following defines the control block used to manage each + * Message Queue + */ +typedef struct { + /** This field is the Waiting Queue used to manage the set of tasks + * which are blocked waiting to receive a message from this queue. + */ + Thread_queue_Control Wait_queue; + /** This element is the set of attributes which define this instance's + * behavior. + */ + CORE_message_queue_Attributes Attributes; + /** This element is maximum number of messages which may be pending + * at any given time. + */ + uint32_t maximum_pending_messages; + /** This element is the number of messages which are currently pending. + */ + uint32_t number_of_pending_messages; + /** This is the size in bytes of the largest message which may be + * sent via this queue. + */ + size_t maximum_message_size; + /** This chain is the set of pending messages. It may be ordered by + * message priority or in FIFO order. + */ + Chain_Control Pending_messages; + /** This is the address of the memory allocated for message buffers. + * It is allocated are part of message queue initialization and freed + * as part of destroying it. + */ + CORE_message_queue_Buffer *message_buffers; + #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION) + /** This is the routine invoked when the message queue transitions + * from zero (0) messages pending to one (1) message pending. + */ + CORE_message_queue_Notify_Handler notify_handler; + /** This field is the argument passed to the @ref notify_argument. */ + void *notify_argument; + #endif + /** This chain is the set of inactive messages. A message is inactive + * when it does not contain a pending message. + */ + Chain_Control Inactive_messages; +} CORE_message_queue_Control; + +/** + * @brief Initialize a Message Queue + * + * This routine initializes @a the_message_queue based on the parameters passed. + * + * @param[in] the_message_queue points to the message queue to initialize + * @param[in] the_message_queue_attributes points to the attributes that + * will be used with this message queue instance + * @param[in] maximum_pending_messages is the maximum number of messages + * that will be allowed to pend at any given time + * @param[in] maximum_message_size is the size of largest message that + * may be sent to this message queue instance + * + * @return true if the message queue can be initialized. In general, + * false will only be returned if memory for the pending + * messages cannot be allocated. + */ +bool _CORE_message_queue_Initialize( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Attributes *the_message_queue_attributes, + uint32_t maximum_pending_messages, + size_t maximum_message_size +); + +/** + * @brief Close a Message Queue + * + * This function closes a message by returning all allocated space and + * flushing @a the_message_queue's task wait queue. + * + * @param[in] the_message_queue points to the message queue to close + * @param[in] remote_extract_callout is the routine to call for each thread + * that is extracted from the set of waiting threads + * @param[in] status is the status that each waiting thread will return + * from it's blocking service + */ +void _CORE_message_queue_Close( + CORE_message_queue_Control *the_message_queue, + Thread_queue_Flush_callout remote_extract_callout, + uint32_t status +); + +/** + * @brief Flush Pending Messages + * + * This function flushes @a the_message_queue's pending message queue. The + * number of messages flushed from the queue is returned. + * + * @param[in] the_message_queue points to the message queue to flush + * + * @return This method returns the number of message pending messages flushed. + */ +uint32_t _CORE_message_queue_Flush( + CORE_message_queue_Control *the_message_queue +); + +/** + * @brief Flush Messages Support Routine + * + * This routine flushes all outstanding messages and returns + * them to the inactive message chain. + * + * @param[in] the_message_queue points to the message queue to flush + * + * @return This method returns the number of message pending messages flushed. + */ +uint32_t _CORE_message_queue_Flush_support( + CORE_message_queue_Control *the_message_queue +); + +#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + /** + * @brief Flush Waiting Threads. + * + * This function flushes the threads which are blocked on + * @a the_message_queue's pending message queue. They are + * unblocked whether blocked sending or receiving. + * + * @param[in] the_message_queue points to the message queue to flush + */ + void _CORE_message_queue_Flush_waiting_threads( + CORE_message_queue_Control *the_message_queue + ); +#endif + +/** + * @brief Broadcast a Message to the Message Queue + * + * This function sends a message for every thread waiting on the queue and + * returns the number of threads made ready by the message. + * + * @param[in] the_message_queue points to the message queue + * @param[in] buffer is the starting address of the message to broadcast + * @param[in] size is the size of the message being broadcast + * @param[in] id is the RTEMS object Id associated with this message queue. + * It is used when unblocking a remote thread. + * @param[in] api_message_queue_mp_support is the routine to invoke if + * a thread that is unblocked is actually a remote thread. + * @param[out] count points to the variable that will contain the + * number of tasks that are sent this message + * @return @a *count will contain the number of messages sent + * @return indication of the successful completion or reason for failure + */ +CORE_message_queue_Status _CORE_message_queue_Broadcast( + CORE_message_queue_Control *the_message_queue, + const void *buffer, + size_t size, + Objects_Id id, + CORE_message_queue_API_mp_support_callout api_message_queue_mp_support, + uint32_t *count +); + +/** + * @brief Submit a Message to the Message Queue + * + * This routine implements the send and urgent message functions. It + * processes a message that is to be submitted to the designated + * message queue. The message will either be processed as a + * send message which it will be inserted at the rear of the queue + * or it will be processed as an urgent message which will be inserted + * at the front of the queue. + * + * @param[in] the_message_queue points to the message queue + * @param[in] buffer is the starting address of the message to send + * @param[in] size is the size of the message being send + * @param[in] id is the RTEMS object Id associated with this message queue. + * It is used when unblocking a remote thread. + * @param[in] api_message_queue_mp_support is the routine to invoke if + * a thread that is unblocked is actually a remote thread. + * @param[in] submit_type determines whether the message is prepended, + * appended, or enqueued in priority order. + * @param[in] wait indicates whether the calling thread is willing to block + * if the message queue is full. + * @param[in] timeout is the maximum number of clock ticks that the calling + * thread is willing to block if the message queue is full. + * @return indication of the successful completion or reason for failure + */ +CORE_message_queue_Status _CORE_message_queue_Submit( + CORE_message_queue_Control *the_message_queue, + const void *buffer, + size_t size, + Objects_Id id, + CORE_message_queue_API_mp_support_callout api_message_queue_mp_support, + CORE_message_queue_Submit_types submit_type, + bool wait, + Watchdog_Interval timeout +); + +/** + * @brief Size a Message from the Message Queue + * + * This kernel routine dequeues a message, copies the message buffer to + * a given destination buffer, and frees the message buffer to the + * inactive message pool. The thread will be blocked if wait is true, + * otherwise an error will be given to the thread if no messages are available. + * + * @param[in] the_message_queue points to the message queue + * @param[in] id is the RTEMS object Id associated with this message queue. + * It is used when unblocking a remote thread. + * @param[in] buffer is the starting address of the message buffer to + * to be filled in with a message + * @param[in] size is the size of the @a buffer and indicates the maximum + * size message that the caller can receive. + * @param[in] wait indicates whether the calling thread is willing to block + * if the message queue is empty. + * @param[in] timeout is the maximum number of clock ticks that the calling + * thread is willing to block if the message queue is empty. + * + * @return indication of the successful completion or reason for failure + * @note Returns message priority via return are in TCB. + */ +void _CORE_message_queue_Seize( + CORE_message_queue_Control *the_message_queue, + Objects_Id id, + void *buffer, + size_t *size_p, + bool wait, + Watchdog_Interval timeout +); + +/** + * This kernel routine inserts the specified message into the + * message queue. It is assumed that the message has been filled + * in before this routine is called. + * + * @param[in] the_message_queue points to the message queue + * @param[in] the_message is the message to enqueue + * @param[in] submit_type determines whether the message is prepended, + * appended, or enqueued in priority order. + */ +void _CORE_message_queue_Insert_message( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message, + CORE_message_queue_Submit_types submit_type +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/coremsg.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h new file mode 100644 index 0000000000..084532f36d --- /dev/null +++ b/cpukit/score/include/rtems/score/coremutex.h @@ -0,0 +1,468 @@ +/** + * @file rtems/score/coremutex.h + * + * This include file contains all the constants and structures associated + * with the Mutex Handler. A mutex is an enhanced version of the standard + * Dijkstra binary semaphore used to provide synchronization and mutual + * exclusion capabilities. + */ + +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_COREMUTEX_H +#define _RTEMS_SCORE_COREMUTEX_H + + +/** + * @defgroup ScoreMutex Mutex Handler + * + * This handler encapsulates functionality which provides the foundation + * Mutex services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/priority.h> +#include <rtems/score/watchdog.h> +#include <rtems/score/interr.h> +#include <rtems/score/sysstate.h> + +/** + * @brief MP Support Callback Prototype + * + * The following type defines the callout which the API provides + * to support global/multiprocessor operations on mutexes. + */ +typedef void ( *CORE_mutex_API_mp_support_callout )( + Thread_Control *, + Objects_Id + ); + +/** + * @brief Blocking Disciplines Enumerated Type + * + * This enumerated type defines the blocking disciplines for a mutex. + */ +typedef enum { + /** This specifies that threads will wait for the mutex in FIFO order. */ + CORE_MUTEX_DISCIPLINES_FIFO, + /** This specifies that threads will wait for the mutex in priority order. */ + CORE_MUTEX_DISCIPLINES_PRIORITY, + /** This specifies that threads will wait for the mutex in priority order. + * Additionally, the Priority Inheritance Protocol will be in effect. + */ + CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT, + /** This specifies that threads will wait for the mutex in priority order. + * Additionally, the Priority Ceiling Protocol will be in effect. + */ + CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING +} CORE_mutex_Disciplines; + +/** + * @brief Mutex method return statuses + * + * This enumerated type defines the possible Mutex handler return statuses. + */ +typedef enum { + /** This status indicates that the operation completed successfully. */ + CORE_MUTEX_STATUS_SUCCESSFUL, + /** This status indicates that the calling task did not want to block + * and the operation was unable to complete immediately because the + * resource was unavailable. + */ + CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT, +#if defined(RTEMS_POSIX_API) + /** This status indicates that an attempt was made to relock a mutex + * for which nesting is not configured. + */ + CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED, +#endif + /** This status indicates that an attempt was made to release a mutex + * by a thread other than the thread which locked it. + */ + CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE, + /** This status indicates that the thread was blocked waiting for an + * operation to complete and the mutex was deleted. + */ + CORE_MUTEX_WAS_DELETED, + /** This status indicates that the calling task was willing to block + * but the operation was unable to complete within the time allotted + * because the resource never became available. + */ + CORE_MUTEX_TIMEOUT, + +#if defined(__RTEMS_STRICT_ORDER_MUTEX__) + /** This status indicates that a thread not release the mutex which has + * the priority inheritance property in a right order. + */ + CORE_MUTEX_RELEASE_NOT_ORDER, +#endif + + /** This status indicates that a thread of logically greater importance + * than the ceiling priority attempted to lock this mutex. + */ + CORE_MUTEX_STATUS_CEILING_VIOLATED + +} CORE_mutex_Status; + +/** + * @brief Core Mutex Last Status + * + * This is the last status value. + */ +#define CORE_MUTEX_STATUS_LAST CORE_MUTEX_STATUS_CEILING_VIOLATED + +/** + * @brief Mutex Lock Nesting Behavior Enumeration + * + * This enumerated type defines the possible behaviors for + * lock nesting. + */ +typedef enum { + /** + * This sequence has no blocking or errors: + * + * + lock(m) + * + lock(m) + * + unlock(m) + * + unlock(m) + */ + CORE_MUTEX_NESTING_ACQUIRES, +#if defined(RTEMS_POSIX_API) + /** + * This sequence returns an error at the indicated point: + * + * + lock(m) + * + lock(m) - already locked error + * + unlock(m) + */ + CORE_MUTEX_NESTING_IS_ERROR, +#endif + /** + * This sequence performs as indicated: + * + lock(m) + * + lock(m) - deadlocks or timeouts + * + unlock(m) - releases + */ + CORE_MUTEX_NESTING_BLOCKS +} CORE_mutex_Nesting_behaviors; + +/** + * This is the value of a mutex when it is unlocked. + */ +#define CORE_MUTEX_UNLOCKED 1 + +/** + * This is the value of a mutex when it is locked. + */ +#define CORE_MUTEX_LOCKED 0 + +/** + * @brief Core Mutex Attributes + * + * The following defines the control block used to manage the + * attributes of each mutex. + */ +typedef struct { + /** This field determines what the behavior of this mutex instance will + * be when attempting to acquire the mutex when it is already locked. + */ + CORE_mutex_Nesting_behaviors lock_nesting_behavior; + /** When this field is true, then only the thread that locked the mutex + * is allowed to unlock it. + */ + bool only_owner_release; + /** This field indicates whether threads waiting on the mutex block in + * FIFO or priority order. + */ + CORE_mutex_Disciplines discipline; + /** This field contains the ceiling priority to be used if that protocol + * is selected. + */ + Priority_Control priority_ceiling; +} CORE_mutex_Attributes; + +#ifdef __RTEMS_STRICT_ORDER_MUTEX__ +/*@brief Core Mutex Lock_Chain Struct + * + * The following defines the control block used to manage lock chain of + * priority inheritance mutex. + */ + typedef struct{ + /** This field is a chian of locked mutex by a thread,new mutex will + * be added to the head of queue, and the mutex which will be released + * must be the head of queue. + */ + Chain_Node lock_queue; + /** This field is the priority of thread before locking this mutex + * + */ + Priority_Control priority_before; + } CORE_mutex_order_list; +#endif + +/** + * @brief Core Mutex Control Structure + * + * The following defines the control block used to manage each mutex. + */ +typedef struct { + /** This field is the Waiting Queue used to manage the set of tasks + * which are blocked waiting to lock the mutex. + */ + Thread_queue_Control Wait_queue; + /** This element is the set of attributes which define this instance's + * behavior. + */ + CORE_mutex_Attributes Attributes; + /** This element contains the current state of the mutex. + */ + uint32_t lock; + /** This element contains the number of times the mutex has been acquired + * nested. This must be zero (0) before the mutex is actually unlocked. + */ + uint32_t nest_count; + /** This is the number of waiting threads. */ + uint32_t blocked_count; + /** This element points to the thread which is currently holding this mutex. + * The holder is the last thread to successfully lock the mutex and which + * has not unlocked it. If the thread is not locked, there is no holder. + */ + Thread_Control *holder; + /** This element contains the object Id of the holding thread. */ + Objects_Id holder_id; +#ifdef __RTEMS_STRICT_ORDER_MUTEX__ + /** This field is used to manipulate the priority inheritance mutex queue*/ + CORE_mutex_order_list queue; +#endif + +} CORE_mutex_Control; + +/** + * @brief Initialize a Core Mutex + * + * This routine initializes the mutex based on the parameters passed. + * + * @param[in] the_mutex is the mutex to initalize + * @param[in] the_mutex_attributes is the attributes associated with this + * mutex instance + * @param[in] initial_lock is the initial value of the mutex + * + * @return This method returns CORE_MUTEX_STATUS_SUCCESSFUL if successful. + */ +CORE_mutex_Status _CORE_mutex_Initialize( + CORE_mutex_Control *the_mutex, + CORE_mutex_Attributes *the_mutex_attributes, + uint32_t initial_lock +); + +#ifndef __RTEMS_APPLICATION__ +/** + * @brief Seize Mutex with Quick Success Path + * + * This routine attempts to receive a unit from the_mutex. + * If a unit is available or if the wait flag is false, then the routine + * returns. Otherwise, the calling task is blocked until a unit becomes + * available. + * + * @param[in] the_mutex is the mutex to attempt to lock + * @param[in] level_p is the interrupt level holder + * + * @return This routine returns 0 if "trylock" can resolve whether or not + * the mutex is immediately obtained or there was an error attempting to + * get it. It returns 1 to indicate that the caller cannot obtain + * the mutex and will have to block to do so. + * + * @note For performance reasons, this routine is implemented as + * a macro that uses two support routines. + */ + +RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock_body( + CORE_mutex_Control *the_mutex, + ISR_Level *level_p +); + +#if defined(__RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__) + /** + * When doing test coverage analysis or trying to minimize the code + * space for RTEMS, it is often helpful to not inline this method + * multiple times. It is fairly large and has a high branch complexity + * which makes it harder to get full binary test coverage. + * + * @param[in] the_mutex will attempt to lock + * @param[in] level_p is the interrupt level holder + */ + int _CORE_mutex_Seize_interrupt_trylock( + CORE_mutex_Control *the_mutex, + ISR_Level *level_p + ); +#else + /** + * The default is to favor speed and inlining this definitely saves + * a few instructions. This is very important for mutex performance. + * + * @param[in] _mutex will attempt to lock + * @param[in] _level_p is the interrupt level holder + */ + #define _CORE_mutex_Seize_interrupt_trylock( _mutex, _level_p ) \ + _CORE_mutex_Seize_interrupt_trylock_body( _mutex, _level_p ) +#endif + +/** + * @brief Seize Mutex with Blocking + * + * This routine performs the blocking portion of a mutex obtain. + * It is an actual subroutine and is not implemented as something + * that may be inlined. + * + * @param[in] the_mutex is the mutex to attempt to lock + * @param[in] timeout is the maximum number of ticks to block + */ +void _CORE_mutex_Seize_interrupt_blocking( + CORE_mutex_Control *the_mutex, + Watchdog_Interval timeout +); + +/** + * @brief Sieze Interrupt Wrapper + * + * This routine attempts to obtain the mutex. If the mutex is available, + * then it will return immediately. Otherwise, it will invoke the + * support routine @a _Core_mutex_Seize_interrupt_blocking. + * + * @param[in] _the_mutex is the mutex to attempt to lock + * @param[in] _id is the Id of the owning API level Semaphore object + * @param[in] _wait is true if the thread is willing to wait + * @param[in] _timeout is the maximum number of ticks to block + * @param[in] _level is a temporary variable used to contain the ISR + * disable level cookie + * + * @note If the mutex is called from an interrupt service routine, + * with context switching disabled, or before multitasking, + * then a fatal error is generated. + * + * The logic on this routine is as follows: + * + * * If incorrect system state + * return an error + * * If mutex is available without any contention or blocking + * obtain it with interrupts disabled and returned + * * If the caller is willing to wait + * then they are blocked. + */ + +#define _CORE_mutex_Seize_body( \ + _the_mutex, _id, _wait, _timeout, _level ) \ + do { \ + if ( _Thread_Dispatch_disable_level \ + && (_wait) \ + && (_System_state_Get() >= SYSTEM_STATE_BEGIN_MULTITASKING ) \ + ) { \ + _Internal_error_Occurred( \ + INTERNAL_ERROR_CORE, \ + false, \ + INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE \ + ); \ + } \ + if ( _CORE_mutex_Seize_interrupt_trylock( _the_mutex, &_level ) ) { \ + if ( !_wait ) { \ + _ISR_Enable( _level ); \ + _Thread_Executing->Wait.return_code = \ + CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT; \ + } else { \ + _Thread_queue_Enter_critical_section( &(_the_mutex)->Wait_queue ); \ + _Thread_Executing->Wait.queue = &(_the_mutex)->Wait_queue; \ + _Thread_Executing->Wait.id = _id; \ + _Thread_Disable_dispatch(); \ + _ISR_Enable( _level ); \ + _CORE_mutex_Seize_interrupt_blocking( _the_mutex, _timeout ); \ + } \ + } \ + } while (0) + +/** + * This method is used to obtain a core mutex. + * + * @param[in] _the_mutex is the mutex to attempt to lock + * @param[in] _id is the Id of the owning API level Semaphore object + * @param[in] _wait is true if the thread is willing to wait + * @param[in] _timeout is the maximum number of ticks to block + * @param[in] _level is a temporary variable used to contain the ISR + * disable level cookie + */ +#if defined(__RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__) + void _CORE_mutex_Seize( + CORE_mutex_Control *_the_mutex, + Objects_Id _id, + bool _wait, + Watchdog_Interval _timeout, + ISR_Level _level + ); +#else + #define _CORE_mutex_Seize( _the_mutex, _id, _wait, _timeout, _level ) \ + _CORE_mutex_Seize_body( _the_mutex, _id, _wait, _timeout, _level ) +#endif + +/** + * @brief Surrender the Mutex + * + * This routine frees a unit to the mutex. If a task was blocked waiting for + * a unit from this mutex, then that task will be readied and the unit + * given to that task. Otherwise, the unit will be returned to the mutex. + * + * @param[in] the_mutex is the mutex to surrender + * @param[in] id is the id of the RTEMS Object associated with this mutex + * @param[in] api_mutex_mp_support is the routine that will be called when + * unblocking a remote mutex + * + * @return an indication of whether the routine succeeded or failed + */ +CORE_mutex_Status _CORE_mutex_Surrender( + CORE_mutex_Control *the_mutex, + Objects_Id id, + CORE_mutex_API_mp_support_callout api_mutex_mp_support +); + +/** + * @brief Flush all waiting threads + * + * This routine assists in the deletion of a mutex by flushing the associated + * wait queue. + * + * @param[in] the_mutex is the mutex to flush + * @param[in] remote_extract_callout is the routine to invoke when a remote + * thread is extracted + * @param[in] status is the status value which each unblocked thread will + * return to its caller. + */ +void _CORE_mutex_Flush( + CORE_mutex_Control *the_mutex, + Thread_queue_Flush_callout remote_extract_callout, + uint32_t status +); + +#include <rtems/score/coremutex.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/corerwlock.h b/cpukit/score/include/rtems/score/corerwlock.h new file mode 100644 index 0000000000..f97e4679b8 --- /dev/null +++ b/cpukit/score/include/rtems/score/corerwlock.h @@ -0,0 +1,235 @@ +/** + * @file rtems/score/corerwlock.h + * + * This include file contains all the constants and structures associated + * with the RWLock Handler. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_CORERWLOCK_H +#define _RTEMS_SCORE_CORERWLOCK_H + +/** + * @defgroup ScoreRWLock RWLock Handler + * + * This handler encapsulates functionality which provides the foundation + * RWLock services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/priority.h> +#include <rtems/score/watchdog.h> + +/** + * The following type defines the callout which the API provides + * to support global/multiprocessor operations on RWLocks. + */ +typedef void ( *CORE_RWLock_API_mp_support_callout )( + Thread_Control *, + Objects_Id + ); + +/** + * RWLock State. + */ +typedef enum { + /** This indicates the the RWLock is not currently locked. + */ + CORE_RWLOCK_UNLOCKED, + /** This indicates the the RWLock is currently locked for reading. + */ + CORE_RWLOCK_LOCKED_FOR_READING, + /** This indicates the the RWLock is currently locked for reading. + */ + CORE_RWLOCK_LOCKED_FOR_WRITING +} CORE_RWLock_States; + +/** + * Core RWLock handler return statuses. + */ +typedef enum { + /** This status indicates that the operation completed successfully. */ + CORE_RWLOCK_SUCCESSFUL, + /** This status indicates that the thread was blocked waiting for an */ + CORE_RWLOCK_WAS_DELETED, + /** This status indicates that the rwlock was not immediately available. */ + CORE_RWLOCK_UNAVAILABLE, + /** This status indicates that the calling task was willing to block + * but the operation was unable to complete within the time allotted + * because the resource never became available. + */ + CORE_RWLOCK_TIMEOUT +} CORE_RWLock_Status; + +/** This is the last status value. + */ +#define CORE_RWLOCK_STATUS_LAST CORE_RWLOCK_TIMEOUT + +/** + * This is used to denote that a thread is blocking waiting for + * read-only access to the RWLock. + */ +#define CORE_RWLOCK_THREAD_WAITING_FOR_READ 0 + +/** + * This is used to denote that a thread is blocking waiting for + * write-exclusive access to the RWLock. + */ +#define CORE_RWLOCK_THREAD_WAITING_FOR_WRITE 1 + +/** + * The following defines the control block used to manage the + * attributes of each RWLock. + */ +typedef struct { + /** This field indicates XXX. + */ + int XXX; +} CORE_RWLock_Attributes; + +/** + * The following defines the control block used to manage each + * RWLock. + */ +typedef struct { + /** This field is the Waiting Queue used to manage the set of tasks + * which are blocked waiting for the RWLock to be released. + */ + Thread_queue_Control Wait_queue; + /** This element is the set of attributes which define this instance's + * behavior. + */ + CORE_RWLock_Attributes Attributes; + /** This element is the current state of the RWLock. + */ + CORE_RWLock_States current_state; + /** This element contains the current number of thread waiting for this + * RWLock to be released. */ + uint32_t number_of_readers; +} CORE_RWLock_Control; + +/** + * This routine initializes the RWLock based on the parameters passed. + * + * @param[in] the_rwlock is the RWLock to initialize + * @param[in] the_rwlock_attributes define the behavior of this instance + */ +void _CORE_RWLock_Initialize( + CORE_RWLock_Control *the_rwlock, + CORE_RWLock_Attributes *the_rwlock_attributes +); + +/** + * This routine attempts to obtain the RWLock for read access. + * + * @param[in] the_rwlock is the RWLock to wait for + * @param[in] id is the id of the object being waited upon + * @param[in] wait is true if the calling thread is willing to wait + * @param[in] timeout is the number of ticks the calling thread is willing + * to wait if @a wait is true. + * @param[in] api_rwlock_mp_support is the routine to invoke if the + * thread unblocked is remote + * + * @note Status is returned via the thread control block. + */ +void _CORE_RWLock_Obtain_for_reading( + CORE_RWLock_Control *the_rwlock, + Objects_Id id, + bool wait, + Watchdog_Interval timeout, + CORE_RWLock_API_mp_support_callout api_rwlock_mp_support +); + +/** + * This routine attempts to obtain the RWLock for write exclusive access. + * + * @param[in] the_rwlock is the RWLock to wait for + * @param[in] id is the id of the object being waited upon + * @param[in] wait is true if the calling thread is willing to wait + * @param[in] timeout is the number of ticks the calling thread is willing + * to wait if @a wait is true. + * @param[in] api_rwlock_mp_support is the routine to invoke if the + * thread unblocked is remote + * + * @note Status is returned via the thread control block. + */ +void _CORE_RWLock_Obtain_for_writing( + CORE_RWLock_Control *the_rwlock, + Objects_Id id, + bool wait, + Watchdog_Interval timeout, + CORE_RWLock_API_mp_support_callout api_rwlock_mp_support +); + +/** + * This routine manually releases the RWLock. All of the threads waiting + * for the RWLock will be readied. + * + * @param[in] the_rwlock is the RWLock to surrender + * + * @return Status is returned to indicate successful or failure. + */ +CORE_RWLock_Status _CORE_RWLock_Release( + CORE_RWLock_Control *the_rwlock +); + +/** + * This routine assists in the deletion of a RWLock by flushing the + * associated wait queue. + * + * @param[in] _the_rwlock is the RWLock to flush + * @param[in] _remote_extract_callout is the routine to invoke if the + * thread unblocked is remote + * @param[in] _status is the status to be returned to the unblocked thread + */ +#define _CORE_RWLock_Flush( _the_rwlock, _remote_extract_callout, _status) \ + _Thread_queue_Flush( \ + &((_the_rwlock)->Wait_queue), \ + (_remote_extract_callout), \ + (_status) \ + ) + +/** + * @brief RWLock Specific Thread Queue Timeout + * + * This routine processes a thread which timeouts while waiting on + * an RWLock's thread queue. It is called by the watchdog handler. + * + * @param[in] id is the Id of thread to timeout + * @param[in] ignored is an unused pointer to a caller defined area + */ + +void _CORE_RWLock_Timeout( + Objects_Id id, + void *ignored +); + + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/corerwlock.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/coresem.h b/cpukit/score/include/rtems/score/coresem.h new file mode 100644 index 0000000000..cf89e629d7 --- /dev/null +++ b/cpukit/score/include/rtems/score/coresem.h @@ -0,0 +1,209 @@ +/** + * @file rtems/score/coresem.h + * + * This include file contains all the constants and structures associated + * with the Counting Semaphore Handler. A counting semaphore is the + * standard Dijkstra binary semaphore used to provide synchronization + * and mutual exclusion capabilities. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_CORESEM_H +#define _RTEMS_SCORE_CORESEM_H + +/** + * @defgroup ScoreSemaphore Semaphore Handler + * + * This handler encapsulates functionality which provides the foundation + * Semaphore services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/priority.h> +#include <rtems/score/watchdog.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_CORESEM_ENABLE_SEIZE_BODY +#endif + +/** + * The following type defines the callout which the API provides + * to support global/multiprocessor operations on semaphores. + */ +typedef void ( *CORE_semaphore_API_mp_support_callout )( + Thread_Control *, + Objects_Id + ); + +/** + * Blocking disciplines for a semaphore. + */ +typedef enum { + /** This specifies that threads will wait for the semaphore in FIFO order. */ + CORE_SEMAPHORE_DISCIPLINES_FIFO, + /** This specifies that threads will wait for the semaphore in + * priority order. + */ + CORE_SEMAPHORE_DISCIPLINES_PRIORITY +} CORE_semaphore_Disciplines; + +/** + * Core Semaphore handler return statuses. + */ +typedef enum { + /** This status indicates that the operation completed successfully. */ + CORE_SEMAPHORE_STATUS_SUCCESSFUL, + /** This status indicates that the calling task did not want to block + * and the operation was unable to complete immediately because the + * resource was unavailable. + */ + CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT, + /** This status indicates that the thread was blocked waiting for an + * operation to complete and the semaphore was deleted. + */ + CORE_SEMAPHORE_WAS_DELETED, + /** This status indicates that the calling task was willing to block + * but the operation was unable to complete within the time allotted + * because the resource never became available. + */ + CORE_SEMAPHORE_TIMEOUT, + /** This status indicates that an attempt was made to unlock the semaphore + * and this would have made its count greater than that allowed. + */ + CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED +} CORE_semaphore_Status; + +/** + * @brief Core Semaphore Last Status + * + * This is the last status value. + */ +#define CORE_SEMAPHORE_STATUS_LAST CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED + +/** + * The following defines the control block used to manage the + * attributes of each semaphore. + */ +typedef struct { + /** This element indicates the maximum count this semaphore may have. */ + uint32_t maximum_count; + /** This field indicates whether threads waiting on the semaphore block in + * FIFO or priority order. + */ + CORE_semaphore_Disciplines discipline; +} CORE_semaphore_Attributes; + +/** + * The following defines the control block used to manage each + * counting semaphore. + */ +typedef struct { + /** This field is the Waiting Queue used to manage the set of tasks + * which are blocked waiting to obtain the semaphore. + */ + Thread_queue_Control Wait_queue; + /** This element is the set of attributes which define this instance's + * behavior. + */ + CORE_semaphore_Attributes Attributes; + /** This element contains the current count of this semaphore. */ + uint32_t count; +} CORE_semaphore_Control; + +/** + * This routine initializes the semaphore based on the parameters passed. + * + * @param[in] the_semaphore is the semaphore to initialize + * @param[in] the_semaphore_attributes define the behavior of this instance + * @param[in] initial_value is the initial count of the semaphore + */ +void _CORE_semaphore_Initialize( + CORE_semaphore_Control *the_semaphore, + CORE_semaphore_Attributes *the_semaphore_attributes, + uint32_t initial_value +); + +#if defined(RTEMS_SCORE_CORESEM_ENABLE_SEIZE_BODY) + /** + * This routine attempts to receive a unit from @a the_semaphore. + * If a unit is available or if the wait flag is false, then the routine + * returns. Otherwise, the calling task is blocked until a unit becomes + * available. + * + * @param[in] the_semaphore is the semaphore to seize + * @param[in] id is the Id of the API level Semaphore object associated + * with this instance of a SuperCore Semaphore + * @param[in] wait indicates if the caller is willing to block + * @param[in] timeout is the number of ticks the calling thread is willing + * to wait if @a wait is true. + */ + void _CORE_semaphore_Seize( + CORE_semaphore_Control *the_semaphore, + Objects_Id id, + bool wait, + Watchdog_Interval timeout + ); +#endif + +/** + * This routine frees a unit to the semaphore. If a task was blocked waiting + * for a unit from this semaphore, then that task will be readied and the unit + * given to that task. Otherwise, the unit will be returned to the semaphore. + * + * @param[in] the_semaphore is the semaphore to surrender + * @param[in] id is the Id of the API level Semaphore object associated + * with this instance of a SuperCore Semaphore + * @param[in] api_semaphore_mp_support is the routine to invoke if the + * thread unblocked is remote + * + * @return an indication of whether the routine succeeded or failed + */ +CORE_semaphore_Status _CORE_semaphore_Surrender( + CORE_semaphore_Control *the_semaphore, + Objects_Id id, + CORE_semaphore_API_mp_support_callout api_semaphore_mp_support +); + +/** + * This routine assists in the deletion of a semaphore by flushing the + * associated wait queue. + * + * @param[in] the_semaphore is the semaphore to flush + * @param[in] remote_extract_callout is the routine to invoke if the + * thread unblocked is remote + * @param[in] status is the status to be returned to the unblocked thread + */ +void _CORE_semaphore_Flush( + CORE_semaphore_Control *the_semaphore, + Thread_queue_Flush_callout remote_extract_callout, + uint32_t status +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/coresem.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/corespinlock.h b/cpukit/score/include/rtems/score/corespinlock.h new file mode 100644 index 0000000000..e8ba1fde07 --- /dev/null +++ b/cpukit/score/include/rtems/score/corespinlock.h @@ -0,0 +1,163 @@ +/** + * @file rtems/score/corespinlock.h + * + * This include file contains all the constants and structures associated + * with the Spinlock Handler. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_CORESPINLOCK_H +#define _RTEMS_SCORE_CORESPINLOCK_H + +/** + * @defgroup ScoreSpinlock Spinlock Handler + * + * This handler encapsulates functionality which provides the foundation + * Spinlock services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/thread.h> +#include <rtems/score/priority.h> + +/** + * Core Spinlock handler return statuses. + */ +typedef enum { + /** This status indicates that the operation completed successfully. */ + CORE_SPINLOCK_SUCCESSFUL, + /** This status indicates that the current thread already holds the spinlock. + * An attempt to relock it will result in deadlock. + */ + CORE_SPINLOCK_HOLDER_RELOCKING, + /** This status indicates that the current thread is attempting to unlock a + * spinlock that is held by another thread. + */ + CORE_SPINLOCK_NOT_HOLDER, + /** This status indicates that a thread reached the limit of time it + * was willing to wait on the spin lock. + */ + CORE_SPINLOCK_TIMEOUT, + /** This status indicates that a thread is currently waiting for this + * spin lock. + */ + CORE_SPINLOCK_IS_BUSY, + /** This status indicates that the spinlock is currently locked and thus + * unavailable. + */ + CORE_SPINLOCK_UNAVAILABLE, + /** This status indicates that the spinlock is not currently locked and thus + * should not be released. + */ + CORE_SPINLOCK_NOT_LOCKED +} CORE_spinlock_Status; + +/** This is a shorthand for the last status code. */ +#define CORE_SPINLOCK_STATUS_LAST CORE_SPINLOCK_NOT_LOCKED + +/** This indicates the lock is available. */ +#define CORE_SPINLOCK_UNLOCKED 0 + +/** This indicates the lock is unavailable. */ +#define CORE_SPINLOCK_LOCKED 1 + +/** + * The following defines the control block used to manage the + * attributes of each spinlock. + */ +typedef struct { + /** This element indicates XXX + */ + uint32_t XXX; +} CORE_spinlock_Attributes; + +/** + * The following defines the control block used to manage each + * spinlock. + */ +typedef struct { + /** XXX may not be needed */ + CORE_spinlock_Attributes Attributes; + + /** This field is the lock. + */ + volatile uint32_t lock; + + /** This field is a count of the current number of threads using + * this spinlock. It includes the thread holding the lock as well + * as those waiting. + */ + volatile uint32_t users; + + /** This field is the Id of the thread holding the lock. It may or may + * not be the thread which acquired it. + */ + volatile Objects_Id holder; +} CORE_spinlock_Control; + +/** + * This routine initializes the spinlock based on the parameters passed. + * + * @param[in] the_spinlock is the spinlock to initialize + * @param[in] the_spinlock_attributes define the behavior of this instance + */ +void _CORE_spinlock_Initialize( + CORE_spinlock_Control *the_spinlock, + CORE_spinlock_Attributes *the_spinlock_attributes +); + +/** + * This routine wait for the spinlock to be released. If the spinlock + * is set to automatic and this is the appropriate thread, then it returns + * immediately. Otherwise, the calling thread is blocked until the spinlock + * is released. + * + * @param[in] the_spinlock is the spinlock to wait for + * @param[in] wait is true if willing to wait + * @param[in] timeout is the maximum number of ticks to spin (0 is forever) + * + * @return A status is returned which indicates the success or failure of + * this operation. + */ +CORE_spinlock_Status _CORE_spinlock_Wait( + CORE_spinlock_Control *the_spinlock, + bool wait, + Watchdog_Interval timeout +); + +/** + * This routine manually releases the spinlock. All of the threads waiting + * for the spinlock will be readied. + * + * @param[in] the_spinlock is the spinlock to surrender + */ +CORE_spinlock_Status _CORE_spinlock_Release( + CORE_spinlock_Control *the_spinlock +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/corespinlock.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/heap.h b/cpukit/score/include/rtems/score/heap.h new file mode 100644 index 0000000000..6eee1c745b --- /dev/null +++ b/cpukit/score/include/rtems/score/heap.h @@ -0,0 +1,662 @@ +/** + * @file + * + * @ingroup ScoreHeap + * + * @brief Heap Handler API. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_HEAP_H +#define _RTEMS_SCORE_HEAP_H + +#include <rtems/system.h> +#include <rtems/score/thread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef RTEMS_DEBUG + #define HEAP_PROTECTION +#endif + +/** + * @defgroup ScoreHeap Heap Handler + * + * @ingroup Score + * + * @brief The Heap Handler provides a heap. + * + * A heap is a doubly linked list of variable size blocks which are allocated + * using the first fit method. Garbage collection is performed each time a + * block is returned to the heap by coalescing neighbor blocks. Control + * information for both allocated and free blocks is contained in the heap + * area. A heap control structure contains control information for the heap. + * + * The alignment routines could be made faster should we require only powers of + * two to be supported for page size, alignment and boundary arguments. The + * minimum alignment requirement for pages is currently CPU_ALIGNMENT and this + * value is only required to be multiple of two and explicitly not required to + * be a power of two. + * + * There are two kinds of blocks. One sort describes a free block from which + * we can allocate memory. The other blocks are used and provide an allocated + * memory area. The free blocks are accessible via a list of free blocks. + * + * Blocks or areas cover a continuous set of memory addresses. They have a + * begin and end address. The end address is not part of the set. The size of + * a block or area equals the distance between the begin and end address in + * units of bytes. + * + * Free blocks look like: + * <table> + * <tr> + * <td rowspan=4>@ref Heap_Block</td><td>previous block size in case the + * previous block is free, <br> otherwise it may contain data used by + * the previous block</td> + * </tr> + * <tr> + * <td>block size and a flag which indicates if the previous block is free + * or used, <br> this field contains always valid data regardless of the + * block usage</td> + * </tr> + * <tr><td>pointer to next block (this field is page size aligned)</td></tr> + * <tr><td>pointer to previous block</td></tr> + * <tr><td colspan=2>free space</td></tr> + * </table> + * + * Used blocks look like: + * <table> + * <tr> + * <td rowspan=4>@ref Heap_Block</td><td>previous block size in case the + * previous block is free,<br>otherwise it may contain data used by + * the previous block</td> + * </tr> + * <tr> + * <td>block size and a flag which indicates if the previous block is free + * or used, <br> this field contains always valid data regardless of the + * block usage</td> + * </tr> + * <tr><td>begin of allocated area (this field is page size aligned)</td></tr> + * <tr><td>allocated space</td></tr> + * <tr><td colspan=2>allocated space</td></tr> + * </table> + * + * The heap area after initialization contains two blocks and looks like: + * <table> + * <tr><th>Label</th><th colspan=2>Content</th></tr> + * <tr><td>heap->area_begin</td><td colspan=2>heap area begin address</td></tr> + * <tr> + * <td>first_block->prev_size</td> + * <td colspan=2> + * subordinate heap area end address (this will be used to maintain a + * linked list of scattered heap areas) + * </td> + * </tr> + * <tr> + * <td>first_block->size</td> + * <td colspan=2>size available for allocation + * | @c HEAP_PREV_BLOCK_USED</td> + * </tr> + * <tr> + * <td>first_block->next</td><td>_Heap_Free_list_tail(heap)</td> + * <td rowspan=3>memory area available for allocation</td> + * </tr> + * <tr><td>first_block->prev</td><td>_Heap_Free_list_head(heap)</td></tr> + * <tr><td>...</td></tr> + * <tr> + * <td>last_block->prev_size</td><td colspan=2>size of first block</td> + * </tr> + * <tr> + * <td>last_block->size</td> + * <td colspan=2>first block begin address - last block begin address</td> + * </tr> + * <tr><td>heap->area_end</td><td colspan=2>heap area end address</td></tr> + * </table> + * The next block of the last block is the first block. Since the first + * block indicates that the previous block is used, this ensures that the + * last block appears as used for the _Heap_Is_used() and _Heap_Is_free() + * functions. + * + * @{ + */ + +typedef struct Heap_Control Heap_Control; + +typedef struct Heap_Block Heap_Block; + +#ifndef HEAP_PROTECTION + #define HEAP_PROTECTION_HEADER_SIZE 0 +#else + #define HEAP_PROTECTOR_COUNT 2 + + #define HEAP_BEGIN_PROTECTOR_0 ((uintptr_t) 0xfd75a98f) + #define HEAP_BEGIN_PROTECTOR_1 ((uintptr_t) 0xbfa1f177) + #define HEAP_END_PROTECTOR_0 ((uintptr_t) 0xd6b8855e) + #define HEAP_END_PROTECTOR_1 ((uintptr_t) 0x13a44a5b) + + #define HEAP_FREE_PATTERN ((uintptr_t) 0xe7093cdf) + + #define HEAP_PROTECTION_OBOLUS ((Heap_Block *) 1) + + typedef void (*_Heap_Protection_handler)( + Heap_Control *heap, + Heap_Block *block + ); + + typedef struct { + _Heap_Protection_handler block_initialize; + _Heap_Protection_handler block_check; + _Heap_Protection_handler block_error; + void *handler_data; + Heap_Block *first_delayed_free_block; + Heap_Block *last_delayed_free_block; + uintptr_t delayed_free_block_count; + } Heap_Protection; + + typedef struct { + uintptr_t protector [HEAP_PROTECTOR_COUNT]; + Heap_Block *next_delayed_free_block; + Thread_Control *task; + void *tag; + } Heap_Protection_block_begin; + + typedef struct { + uintptr_t protector [HEAP_PROTECTOR_COUNT]; + } Heap_Protection_block_end; + + #define HEAP_PROTECTION_HEADER_SIZE \ + (sizeof(Heap_Protection_block_begin) + sizeof(Heap_Protection_block_end)) +#endif + +/** + * @brief See also @ref Heap_Block.size_and_flag. + */ +#define HEAP_PREV_BLOCK_USED ((uintptr_t) 1) + +/** + * @brief Size of the part at the block begin which may be used for allocation + * in charge of the previous block. + */ +#define HEAP_ALLOC_BONUS sizeof(uintptr_t) + +/** + * @brief The block header consists of the two size fields + * (@ref Heap_Block.prev_size and @ref Heap_Block.size_and_flag). + */ +#define HEAP_BLOCK_HEADER_SIZE \ + (2 * sizeof(uintptr_t) + HEAP_PROTECTION_HEADER_SIZE) + +/** + * @brief Description for free or used blocks. + */ +struct Heap_Block { + /** + * @brief Size of the previous block or part of the allocated area of the + * previous block. + * + * This field is only valid if the previous block is free. This case is + * indicated by a cleared @c HEAP_PREV_BLOCK_USED flag in the + * @a size_and_flag field of the current block. + * + * In a used block only the @a size_and_flag field needs to be valid. The + * @a prev_size field of the current block is maintained by the previous + * block. The current block can use the @a prev_size field in the next block + * for allocation. + */ + uintptr_t prev_size; + + #ifdef HEAP_PROTECTION + Heap_Protection_block_begin Protection_begin; + #endif + + /** + * @brief Contains the size of the current block and a flag which indicates + * if the previous block is free or used. + * + * If the flag @c HEAP_PREV_BLOCK_USED is set, then the previous block is + * used, otherwise the previous block is free. A used previous block may + * claim the @a prev_size field for allocation. This trick allows to + * decrease the overhead in the used blocks by the size of the @a prev_size + * field. As sizes are required to be multiples of two, the least + * significant bits would be always zero. We use this bit to store the flag. + * + * This field is always valid. + */ + uintptr_t size_and_flag; + + #ifdef HEAP_PROTECTION + Heap_Protection_block_end Protection_end; + #endif + + /** + * @brief Pointer to the next free block or part of the allocated area. + * + * This field is page size aligned and begins of the allocated area in case + * the block is used. + * + * This field is only valid if the block is free and thus part of the free + * block list. + */ + Heap_Block *next; + + /** + * @brief Pointer to the previous free block or part of the allocated area. + * + * This field is only valid if the block is free and thus part of the free + * block list. + */ + Heap_Block *prev; +}; + +/** + * @brief Run-time heap statistics. + * + * The value @a searches / @a allocs gives the mean number of searches per + * allocation, while @a max_search gives maximum number of searches ever + * performed on a single allocation call. + */ +typedef struct { + /** + * @brief Instance number of this heap. + */ + uint32_t instance; + + /** + * @brief Size of the allocatable area in bytes. + * + * This value is an integral multiple of the page size. + */ + uintptr_t size; + + /** + * @brief Current free size in bytes. + * + * This value is an integral multiple of the page size. + */ + uintptr_t free_size; + + /** + * @brief Minimum free size ever in bytes. + * + * This value is an integral multiple of the page size. + */ + uintptr_t min_free_size; + + /** + * @brief Current number of free blocks. + */ + uint32_t free_blocks; + + /** + * @brief Maximum number of free blocks ever. + */ + uint32_t max_free_blocks; + + /** + * @brief Current number of used blocks. + */ + uint32_t used_blocks; + + /** + * @brief Maximum number of blocks searched ever. + */ + uint32_t max_search; + + /** + * @brief Total number of successful allocations. + */ + uint32_t allocs; + + /** + * @brief Total number of searches ever. + */ + uint32_t searches; + + /** + * @brief Total number of suceessful calls to free. + */ + uint32_t frees; + + /** + * @brief Total number of successful resizes. + */ + uint32_t resizes; +} Heap_Statistics; + +/** + * @brief Control block used to manage a heap. + */ +struct Heap_Control { + Heap_Block free_list; + uintptr_t page_size; + uintptr_t min_block_size; + uintptr_t area_begin; + uintptr_t area_end; + Heap_Block *first_block; + Heap_Block *last_block; + Heap_Statistics stats; + #ifdef HEAP_PROTECTION + Heap_Protection Protection; + #endif +}; + +/** + * @brief Information about blocks. + */ +typedef struct { + /** + * @brief Number of blocks of this type. + */ + uint32_t number; + + /** + * @brief Largest block of this type. + */ + uint32_t largest; + + /** + * @brief Total size of the blocks of this type. + */ + uint32_t total; +} Heap_Information; + +/** + * @brief Information block returned by _Heap_Get_information(). + */ +typedef struct { + Heap_Information Free; + Heap_Information Used; +} Heap_Information_block; + +/** + * @brief See _Heap_Resize_block(). + */ +typedef enum { + HEAP_RESIZE_SUCCESSFUL, + HEAP_RESIZE_UNSATISFIED, + HEAP_RESIZE_FATAL_ERROR +} Heap_Resize_status; + +/** + * @brief Gets the first and last block for the heap area with begin + * @a heap_area_begin and size @a heap_area_size. + * + * A page size of @a page_size and minimal block size of @a min_block_size will + * be used for calculation. + * + * Nothing will be written to this area. + * + * In case of success the pointers to the first and last block will be returned + * via @a first_block_ptr and @a last_block_ptr. + * + * Returns @c true if the area is big enough, and @c false otherwise. + */ +bool _Heap_Get_first_and_last_block( + uintptr_t heap_area_begin, + uintptr_t heap_area_size, + uintptr_t page_size, + uintptr_t min_block_size, + Heap_Block **first_block_ptr, + Heap_Block **last_block_ptr +); + +/** + * @brief Initializes the heap control block @a heap to manage the area + * starting at @a area_begin of size @a area_size bytes. + * + * Blocks of memory are allocated from the heap in multiples of @a page_size + * byte units. If the @a page_size is equal to zero or is not multiple of + * @c CPU_ALIGNMENT, it is aligned up to the nearest @c CPU_ALIGNMENT boundary. + * + * Returns the maximum memory available, or zero in case of failure. + */ +uintptr_t _Heap_Initialize( + Heap_Control *heap, + void *area_begin, + uintptr_t area_size, + uintptr_t page_size +); + +/** + * @brief Extends the memory available for the heap @a heap using the memory + * area starting at @a area_begin of size @a area_size bytes. + * + * The extended space available for allocation will be returned in + * @a amount_extended. This pointer may be @c NULL. + * + * There are no alignment requirements. The memory area must be big enough to + * contain some maintainance blocks. It must not overlap parts of the current + * heap areas. Disconnected subordinate heap areas will lead to used blocks + * which cover the gaps. Extending with an inappropriate memory area will + * corrupt the heap. + * + * Returns @c true in case of success, and @c false otherwise. + */ +bool _Heap_Extend( + Heap_Control *heap, + void *area_begin, + uintptr_t area_size, + uintptr_t *amount_extended +); + +/** + * @brief Allocates a memory area of size @a size bytes from the heap @a heap. + * + * If the alignment parameter @a alignment is not equal to zero, the allocated + * memory area will begin at an address aligned by this value. + * + * If the boundary parameter @a boundary is not equal to zero, the allocated + * memory area will fulfill a boundary constraint. The boundary value + * specifies the set of addresses which are aligned by the boundary value. The + * interior of the allocated memory area will not contain an element of this + * set. The begin or end address of the area may be a member of the set. + * + * A size value of zero will return a unique address which may be freed with + * _Heap_Free(). + * + * Returns a pointer to the begin of the allocated memory area, or @c NULL if + * no memory is available or the parameters are inconsistent. + */ +void *_Heap_Allocate_aligned_with_boundary( + Heap_Control *heap, + uintptr_t size, + uintptr_t alignment, + uintptr_t boundary +); + +/** + * @brief See _Heap_Allocate_aligned_with_boundary() with boundary equals zero. + */ +RTEMS_INLINE_ROUTINE void *_Heap_Allocate_aligned( + Heap_Control *heap, + uintptr_t size, + uintptr_t alignment +) +{ + return _Heap_Allocate_aligned_with_boundary( heap, size, alignment, 0 ); +} + +/** + * @brief See _Heap_Allocate_aligned_with_boundary() with alignment and + * boundary equals zero. + */ +RTEMS_INLINE_ROUTINE void *_Heap_Allocate( Heap_Control *heap, uintptr_t size ) +{ + return _Heap_Allocate_aligned_with_boundary( heap, size, 0, 0 ); +} + +/** + * @brief Frees the allocated memory area starting at @a addr in the heap + * @a heap. + * + * Inappropriate values for @a addr may corrupt the heap. + * + * Returns @c true in case of success, and @c false otherwise. + */ +bool _Heap_Free( Heap_Control *heap, void *addr ); + +/** + * @brief Walks the heap @a heap to verify its integrity. + * + * If @a dump is @c true, then diagnostic messages will be printed to standard + * output. In this case @a source is used to mark the output lines. + * + * Returns @c true if no errors occured, and @c false if the heap is corrupt. + */ +bool _Heap_Walk( + Heap_Control *heap, + int source, + bool dump +); + +/** + * @brief Returns information about used and free blocks for the heap @a heap + * in @a info. + */ +void _Heap_Get_information( + Heap_Control *heap, + Heap_Information_block *info +); + +/** + * @brief Returns information about free blocks for the heap @a heap in + * @a info. + */ +void _Heap_Get_free_information( + Heap_Control *heap, + Heap_Information *info +); + +/** + * @brief Returns the size of the allocatable memory area starting at @a addr + * in @a size. + * + * The size value may be greater than the initially requested size in + * _Heap_Allocate_aligned_with_boundary(). + * + * Inappropriate values for @a addr will not corrupt the heap, but may yield + * invalid size values. + * + * Returns @a true if successful, and @c false otherwise. + */ +bool _Heap_Size_of_alloc_area( + Heap_Control *heap, + void *addr, + uintptr_t *size +); + +/** + * @brief Resizes the block of the allocated memory area starting at @a addr. + * + * The new memory area will have a size of at least @a size bytes. A resize + * may be impossible and depends on the current heap usage. + * + * The size available for allocation in the current block before the resize + * will be returned in @a old_size. The size available for allocation in + * the resized block will be returned in @a new_size. If the resize was not + * successful, then a value of zero will be returned in @a new_size. + * + * Inappropriate values for @a addr may corrupt the heap. + */ +Heap_Resize_status _Heap_Resize_block( + Heap_Control *heap, + void *addr, + uintptr_t size, + uintptr_t *old_size, + uintptr_t *new_size +); + +#if !defined(__RTEMS_APPLICATION__) + +#include <rtems/score/heap.inl> + +/** + * @brief Allocates the memory area starting at @a alloc_begin of size + * @a alloc_size bytes in the block @a block. + * + * The block may be split up into multiple blocks. The previous and next block + * may be used or free. Free block parts which form a vaild new block will be + * inserted into the free list or merged with an adjacent free block. If the + * block is used, they will be inserted after the free list head. If the block + * is free, they will be inserted after the previous block in the free list. + * + * Inappropriate values for @a alloc_begin or @a alloc_size may corrupt the + * heap. + * + * Returns the block containing the allocated memory area. + */ +Heap_Block *_Heap_Block_allocate( + Heap_Control *heap, + Heap_Block *block, + uintptr_t alloc_begin, + uintptr_t alloc_size +); + +#ifndef HEAP_PROTECTION + #define _Heap_Protection_block_initialize( heap, block ) ((void) 0) + #define _Heap_Protection_block_check( heap, block ) ((void) 0) + #define _Heap_Protection_block_error( heap, block ) ((void) 0) +#else + static inline void _Heap_Protection_block_initialize( + Heap_Control *heap, + Heap_Block *block + ) + { + (*heap->Protection.block_initialize)( heap, block ); + } + + static inline void _Heap_Protection_block_check( + Heap_Control *heap, + Heap_Block *block + ) + { + (*heap->Protection.block_check)( heap, block ); + } + + static inline void _Heap_Protection_block_error( + Heap_Control *heap, + Heap_Block *block + ) + { + (*heap->Protection.block_error)( heap, block ); + } +#endif + +/** @} */ + +#ifdef RTEMS_DEBUG + #define RTEMS_HEAP_DEBUG +#endif + +#ifdef RTEMS_HEAP_DEBUG + #include <assert.h> + #define _HAssert( cond ) \ + do { \ + if ( !(cond) ) { \ + __assert( __FILE__, __LINE__, #cond ); \ + } \ + } while (0) +#else + #define _HAssert( cond ) ((void) 0) +#endif + +#endif /* !defined(__RTEMS_APPLICATION__) */ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h new file mode 100644 index 0000000000..b98eba8d7a --- /dev/null +++ b/cpukit/score/include/rtems/score/interr.h @@ -0,0 +1,115 @@ +/** + * @file rtems/score/interr.h + * + * This include file contains constants and prototypes related + * to the Internal Error Handler. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_INTERR_H +#define _RTEMS_SCORE_INTERR_H + +#include <stdbool.h> +#include <stdint.h> + +#include <rtems/system.h> + +/** + * @defgroup ScoreIntErr Internal Error Handler + * + * This handler encapsulates functionality which provides the foundation + * Semaphore services used in all of the APIs supported by RTEMS. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This type lists the possible sources from which an error + * can be reported. + */ +typedef enum { + INTERNAL_ERROR_CORE, + INTERNAL_ERROR_RTEMS_API, + INTERNAL_ERROR_POSIX_API +} Internal_errors_Source; + +/** + * A list of errors which are generated internally by the executive core. + */ +typedef enum { + INTERNAL_ERROR_NO_CONFIGURATION_TABLE, + INTERNAL_ERROR_NO_CPU_TABLE, + INTERNAL_ERROR_TOO_LITTLE_WORKSPACE, + INTERNAL_ERROR_WORKSPACE_ALLOCATION, + INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL, + INTERNAL_ERROR_THREAD_EXITTED, + INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION, + INTERNAL_ERROR_INVALID_NODE, + INTERNAL_ERROR_NO_MPCI, + INTERNAL_ERROR_BAD_PACKET, + INTERNAL_ERROR_OUT_OF_PACKETS, + INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS, + INTERNAL_ERROR_OUT_OF_PROXIES, + INTERNAL_ERROR_INVALID_GLOBAL_ID, + INTERNAL_ERROR_BAD_STACK_HOOK, + INTERNAL_ERROR_BAD_ATTRIBUTES, + INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY, + INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL, + INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE, + INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0, + INTERNAL_ERROR_SHUTDOWN_WHEN_NOT_UP, + INTERNAL_ERROR_GXX_KEY_ADD_FAILED, + INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED +} Internal_errors_Core_list; + +typedef uint32_t Internal_errors_t; + +/** + * This type holds the fatal error information. + */ +typedef struct { + /** This is the source of the error. */ + Internal_errors_Source the_source; + /** This indicates if the error is internal of external. */ + bool is_internal; + /** This is the error code. */ + Internal_errors_t the_error; +} Internal_errors_Information; + +/** + * When a fatal error occurs, the error information is stored here. + */ +SCORE_EXTERN Internal_errors_Information _Internal_errors_What_happened; + +/** @brief Internal error Occurred + * + * This routine is invoked when the application or the executive itself + * determines that a fatal error has occurred. + */ +void _Internal_error_Occurred( + Internal_errors_Source the_source, + bool is_internal, + Internal_errors_t the_error +) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE; + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/isr.h b/cpukit/score/include/rtems/score/isr.h new file mode 100644 index 0000000000..3da25859ec --- /dev/null +++ b/cpukit/score/include/rtems/score/isr.h @@ -0,0 +1,212 @@ +/** + * @file rtems/score/isr.h + * + * This include file contains all the constants and structures associated + * with the management of processor interrupt levels. This handler + * supports interrupt critical sections, vectoring of user interrupt + * handlers, nesting of interrupts, and manipulating interrupt levels. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_ISR_H +#define _RTEMS_SCORE_ISR_H + +#include <rtems/score/percpu.h> + +/** + * @defgroup ScoreISR ISR Handler + * + * This handler encapsulates functionality which provides the foundation + * ISR services used in all of the APIs supported by RTEMS. + * + * The ISR Nest level counter variable is maintained as part of the + * per cpu data structure. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The following type defines the control block used to manage + * the interrupt level portion of the status register. + */ +typedef uint32_t ISR_Level; + +/** + * The following type defines the type used to manage the vectors. + */ +typedef uint32_t ISR_Vector_number; + +/** + * Return type for ISR Handler + */ +typedef void ISR_Handler; + +/** + * Pointer to an ISR Handler + */ +#if (CPU_ISR_PASSES_FRAME_POINTER == 1) +typedef ISR_Handler ( *ISR_Handler_entry )( + ISR_Vector_number, + CPU_Interrupt_frame * + ); +#else +typedef ISR_Handler ( *ISR_Handler_entry )( + ISR_Vector_number + ); +#endif + +/** + * This constant promotes out the number of vectors truly supported by + * the current CPU being used. This is usually the number of distinct vectors + * the cpu can vector. + */ +#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS + +/** + * This constant promotes out the highest valid interrupt vector number. + */ +#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER + +#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE) +/** + * The following declares the Vector Table. Application + * interrupt service routines are vectored by the ISR Handler via this table. + */ +SCORE_EXTERN ISR_Handler_entry *_ISR_Vector_table; +#endif + +/** + * This routine performs the initialization necessary for this handler. + */ +void _ISR_Handler_initialization ( void ); + +/** + * This routine disables all interrupts so that a critical section + * of code can be executing without being interrupted. Upon return, + * the argument _level will contain the previous interrupt mask level. + */ +#define _ISR_Disable( _level ) \ + do { \ + _CPU_ISR_Disable( _level ); \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + } while (0) + +/** + * This routine enables interrupts to the previous interrupt mask + * LEVEL. It is used at the end of a critical section of code to + * enable interrupts so they can be processed again. + */ +#define _ISR_Enable( _level ) \ + do { \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + _CPU_ISR_Enable( _level ); \ + } while (0) + +/** + * This routine temporarily enables interrupts to the previous + * interrupt mask level and then disables all interrupts so that + * the caller can continue into the second part of a critical + * section. This routine is used to temporarily enable interrupts + * during a long critical section. It is used in long sections of + * critical code when a point is reached at which interrupts can + * be temporarily enabled. Deciding where to flash interrupts + * in a long critical section is often difficult and the point + * must be selected with care to ensure that the critical section + * properly protects itself. + */ +#define _ISR_Flash( _level ) \ + do { \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + _CPU_ISR_Flash( _level ); \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + } while (0) + +/** + * This routine installs new_handler as the interrupt service routine + * for the specified vector. The previous interrupt service routine is + * returned as old_handler. + */ +#define _ISR_Install_vector( _vector, _new_handler, _old_handler ) \ + _CPU_ISR_install_vector( _vector, _new_handler, _old_handler ) + +/** + * This routine returns the current interrupt level. + */ +#define _ISR_Get_level() \ + _CPU_ISR_Get_level() + +/** + * This routine sets the current interrupt level to that specified + * by new_level. The new interrupt level is effective when the + * routine exits. + */ +#define _ISR_Set_level( _new_level ) \ + do { \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + _CPU_ISR_Set_level( _new_level ); \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + } while (0) + + +/** + * This routine is the interrupt dispatcher. ALL interrupts + * are vectored to this routine so that minimal context can be saved + * and setup performed before the application's high-level language + * interrupt service routine is invoked. After the application's + * interrupt service routine returns control to this routine, it + * will determine if a thread dispatch is necessary. If so, it will + * ensure that the necessary thread scheduling operations are + * performed when the outermost interrupt service routine exits. + * + * @note Implemented in assembly language. + */ +void _ISR_Handler( void ); + +/** + * This routine provides a wrapper so that the routine + * @ref _Thread_Dispatch can be invoked when a reschedule is necessary + * at the end of the outermost interrupt service routine. This + * wrapper is necessary to establish the processor context needed + * by _Thread_Dispatch and to save the processor context which is + * corrupted by _Thread_Dispatch. This context typically consists + * of registers which are not preserved across routine invocations. + * + * @note Implemented in assembly language. + */ +void _ISR_Dispatch( void ); + +/** + * This function returns true if the processor is currently servicing + * and interrupt and false otherwise. A return value of true indicates + * that the caller is an interrupt service routine, NOT a thread. The + */ +#if (CPU_PROVIDES_ISR_IS_IN_PROGRESS == TRUE) +bool _ISR_Is_in_progress( void ); +#else +#define _ISR_Is_in_progress() \ + (_ISR_Nest_level != 0) +#endif + +#include <rtems/score/isr.inl> + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/mpci.h b/cpukit/score/include/rtems/score/mpci.h new file mode 100644 index 0000000000..f763ed89a8 --- /dev/null +++ b/cpukit/score/include/rtems/score/mpci.h @@ -0,0 +1,404 @@ +/** + * @file rtems/score/mpci.h + * + * This include file contains all the constants and structures associated + * with the MPCI layer. It provides mechanisms to utilize packets. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_MPCI_H +#define _RTEMS_SCORE_MPCI_H + +/** + * @defgroup ScoreMPCI MPCI Handler + * + * The MPCI Handler encapsulates functionality which is related to the + * generation, receipt, and processing of remote operations in a + * multiprocessor system. This handler contains the message passing + * support for making remote service calls as well as the server thread + * which processes requests from remote nodes. +*/ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/mppkt.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/watchdog.h> + +/** + * The following defines the node number used when a broadcast is desired. + */ +#define MPCI_ALL_NODES 0 + +/** + * For packets associated with requests that don't already have a timeout, + * use the one specified by this MPCI driver. The value specified by + * the MPCI driver sets an upper limit on how long a remote request + * should take to complete. + */ +#define MPCI_DEFAULT_TIMEOUT 0xFFFFFFFF + +/** + * This type is returned by all user provided MPCI routines. + */ +typedef void MPCI_Entry; + +/** + * This type defines the prototype for the initization entry point + * in an Multiprocessor Communications Interface. + */ +typedef MPCI_Entry ( *MPCI_initialization_entry )( void ); + +/** + * This type defines the prototype for the get packet entry point + * in an Multiprocessor Communications Interface. The single + * parameter will point to the packet allocated. + */ +typedef MPCI_Entry ( *MPCI_get_packet_entry )( + MP_packet_Prefix ** + ); + +/** + * This type defines the prototype for the return packet entry point + * in an Multiprocessor Communications Interface. The single + * parameter will point to a packet previously allocated by the + * get packet MPCI entry. + */ +typedef MPCI_Entry ( *MPCI_return_packet_entry )( + MP_packet_Prefix * + ); + +/** + * This type defines the prototype for send get packet entry point + * in an Multiprocessor Communications Interface. The single + * parameter will point to a packet previously allocated by the + * get packet entry point that has been filled in by the caller. + */ +typedef MPCI_Entry ( *MPCI_send_entry )( + uint32_t, + MP_packet_Prefix * + ); + +/** + * This type defines the prototype for the receive packet entry point + * in an Multiprocessor Communications Interface. The single + * parameter will point to a packet allocated and filled in by the + * receive packet handler. The caller will block until a packet is + * received. + */ +typedef MPCI_Entry ( *MPCI_receive_entry )( + MP_packet_Prefix ** + ); + +/** + * This type defines the Multiprocessor Communications + * Interface (MPCI) Table. This table defines the user-provided + * MPCI which is a required part of a multiprocessor system. + * + * For non-blocking local operations that become remote operations, + * we need a timeout. This is a per-driver timeout: default_timeout + */ +typedef struct { + /** This fields contains the timeout for MPCI operations in ticks. */ + uint32_t default_timeout; + /** This field contains the maximum size of a packet supported by this + * MPCI layer. This size places a limit on the size of a message + * which can be transmitted over this interface. + **/ + size_t maximum_packet_size; + /** This field points to the MPCI initialization entry point. */ + MPCI_initialization_entry initialization; + /** This field points to the MPCI get packet entry point. */ + MPCI_get_packet_entry get_packet; + /** This field points to the MPCI return packet entry point. */ + MPCI_return_packet_entry return_packet; + /** This field points to the MPCI send packet entry point. */ + MPCI_send_entry send_packet; + /** This field points to the MPCI receive packet entry point. */ + MPCI_receive_entry receive_packet; +} MPCI_Control; + +/** + * The following defines the type for packet processing routines + * invoked by the MPCI Receive server. + */ +typedef void (*MPCI_Packet_processor)( MP_packet_Prefix * ); + +/** + * The following enumerated type defines the list of + * internal MP operations. + */ +typedef enum { + MPCI_PACKETS_SYSTEM_VERIFY = 0 +} MPCI_Internal_Remote_operations; + +/** + * The following data structure defines the packet used to perform + * remote event operations. + */ +typedef struct { + /** This field is the general header for all packets. */ + MP_packet_Prefix Prefix; + /** This value specifies the operation. */ + MPCI_Internal_Remote_operations operation; + /** This is the maximum number of nodes in the system. It must agree + * on all nodes. + */ + uint32_t maximum_nodes; + /** This field is the maximum number of concurrently existent + * globally offered objects. + */ + uint32_t maximum_global_objects; +} MPCI_Internal_packet; + +/** + * The following thread queue is used to maintain a list of tasks + * which currently have outstanding remote requests. + */ +SCORE_EXTERN Thread_queue_Control _MPCI_Remote_blocked_threads; + +/** + * The following define the internal pointers to the user's + * configuration information. + */ +SCORE_EXTERN MPCI_Control *_MPCI_table; + +/** @brief Pointer to MP Thread Control Block + * + * The following is used to determine when the multiprocessing receive + * thread is executing so that a proxy can be allocated instead of + * blocking the multiprocessing receive thread. + */ +SCORE_EXTERN Thread_Control *_MPCI_Receive_server_tcb; + +/** + * The following table contains the process packet routines provided + * by each object that supports MP operations. + */ +SCORE_EXTERN MPCI_Packet_processor + _MPCI_Packet_processors[MP_PACKET_CLASSES_LAST+1]; + +/** + * This routine performs the initialization necessary for this handler. + * + * @param[in] timeout_status is the value which should be returned to + * blocking threads when they timeout on a remote operation. + */ +void _MPCI_Handler_initialization( + uint32_t timeout_status +); + +/** + * This routine creates the packet receive server used in MP systems. + */ +void _MPCI_Create_server( void ); + +/** + * This routine initializes the MPCI driver by + * invoking the user provided MPCI initialization callout. + */ +void _MPCI_Initialization ( void ); + +/** + * This routine registers the MPCI packet processor for the + * designated object class. + * + * @param[in] the_class is the class indicator for packets which will + * be processed by @a the_packet_processor method. + * @param[in] the_packet_processor is a pointer to a method which is + * invoked when packets with @a the_class are received. + */ +void _MPCI_Register_packet_processor( + MP_packet_Classes the_class, + MPCI_Packet_processor the_packet_processor + +); + +/** + * This function obtains a packet by invoking the user provided + * MPCI get packet callout. + * + * @return This method returns a pointer to a MPCI packet which can be + * filled in by the caller and used to perform a subsequent + * remote operation. + */ +MP_packet_Prefix *_MPCI_Get_packet ( void ); + +/** + * This routine deallocates a packet by invoking the user provided + * MPCI return packet callout. + * + * @param[in] the_packet is the MP packet to deallocate. + */ +void _MPCI_Return_packet ( + MP_packet_Prefix *the_packet +); + +/** + * This routine sends a process packet by invoking the user provided + * MPCI send callout. + * + * @param[in] destination is the node which should receive this packet. + * @param[in] the_packet is the packet to be sent. + */ +void _MPCI_Send_process_packet ( + uint32_t destination, + MP_packet_Prefix *the_packet +); + +/** + * This routine sends a request packet by invoking the user provided + * MPCI send callout. + * + * @param[in] destination is the node which should receive this packet. + * @param[in] the_packet is the packet to be sent. + * @param[in] extra_state is the extra thread state bits which should be + * set in addition to the remote operation pending state. It + * may indicate the caller is blocking on a message queue + * operation. + * + * @return This method returns the operation status from the remote node. + */ +uint32_t _MPCI_Send_request_packet ( + uint32_t destination, + MP_packet_Prefix *the_packet, + States_Control extra_state +); + +/** + * This routine sends a response packet by invoking the user provided + * MPCI send callout. + * + * @param[in] destination is the node which should receive this packet. + * @param[in] the_packet is the packet to be sent. + */ +void _MPCI_Send_response_packet ( + uint32_t destination, + MP_packet_Prefix *the_packet +); + +/** + * This routine receives a packet by invoking the user provided + * MPCI receive callout. + * + * @return This method returns the packet received. + */ +MP_packet_Prefix *_MPCI_Receive_packet ( void ); + +/** + * This routine is responsible for passing @a the_packet to the thread + * waiting on the remote operation to complete. The unblocked thread is + * responsible for eventually freeing @a the_packet. + * + * @param[in] the_packet is the response packet to be processed. + * + * @return This method returns a pointer to the thread which was if unblocked + * or NULL if the waiting thread no longer exists. + */ +Thread_Control *_MPCI_Process_response ( + MP_packet_Prefix *the_packet +); + +/** + * This is the server thread which receives and processes all MCPI packets. + * + * @param[in] ignored is the thread argument. It is not used. + */ +Thread _MPCI_Receive_server( + uint32_t ignored +); + +/** + * This routine informs RTEMS of the availability of an MPCI packet. + */ +void _MPCI_Announce ( void ); + +/** + * This routine performs a remote procedure call so that a + * process operation can be performed on another node. + * + * @param[in] operation is the remote operation to perform. + */ +void _MPCI_Internal_packets_Send_process_packet ( + MPCI_Internal_Remote_operations operation +); + +/** + * _MPCI_Internal_packets_Send_request_packet + * + * This routine performs a remote procedure call so that a + * directive operation can be initiated on another node. + * + * This routine is not needed since there are no request + * packets to be sent by this manager. + */ + +/** + * _MPCI_Internal_packets_Send_response_packet + * + * This routine performs a remote procedure call so that a + * directive can be performed on another node. + * + * This routine is not needed since there are no response + * packets to be sent by this manager. + */ + +/** + * This routine performs the actions specific to this package for + * the request from another node. + */ +void _MPCI_Internal_packets_Process_packet ( + MP_packet_Prefix *the_packet_prefix +); + +/** + * _MPCI_Internal_packets_Send_object_was_deleted + * + * This routine is invoked indirectly by the thread queue + * when a proxy has been removed from the thread queue and + * the remote node must be informed of this. + * + * This routine is not needed since there are no objects + * deleted by this manager. + */ + +/** + * _MPCI_Internal_packets_Send_extract_proxy + * + * This routine is invoked when a task is deleted and it + * has a proxy which must be removed from a thread queue and + * the remote node must be informed of this. + * + * This routine is not needed since there are no objects + * deleted by this manager. + */ + +/** + * This routine is used to obtain a internal threads mp packet. + */ +MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void ); + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/mppkt.h b/cpukit/score/include/rtems/score/mppkt.h new file mode 100644 index 0000000000..db8e60d0df --- /dev/null +++ b/cpukit/score/include/rtems/score/mppkt.h @@ -0,0 +1,123 @@ +/** + * @file rtems/score/mppkt.h + * + * This package is the specification for the Packet Handler. + * This handler defines the basic packet and provides + * mechanisms to utilize packets based on this prefix. + * Packets are the fundamental basis for messages passed between + * nodes in an MP system. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_MPPKT_H +#define _RTEMS_SCORE_MPPKT_H + +/** + * @defgroup ScoreMPPacket MP Packet Handler + * + * This handler encapsulates the primary definition of MPCI packets. This + * handler defines the part of the packet that is common to all remote + * operations. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/object.h> +#include <rtems/score/priority.h> +#include <rtems/score/watchdog.h> + +/** + * The following enumerated type defines the packet classes. + * + * @note In general, each class corresponds to a manager + * which supports global operations. Each manager + * defines the set of supported operations. + */ +typedef enum { + MP_PACKET_MPCI_INTERNAL = 0, + MP_PACKET_TASKS = 1, + MP_PACKET_MESSAGE_QUEUE = 2, + MP_PACKET_SEMAPHORE = 3, + MP_PACKET_PARTITION = 4, + MP_PACKET_REGION = 5, + MP_PACKET_EVENT = 6, + MP_PACKET_SIGNAL = 7 +} MP_packet_Classes; + +/** + * This constant defines the first entry in the MP_packet_Classes enumeration. + */ +#define MP_PACKET_CLASSES_FIRST MP_PACKET_MPCI_INTERNAL + +/** + * This constant defines the last entry in the MP_packet_Classes enumeration. + */ +#define MP_PACKET_CLASSES_LAST MP_PACKET_SIGNAL + +/** + * The following record contains the prefix for every packet + * passed between nodes in an MP system. + * + * @note This structure is padded to ensure that anything following it + * is on a 16 byte boundary. This is the most stringent structure + * alignment rule encountered yet. + */ +typedef struct { + /** This field indicates the API class of the operation being performed. */ + MP_packet_Classes the_class; + /** This field is the id of the object to be acted upon. */ + Objects_Id id; + /** This field is the ID of the originating thread. */ + Objects_Id source_tid; + /** This field is the priority of the originating thread. */ + Priority_Control source_priority; + /** This field is where the status of the operation will be returned. */ + uint32_t return_code; + /** This field is the length of the data following the prefix. */ + uint32_t length; + /** This field is the length of the data which required network conversion. */ + uint32_t to_convert; + /** This field is the requested timeout for this operation. */ + Watchdog_Interval timeout; +} MP_packet_Prefix; + +/** + * An MPCI must support packets of at least this size. + */ +#define MP_PACKET_MINIMUM_PACKET_SIZE 64 + +/** + * The following constant defines the number of uint32_t 's + * in a packet which must be converted to native format in a + * heterogeneous system. In packets longer than + * MP_PACKET_MINIMUN_HETERO_CONVERSION uint32_t 's, some of the "extra" data + * may a user message buffer which is not automatically endian swapped. + */ +#define MP_PACKET_MINIMUN_HETERO_CONVERSION \ + ( sizeof( MP_packet_Prefix ) / sizeof( uint32_t ) ) + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/mppkt.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/object.h b/cpukit/score/include/rtems/score/object.h new file mode 100644 index 0000000000..590d831345 --- /dev/null +++ b/cpukit/score/include/rtems/score/object.h @@ -0,0 +1,845 @@ +/** + * @file rtems/score/object.h + * + * + * This include file contains all the constants and structures associated + * with the Object Handler. This Handler provides mechanisms which + * can be used to initialize and manipulate all objects which have + * ids. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_OBJECT_H +#define _RTEMS_SCORE_OBJECT_H + +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup Score SuperCore + * + * @brief Provides services for all APIs. + */ + +/** + * @defgroup ScoreCPU CPU Architecture Support + * + * @ingroup Score + * + * @brief Provides CPU architecture dependent services. + */ + +/** + * The following type defines the control block used to manage + * object names. + */ +typedef union { + #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES) + /** This is a pointer to a string name. */ + const char *name_p; + #endif + /** This is the actual 32-bit "raw" integer name. */ + uint32_t name_u32; +} Objects_Name; + +/** + * Space for object names is allocated in multiples of this. + * + * NOTE: Must be a power of 2. Matches the name manipulation routines. + */ +#define OBJECTS_NAME_ALIGNMENT sizeof( uint32_t ) + +/** + * Functions which compare names are prototyped like this. + */ +typedef bool (*Objects_Name_comparators)( + void * /* name_1 */, + void * /* name_2 */, + uint16_t /* length */ +); + +#if defined(RTEMS_USE_16_BIT_OBJECT) +/** + * The following type defines the control block used to manage + * object IDs. The format is as follows (0=LSB): + * + * Bits 0 .. 7 = index (up to 254 objects of a type) + * Bits 8 .. 10 = API (up to 7 API classes) + * Bits 11 .. 15 = class (up to 31 object types per API) + */ +typedef uint16_t Objects_Id; + +/** + * This type is used to store the maximum number of allowed objects + * of each type. + */ +typedef uint8_t Objects_Maximum; + +#define OBJECTS_INDEX_START_BIT 0U +#define OBJECTS_API_START_BIT 8U +#define OBJECTS_CLASS_START_BIT 11U + +#define OBJECTS_INDEX_MASK (Objects_Id)0x00ffU +#define OBJECTS_API_MASK (Objects_Id)0x0700U +#define OBJECTS_CLASS_MASK (Objects_Id)0xF800U + +#define OBJECTS_INDEX_VALID_BITS (Objects_Id)0x00ffU +#define OBJECTS_API_VALID_BITS (Objects_Id)0x0007U +/* OBJECTS_NODE_VALID_BITS should not be used with 16 bit Ids */ +#define OBJECTS_CLASS_VALID_BITS (Objects_Id)0x001fU + +#define OBJECTS_UNLIMITED_OBJECTS 0x8000U + +#define OBJECTS_ID_INITIAL_INDEX (0) +#define OBJECTS_ID_FINAL_INDEX (0xff) + +#else +/** + * The following type defines the control block used to manage + * object IDs. The format is as follows (0=LSB): + * + * Bits 0 .. 15 = index (up to 65535 objects of a type) + * Bits 16 .. 23 = node (up to 255 nodes) + * Bits 24 .. 26 = API (up to 7 API classes) + * Bits 27 .. 31 = class (up to 31 object types per API) + */ +typedef uint32_t Objects_Id; + +/** + * This type is used to store the maximum number of allowed objects + * of each type. + */ +typedef uint16_t Objects_Maximum; + +/** + * This is the bit position of the starting bit of the index portion of + * the object Id. + */ +#define OBJECTS_INDEX_START_BIT 0U + + +/** + * This is the bit position of the starting bit of the node portion of + * the object Id. + */ +#define OBJECTS_NODE_START_BIT 16U + +/** + * This is the bit position of the starting bit of the API portion of + * the object Id. + */ +#define OBJECTS_API_START_BIT 24U + +/** + * This is the bit position of the starting bit of the class portion of + * the object Id. + */ +#define OBJECTS_CLASS_START_BIT 27U + +/** + * This mask is used to extract the index portion of an object Id. + */ +#define OBJECTS_INDEX_MASK (Objects_Id)0x0000ffffU + +/** + * This mask is used to extract the node portion of an object Id. + */ +#define OBJECTS_NODE_MASK (Objects_Id)0x00ff0000U + +/** + * This mask is used to extract the API portion of an object Id. + */ +#define OBJECTS_API_MASK (Objects_Id)0x07000000U + +/** + * This mask is used to extract the class portion of an object Id. + */ +#define OBJECTS_CLASS_MASK (Objects_Id)0xf8000000U + +/** + * This mask represents the bits that is used to ensure no extra bits + * are set after shifting to extract the index portion of an object Id. + */ +#define OBJECTS_INDEX_VALID_BITS (Objects_Id)0x0000ffffU + +/** + * This mask represents the bits that is used to ensure no extra bits + * are set after shifting to extract the node portion of an object Id. + */ +#define OBJECTS_NODE_VALID_BITS (Objects_Id)0x000000ffU + +/** + * This mask represents the bits that is used to ensure no extra bits + * are set after shifting to extract the API portion of an object Id. + */ +#define OBJECTS_API_VALID_BITS (Objects_Id)0x00000007U + +/** + * This mask represents the bits that is used to ensure no extra bits + * are set after shifting to extract the class portion of an object Id. + */ +#define OBJECTS_CLASS_VALID_BITS (Objects_Id)0x0000001fU + +/** + * Mask to enable unlimited objects. This is used in the configuration + * table when specifying the number of configured objects. + */ +#define OBJECTS_UNLIMITED_OBJECTS 0x80000000U + +/** + * This is the lowest value for the index portion of an object Id. + */ +#define OBJECTS_ID_INITIAL_INDEX (0) + +/** + * This is the highest value for the index portion of an object Id. + */ +#define OBJECTS_ID_FINAL_INDEX (0xffffU) +#endif + +/** + * This enumerated type is used in the class field of the object ID. + */ +typedef enum { + OBJECTS_NO_API = 0, + OBJECTS_INTERNAL_API = 1, + OBJECTS_CLASSIC_API = 2, + OBJECTS_POSIX_API = 3 +} Objects_APIs; + +/** This macro is used to generically specify the last API index. */ +#define OBJECTS_APIS_LAST OBJECTS_POSIX_API + +/** + * This enumerated type is used in the class field of the object ID + * for RTEMS internal object classes. + */ +typedef enum { + OBJECTS_INTERNAL_NO_CLASS = 0, + OBJECTS_INTERNAL_THREADS = 1, + OBJECTS_INTERNAL_MUTEXES = 2 +} Objects_Internal_API; + +/** This macro is used to generically specify the last API index. */ +#define OBJECTS_INTERNAL_CLASSES_LAST OBJECTS_INTERNAL_MUTEXES + +/** + * This enumerated type is used in the class field of the object ID + * for the RTEMS Classic API. + */ +typedef enum { + OBJECTS_CLASSIC_NO_CLASS = 0, + OBJECTS_RTEMS_TASKS = 1, + OBJECTS_RTEMS_TIMERS = 2, + OBJECTS_RTEMS_SEMAPHORES = 3, + OBJECTS_RTEMS_MESSAGE_QUEUES = 4, + OBJECTS_RTEMS_PARTITIONS = 5, + OBJECTS_RTEMS_REGIONS = 6, + OBJECTS_RTEMS_PORTS = 7, + OBJECTS_RTEMS_PERIODS = 8, + OBJECTS_RTEMS_EXTENSIONS = 9, + OBJECTS_RTEMS_BARRIERS = 10 +} Objects_Classic_API; + +/** This macro is used to generically specify the last API index. */ +#define OBJECTS_RTEMS_CLASSES_LAST OBJECTS_RTEMS_BARRIERS + +/** + * This enumerated type is used in the class field of the object ID + * for the POSIX API. + */ +typedef enum { + OBJECTS_POSIX_NO_CLASS = 0, + OBJECTS_POSIX_THREADS = 1, + OBJECTS_POSIX_KEYS = 2, + OBJECTS_POSIX_INTERRUPTS = 3, + OBJECTS_POSIX_MESSAGE_QUEUE_FDS = 4, + OBJECTS_POSIX_MESSAGE_QUEUES = 5, + OBJECTS_POSIX_MUTEXES = 6, + OBJECTS_POSIX_SEMAPHORES = 7, + OBJECTS_POSIX_CONDITION_VARIABLES = 8, + OBJECTS_POSIX_TIMERS = 9, + OBJECTS_POSIX_BARRIERS = 10, + OBJECTS_POSIX_SPINLOCKS = 11, + OBJECTS_POSIX_RWLOCKS = 12 +} Objects_POSIX_API; + +/** This macro is used to generically specify the last API index. */ +#define OBJECTS_POSIX_CLASSES_LAST OBJECTS_POSIX_RWLOCKS + +/** + * This enumerated type lists the locations which may be returned + * by _Objects_Get. These codes indicate the success of locating + * an object with the specified ID. + */ +typedef enum { +#if defined(RTEMS_MULTIPROCESSING) + OBJECTS_REMOTE = 2, /* object is remote */ +#endif + OBJECTS_LOCAL = 0, /* object is local */ + OBJECTS_ERROR = 1 /* id was invalid */ +} Objects_Locations; + +/** + * The following type defines the callout used when a local task + * is extracted from a remote thread queue (i.e. it's proxy must + * extracted from the remote queue). + */ +typedef void ( *Objects_Thread_queue_Extract_callout )( void * ); + +/** + * The following defines the Object Control Block used to manage + * each object local to this node. + */ +typedef struct { + /** This is the chain node portion of an object. */ + Chain_Node Node; + /** This is the object's ID. */ + Objects_Id id; + /** This is the object's name. */ + Objects_Name name; +} Objects_Control; + +/** + * The following defines the structure for the information used to + * manage each class of objects. + */ +typedef struct { + /** This field indicates the API of this object class. */ + Objects_APIs the_api; + /** This is the class of this object set. */ + uint16_t the_class; + /** This is the minimum valid id of this object class. */ + Objects_Id minimum_id; + /** This is the maximum valid id of this object class. */ + Objects_Id maximum_id; + /** This is the maximum number of objects in this class. */ + Objects_Maximum maximum; + /** This is the true if unlimited objects in this class. */ + bool auto_extend; + /** This is the number of objects in a block. */ + Objects_Maximum allocation_size; + /** This is the size in bytes of each object instance. */ + size_t size; + /** This points to the table of local objects. */ + Objects_Control **local_table; + /** This is the chain of inactive control blocks. */ + Chain_Control Inactive; + /** This is the number of objects on the Inactive list. */ + Objects_Maximum inactive; + /** This is the number of inactive objects per block. */ + uint32_t *inactive_per_block; + /** This is a table to the chain of inactive object memory blocks. */ + void **object_blocks; + #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES) + /** This is true if names are strings. */ + bool is_string; + #endif + /** This is the maximum length of names. */ + uint16_t name_length; + /** This is this object class' method called when extracting a thread. */ + Objects_Thread_queue_Extract_callout extract; + #if defined(RTEMS_MULTIPROCESSING) + /** This is this object class' pointer to the global name table */ + Chain_Control *global_table; + #endif +} Objects_Information; + +/** + * The following is referenced to the node number of the local node. + */ +#if defined(RTEMS_MULTIPROCESSING) +SCORE_EXTERN uint16_t _Objects_Local_node; +#else +#define _Objects_Local_node ((uint16_t)1) +#endif + +/** + * The following is referenced to the number of nodes in the system. + */ +#if defined(RTEMS_MULTIPROCESSING) +SCORE_EXTERN uint16_t _Objects_Maximum_nodes; +#else +#define _Objects_Maximum_nodes 1 +#endif + +/** + * The following is the list of information blocks per API for each object + * class. From the ID, we can go to one of these information blocks, + * and obtain a pointer to the appropriate object control block. + */ +SCORE_EXTERN Objects_Information + **_Objects_Information_table[OBJECTS_APIS_LAST + 1]; + +/** + * No object can have this ID. + */ +#define OBJECTS_ID_NONE 0 + +/** + * The following defines the constant which may be used + * with _Objects_Get to manipulate the calling task. + */ +#define OBJECTS_ID_OF_SELF ((Objects_Id) 0) + +/** + * The following constant is used to specify that a name to ID search + * should search through all nodes. + */ +#define OBJECTS_SEARCH_ALL_NODES 0 + +/** + * The following constant is used to specify that a name to ID search + * should search through all nodes except the current node. + */ +#define OBJECTS_SEARCH_OTHER_NODES 0x7FFFFFFE + +/** + * The following constant is used to specify that a name to ID search + * should search only on this node. + */ +#define OBJECTS_SEARCH_LOCAL_NODE 0x7FFFFFFF + +/** + * The following constant is used to specify that a name to ID search + * is being asked for the ID of the currently executing task. + */ +#define OBJECTS_WHO_AM_I 0 + +/** + * This macros calculates the lowest ID for the specified api, class, + * and node. + */ +#define OBJECTS_ID_INITIAL(_api, _class, _node) \ + _Objects_Build_id( (_api), (_class), (_node), OBJECTS_ID_INITIAL_INDEX ) + +/** + * This macro specifies the highest object ID value + */ +#define OBJECTS_ID_FINAL ((Objects_Id)~0) + +/** + * This function extends an object class information record. + * + * @param[in] information points to an object class information block. + */ +void _Objects_Extend_information( + Objects_Information *information +); + +/** + * This function shrink an object class information record. + * + * @param[in] information points to an object class information block. + */ +void _Objects_Shrink_information( + Objects_Information *information +); + +/** + * This function initializes an object class information record. + * SUPPORTS_GLOBAL is true if the object class supports global + * objects, and false otherwise. Maximum indicates the number + * of objects required in this class and size indicates the size + * in bytes of each control block for this object class. The + * name length and string designator are also set. In addition, + * the class may be a task, therefore this information is also included. + * + * @param[in] information points to an object class information block. + * @param[in] the_api indicates the API associated with this information block. + * @param[in] the_class indicates the class of object being managed + * by this information block. It is specific to @a the_api. + * @param[in] maximum is the maximum number of instances of this object + * class which may be concurrently active. + * @param[in] size is the size of the data structure for this class. + * @param[in] is_string is true if this object uses string style names. + * @param[in] maximum_name_length is the maximum length of object names. + */ +void _Objects_Initialize_information ( + Objects_Information *information, + Objects_APIs the_api, + uint16_t the_class, + uint32_t maximum, + uint16_t size, + bool is_string, + uint32_t maximum_name_length +#if defined(RTEMS_MULTIPROCESSING) + , + bool supports_global, + Objects_Thread_queue_Extract_callout extract +#endif +); + +/** + * This function returns the highest numeric value of a valid + * API for the specified @a api. + * + * @param[in] api is the API of interest + * + * @return A positive integer on success and 0 otherwise. + */ +unsigned int _Objects_API_maximum_class( + uint32_t api +); + +/** + * This function allocates a object control block from + * the inactive chain of free object control blocks. + * + * @param[in] information points to an object class information block. + */ +Objects_Control *_Objects_Allocate( + Objects_Information *information +); + +/** + * + * This function frees a object control block to the + * inactive chain of free object control blocks. + * + * @param[in] information points to an object class information block. + * @param[in] the_object points to the object to deallocate. + */ +void _Objects_Free( + Objects_Information *information, + Objects_Control *the_object +); + +/** + * This macro is used to build a thirty-two bit style name from + * four characters. The most significant byte will be the + * character @a _C1. + * + * @param[in] _C1 is the first character of the name + * @param[in] _C2 is the second character of the name + * @param[in] _C3 is the third character of the name + * @param[in] _C4 is the fourth character of the name + */ +#define _Objects_Build_name( _C1, _C2, _C3, _C4 ) \ + ( (uint32_t)(_C1) << 24 | \ + (uint32_t)(_C2) << 16 | \ + (uint32_t)(_C3) << 8 | \ + (uint32_t)(_C4) ) + +/** + * This function implements the common portion of the object + * identification directives. This directive returns the object + * id associated with name. If more than one object of this class + * is named name, then the object to which the id belongs is + * arbitrary. Node indicates the extent of the search for the + * id of the object named name. If the object class supports global + * objects, then the search can be limited to a particular node + * or allowed to encompass all nodes. + */ +typedef enum { + OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL, + OBJECTS_INVALID_NAME, + OBJECTS_INVALID_ADDRESS, + OBJECTS_INVALID_ID, + OBJECTS_INVALID_NODE +} Objects_Name_or_id_lookup_errors; + +/** + * This macro defines the first entry in the + * @ref Objects_Name_or_id_lookup_errors enumerated list. + */ +#define OBJECTS_NAME_ERRORS_FIRST OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL + +/** + * This macro defines the last entry in the + * @ref Objects_Name_or_id_lookup_errors enumerated list. + */ +#define OBJECTS_NAME_ERRORS_LAST OBJECTS_INVALID_NODE + +/** + * This method converts an object name to an Id. It performs a look up + * using the object information block for this object class. + * + * @param[in] information points to an object class information block. + * @param[in] name is the name of the object to find. + * @param[in] node is the set of nodes to search. + * @param[in] id will contain the Id if the search is successful. + * + * @return This method returns one of the values from the + * @ref Objects_Name_or_id_lookup_errors enumeration to indicate + * successful or failure. On success @a id will contain the Id of + * the requested object. + */ +Objects_Name_or_id_lookup_errors _Objects_Name_to_id_u32( + Objects_Information *information, + uint32_t name, + uint32_t node, + Objects_Id *id +); + +#if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES) +/** + * This method converts an object name to an Id. It performs a look up + * using the object information block for this object class. + * + * @param[in] information points to an object class information block. + * @param[in] name is the name of the object to find. + * @param[in] id will contain the Id if the search is successful. + * + * @return This method returns one of the values from the + * @ref Objects_Name_or_id_lookup_errors enumeration to indicate + * successful or failure. On success @a id will contain the Id of + * the requested object. + */ +Objects_Name_or_id_lookup_errors _Objects_Name_to_id_string( + Objects_Information *information, + const char *name, + Objects_Id *id +); +#endif + +/** + * This function implements the common portion of the object Id + * to name directives. This function returns the name + * associated with object id. + * + * @param[in] id is the Id of the object whose name we are locating. + * @param[in] name will contain the name of the object, if found. + * + * @return This method returns one of the values from the + * @ref Objects_Name_or_id_lookup_errors enumeration to indicate + * successful or failure. On success @a name will contain the name of + * the requested object. + * + * @note This function currently does not support string names. + */ +Objects_Name_or_id_lookup_errors _Objects_Id_to_name ( + Objects_Id id, + Objects_Name *name +); + +/** + * This function maps object ids to object control blocks. + * If id corresponds to a local object, then it returns + * the_object control pointer which maps to id and location + * is set to OBJECTS_LOCAL. If the object class supports global + * objects and the object id is global and resides on a remote + * node, then location is set to OBJECTS_REMOTE, and the_object + * is undefined. Otherwise, location is set to OBJECTS_ERROR + * and the_object is undefined. + * + * @param[in] information points to an object class information block. + * @param[in] id is the Id of the object whose name we are locating. + * @param[in] location will contain an indication of success or failure. + * + * @return This method returns one of the values from the + * @ref Objects_Name_or_id_lookup_errors enumeration to indicate + * successful or failure. On success @a id will contain the Id of + * the requested object. + * + * @note _Objects_Get returns with dispatching disabled for + * local and remote objects. _Objects_Get_isr_disable returns with + * dispatching disabled for remote objects and interrupts for local + * objects. + */ +Objects_Control *_Objects_Get ( + Objects_Information *information, + Objects_Id id, + Objects_Locations *location +); + +/** + * This function maps object ids to object control blocks. + * If id corresponds to a local object, then it returns + * the_object control pointer which maps to id and location + * is set to OBJECTS_LOCAL. If the object class supports global + * objects and the object id is global and resides on a remote + * node, then location is set to OBJECTS_REMOTE, and the_object + * is undefined. Otherwise, location is set to OBJECTS_ERROR + * and the_object is undefined. + * + * @param[in] information points to an object class information block. + * @param[in] id is the Id of the object whose name we are locating. + * @param[in] location will contain an indication of success or failure. + * @param[in] level is the interrupt level being turned. + * + * @return This method returns one of the values from the + * @ref Objects_Name_or_id_lookup_errors enumeration to indicate + * successful or failure. On success @a name will contain the name of + * the requested object. + * + * @note _Objects_Get returns with dispatching disabled for + * local and remote objects. _Objects_Get_isr_disable returns with + * dispatchng disabled for remote objects and interrupts for local + * objects. + */ +Objects_Control *_Objects_Get_isr_disable( + Objects_Information *information, + Objects_Id id, + Objects_Locations *location, + ISR_Level *level +); + +/** + * This function maps object ids to object control blocks. + * If id corresponds to a local object, then it returns + * the_object control pointer which maps to id and location + * is set to OBJECTS_LOCAL. If the object class supports global + * objects and the object id is global and resides on a remote + * node, then location is set to OBJECTS_REMOTE, and the_object + * is undefined. Otherwise, location is set to OBJECTS_ERROR + * and the_object is undefined. + * + * @param[in] information points to an object class information block. + * @param[in] id is the Id of the object whose name we are locating. + * @param[in] location will contain an indication of success or failure. + * + * @return This method returns one of the values from the + * @ref Objects_Name_or_id_lookup_errors enumeration to indicate + * successful or failure. On success @a id will contain the Id of + * the requested object. + * + * @note _Objects_Get returns with dispatching disabled for + * local and remote objects. _Objects_Get_isr_disable returns with + * dispatching disabled for remote objects and interrupts for local + * objects. + */ +Objects_Control *_Objects_Get_no_protection( + Objects_Information *information, + Objects_Id id, + Objects_Locations *location +); + +/** + * Like @ref _Objects_Get, but is used to find "next" open object. + * + * @param[in] information points to an object class information block. + * @param[in] id is the Id of the object whose name we are locating. + * @param[in] location_p will contain an indication of success or failure. + * @param[in] next_id_p is the Id of the next object we will look at. + * + * @return This method returns the pointer to the object located or + * NULL on error. + */ +Objects_Control *_Objects_Get_next( + Objects_Information *information, + Objects_Id id, + Objects_Locations *location_p, + Objects_Id *next_id_p +); + +/** + * This function return the information structure given + * an the API and Class. This can be done independent of + * the existence of any objects created by the API. + * + * @param[in] the_api indicates the API for the information we want + * @param[in] the_class indicates the Class for the information we want + * + * @return This method returns a pointer to the Object Information Table + * for the class of objects which corresponds to this object ID. + */ +Objects_Information *_Objects_Get_information( + Objects_APIs the_api, + uint16_t the_class +); + +/** + * This function return the information structure given + * an id of an object. + * + * @param[in] id is an object ID + * + * @return This method returns a pointer to the Object Information Table + * for the class of objects which corresponds to this object ID. + */ +Objects_Information *_Objects_Get_information_id( + Objects_Id id +); + +/** + * This method objects the name of an object and returns its name + * in the form of a C string. It attempts to be careful about + * overflowing the user's string and about returning unprintable characters. + * + * @param[in] id is the object to obtain the name of + * @param[in] length indicates the length of the caller's buffer + * @param[in] name points a string which will be filled in. + * + * @return This method returns @a name or NULL on error. @a *name will + * contain the name if successful. + */ +char *_Objects_Get_name_as_string( + Objects_Id id, + size_t length, + char *name +); + +/** + * This method sets the object name to either a copy of a string + * or up to the first four characters of the string based upon + * whether this object class uses strings for names. + * + * @param[in] information points to the object information structure + * @param[in] the_object is the object to operate upon + * @param[in] name is a pointer to the name to use + * + * @return If successful, true is returned. Otherwise false is returned. + */ +bool _Objects_Set_name( + Objects_Information *information, + Objects_Control *the_object, + const char *name +); + +/** + * This function removes the_object from the namespace. + * + * @param[in] information points to an Object Information Table + * @param[in] the_object is a pointer to an object + */ +void _Objects_Namespace_remove( + Objects_Information *information, + Objects_Control *the_object +); + +/** + * This function removes the_object control pointer and object name + * in the Local Pointer and Local Name Tables. + * + * @param[in] information points to an Object Information Table + * @param[in] the_object is a pointer to an object + */ +void _Objects_Close( + Objects_Information *information, + Objects_Control *the_object +); + +/* + * Pieces of object.inl are promoted out to the user + */ + +#include <rtems/score/object.inl> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/objectmp.h> +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/objectmp.h b/cpukit/score/include/rtems/score/objectmp.h new file mode 100644 index 0000000000..318819ffd8 --- /dev/null +++ b/cpukit/score/include/rtems/score/objectmp.h @@ -0,0 +1,188 @@ +/** + * @file rtems/score/objectmp.h + * + * This include file contains all the constants and structures associated + * with the manipulation of Global RTEMS Objects. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_OBJECTMP_H +#define _RTEMS_SCORE_OBJECTMP_H + +/** + * @defgroup ScoreObjectMP Object Handler Multiprocessing Support + * + * This handler encapsulates functionality which is used to manage + * objects which have been declared to be globally visible. This handler + * knows objects from all of the nodes in the system. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This defines the Global Object Control Block used to manage + * objects resident on other nodes. It is derived from Object. + */ +typedef struct { + /** This is an object control structure. */ + Objects_Control Object; + /** This is the name of the object. Using an unsigned thirty two + * bit value is broken but works. If any API is MP with variable + * length names .. BOOM!!!! + */ + uint32_t name; +} Objects_MP_Control; + +/** @brief Objects MP Handler initialization + * + * This routine intializes the inactive global object chain + * based on the maximum number of global objects configured. + */ +void _Objects_MP_Handler_initialization(void); + +/** @brief Objects MP Handler Early initialization + * + * This routine intializes the global object node number + * used in the ID field of all objects. + */ +void _Objects_MP_Handler_early_initialization(void); + +/** @brief Objects MP Open + * + * This routine place the specified global object in the + * specified information table. + * + * @param[in] information points to the object information table for this + * object class. + * @param[in] the_global_object points to the object being opened. + * @param[in] the_name is the name of the object being opened. + * @param[in] the_id is the Id of the object being opened. + * + * @todo This method only works for object types with 4 byte object names. + * It does not support variable length object names. + */ +void _Objects_MP_Open ( + Objects_Information *information, + Objects_MP_Control *the_global_object, + uint32_t the_name, + Objects_Id the_id +); + +/** @brief Objects MP Allocate and open + * + * This routine allocates a global object control block + * and places it in the specified information table. If the + * allocation fails, then is_fatal_error determines the + * error processing actions taken. + * + * @param[in] information points to the object information table for this + * object class. + * @param[in] the_name is the name of the object being opened. + * @param[in] the_id is the Id of the object being opened. + * @param[in] is_fatal_error is true if not being able to allocate the + * object is considered a fatal error. + * + * @todo This method only works for object types with 4 byte object names. + * It does not support variable length object names. + */ +bool _Objects_MP_Allocate_and_open ( + Objects_Information *information, + uint32_t the_name, + Objects_Id the_id, + bool is_fatal_error +); + +/** @brief Objects MP Close + * + * This routine removes a global object from the specified + * information table and deallocates the global object control block. + */ +void _Objects_MP_Close ( + Objects_Information *information, + Objects_Id the_id +); + +/** @brief Objects MP Global name search + * + * This routine looks for the object with the_name in the global + * object tables indicated by information. It returns the ID of the + * object with that name if one is found. + * + * @param[in] information points to the object information table for this + * object class. + * @param[in] the_name is the name of the object being searched for. + * @param[in] nodes_to_search indicates the set of nodes to search. + * @param[in] the_id will contain the Id of the object if found. + * + * @return This method returns one of the + * @ref Objects_Name_or_id_lookup_errors. If successful, @a the_id + * will contain the Id of the object. + */ +Objects_Name_or_id_lookup_errors _Objects_MP_Global_name_search ( + Objects_Information *information, + Objects_Name the_name, + uint32_t nodes_to_search, + Objects_Id *the_id +); + +/** @brief Objects MP Is remote + * + * This function searches the Global Object Table managed + * by information for the object indicated by ID. If the object + * is found, then location is set to objects_remote, otherwise + * location is set to objects_error. In both cases, the_object + * is undefined. + * + * @param[in] information points to the object information table for this + * object class. + * @param[in] the_id is the Id of the object being opened. + * @param[in] location will contain the location of the object. + * @param[in] the_object will contain a pointer to the object. + * + * @return This method fills in @a location to indicate successful location + * of the object or error. On success, @a the_object will be + * filled in. + */ +void _Objects_MP_Is_remote ( + Objects_Information *information, + Objects_Id the_id, + Objects_Locations *location, + Objects_Control **the_object +); + +/** + * This is the maximum number of global objects configured. + */ +SCORE_EXTERN uint32_t _Objects_MP_Maximum_global_objects; + +/** + * The following chain header is used to manage the set of + * inactive global object control blocks. + */ +SCORE_EXTERN Chain_Control _Objects_MP_Inactive_global_objects; + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/objectmp.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h new file mode 100644 index 0000000000..0c48b50570 --- /dev/null +++ b/cpukit/score/include/rtems/score/percpu.h @@ -0,0 +1,257 @@ +/** + * @file rtems/score/percpu.h + * + * This include file defines the per CPU information required + * by RTEMS. + */ + +/* + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_PERCPU_H +#define _RTEMS_PERCPU_H + +#include <rtems/score/cpu.h> + +#ifdef ASM + #include <rtems/asm.h> +#else + #if defined(RTEMS_SMP) + #include <rtems/score/smplock.h> + #endif + #include <rtems/bspsmp.h> +#endif + +/** + * @defgroup PerCPU RTEMS Per CPU Information + * + * This defines the per CPU state information required by RTEMS + * and the BSP. In an SMP configuration, there will be multiple + * instances of this data structure -- one per CPU -- and the + * current CPU number will be used as the index. + */ + +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ASM +#ifndef __THREAD_CONTROL_DEFINED__ +#define __THREAD_CONTROL_DEFINED__ +typedef struct Thread_Control_struct Thread_Control; +#endif + +#if (CPU_ALLOCATE_INTERRUPT_STACK == FALSE) && defined(RTEMS_SMP) + #error "RTEMS must allocate per CPU interrupt stack for SMP" +#endif + +typedef enum { + + /** + * This defines the constant used to indicate that the cpu code is in + * its initial powered up start. + */ + RTEMS_BSP_SMP_CPU_INITIAL_STATE = 1, + + /** + * This defines the constant used to indicate that the cpu code has + * completed basic initialization and awaits further commands. + */ + RTEMS_BSP_SMP_CPU_INITIALIZED = 2, + + /** + * This defines the constant used to indicate that the cpu code has + * shut itself down. + */ + RTEMS_BSP_SMP_CPU_SHUTDOWN = 3 +} bsp_smp_cpu_state; + +/** + * @brief Per CPU Core Structure + * + * This structure is used to hold per core state information. + */ +typedef struct { + #if defined(RTEMS_SMP) + /** This element is used to lock this structure */ + SMP_lock_Control lock; + + /** This indicates that the CPU is online. */ + uint32_t state; + + /** + * This is the request for the interrupt. + * + * @note This may become a chain protected by atomic instructions. + */ + uint32_t message; + + #endif + +#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \ + (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + /** + * This contains a pointer to the lower range of the interrupt stack for + * this CPU. This is the address allocated and freed. + */ + void *interrupt_stack_low; + + /** + * This contains a pointer to the interrupt stack pointer for this CPU. + * It will be loaded at the beginning on an ISR. + */ + void *interrupt_stack_high; +#endif + + /** + * This contains the current interrupt nesting level on this + * CPU. + */ + uint32_t isr_nest_level; + + /** This is the thread executing on this CPU. */ + Thread_Control *executing; + + /** This is the heir thread for this this CPU. */ + Thread_Control *heir; + + /** This is the idle thread for this CPU. */ + Thread_Control *idle; + + /** This is set to true when this CPU needs to run the dispatcher. */ + volatile bool dispatch_necessary; + +} Per_CPU_Control; +#endif + +#ifdef ASM +#if defined(RTEMS_SMP) + #define PER_CPU_LOCK 0 + #define PER_CPU_STATE (1 * __RTEMS_SIZEOF_VOID_P__) + #define PER_CPU_MESSAGE (2 * __RTEMS_SIZEOF_VOID_P__) + #define PER_CPU_END_SMP (3 * __RTEMS_SIZEOF_VOID_P__) +#else + #define PER_CPU_END_SMP 0 +#endif + +#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \ + (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + /* + * If this CPU target lets RTEMS allocates the interrupt stack, then + * we need to have places in the per cpu table to hold them. + */ + #define PER_CPU_INTERRUPT_STACK_LOW PER_CPU_END_SMP + #define PER_CPU_INTERRUPT_STACK_HIGH \ + PER_CPU_INTERRUPT_STACK_LOW + (1 * __RTEMS_SIZEOF_VOID_P__) + #define PER_CPU_END_STACK \ + PER_CPU_INTERRUPT_STACK_HIGH + (1 * __RTEMS_SIZEOF_VOID_P__) +#else + #define PER_CPU_END_STACK PER_CPU_END_SMP +#endif + +/* + * These are the offsets of the required elements in the per CPU table. + */ +#define PER_CPU_ISR_NEST_LEVEL \ + PER_CPU_END_STACK + 0 +#define PER_CPU_EXECUTING \ + PER_CPU_END_STACK + (1 * __RTEMS_SIZEOF_VOID_P__) +#define PER_CPU_HEIR \ + PER_CPU_END_STACK + (2 * __RTEMS_SIZEOF_VOID_P__) +#define PER_CPU_IDLE \ + PER_CPU_END_STACK + (3 * __RTEMS_SIZEOF_VOID_P__) +#define PER_CPU_DISPATCH_NEEDED \ + PER_CPU_END_STACK + (4 * __RTEMS_SIZEOF_VOID_P__) + +#define ISR_NEST_LEVEL \ + (SYM(_Per_CPU_Information) + PER_CPU_ISR_NEST_LEVEL) +#define DISPATCH_NEEDED \ + (SYM(_Per_CPU_Information) + PER_CPU_DISPATCH_NEEDED) + +/* + * Do not define these offsets if they are not in the table. + */ +#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \ + (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + #define INTERRUPT_STACK_LOW \ + (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_LOW) + #define INTERRUPT_STACK_HIGH \ + (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_HIGH) +#endif + +#endif + +#ifndef ASM + +/** + * @brief Set of Per CPU Core Information + * + * This is an array of per CPU core information. + */ +extern Per_CPU_Control _Per_CPU_Information[]; + +#if defined(RTEMS_SMP) +/** + * @brief Set of Pointers to Per CPU Core Information + * + * This is an array of pointers to each CPU's per CPU data structure. + * It should be simpler to retrieve this pointer in assembly language + * that to calculate the array offset. + */ +extern Per_CPU_Control *_Per_CPU_Information_p[]; + +/** + * @brief Initialize SMP Handler + * + * This method initialize the SMP Handler. + */ +void _SMP_Handler_initialize(void); + +/** + * @brief Allocate and Initialize Per CPU Structures + * + * This method allocates and initialize the per CPU structure. + */ +void _Per_CPU_Initialize(void); + +#endif + +/* + * On a non SMP system, the bsp_smp_processor_id is defined to 0. + * Thus when built for non-SMP, there should be no performance penalty. + */ +#define _Thread_Heir \ + _Per_CPU_Information[bsp_smp_processor_id()].heir +#define _Thread_Executing \ + _Per_CPU_Information[bsp_smp_processor_id()].executing +#define _Thread_Idle \ + _Per_CPU_Information[bsp_smp_processor_id()].idle +#define _ISR_Nest_level \ + _Per_CPU_Information[bsp_smp_processor_id()].isr_nest_level +#define _CPU_Interrupt_stack_low \ + _Per_CPU_Information[bsp_smp_processor_id()].interrupt_stack_low +#define _CPU_Interrupt_stack_high \ + _Per_CPU_Information[bsp_smp_processor_id()].interrupt_stack_high +#define _Thread_Dispatch_necessary \ + _Per_CPU_Information[bsp_smp_processor_id()].dispatch_necessary + +#endif /* ASM */ + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/priority.h b/cpukit/score/include/rtems/score/priority.h new file mode 100644 index 0000000000..05dc939d84 --- /dev/null +++ b/cpukit/score/include/rtems/score/priority.h @@ -0,0 +1,85 @@ +/** + * @file rtems/score/priority.h + * + * This include file contains all thread priority manipulation routines. + * This Handler provides mechanisms which can be used to + * initialize and manipulate thread priorities. + */ + +/* + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_PRIORITY_H +#define _RTEMS_SCORE_PRIORITY_H + +/** + * @defgroup ScorePriority Priority Handler + * + * This handler encapsulates functionality which is used to manage + * thread priorities. At the SuperCore level 256 priority levels + * are supported with lower numbers representing logically more important + * threads. The priority level 0 is reserved for internal RTEMS use. + * Typically it is assigned to threads which defer internal RTEMS + * actions from an interrupt to thread level to improve interrupt response. + * Priority level 255 is assigned to the IDLE thread and really should not + * be used by application threads. The default IDLE thread implementation + * is an infinite "branch to self" loop which never yields to other threads + * at the same priority. + */ +/**@{*/ + +/* + * Processor specific information. + */ +#include <rtems/score/cpu.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The following type defines the control block used to manage + * thread priorities. + * + * @note Priority 0 is reserved for internal threads only. + */ +typedef uint32_t Priority_Control; + +/** This defines the highest (most important) thread priority. */ +#define PRIORITY_MINIMUM 0 + +/** This defines the default lowest (least important) thread priority. */ +#if defined (CPU_PRIORITY_MAXIMUM) + #define PRIORITY_DEFAULT_MAXIMUM CPU_PRIORITY_MAXIMUM +#else + #define PRIORITY_DEFAULT_MAXIMUM 255 +#endif + +/** This defines the lowest (least important) thread priority. */ +#define PRIORITY_MAXIMUM rtems_maximum_priority + +/** + * This variable contains the configured number of priorities + */ +extern uint8_t rtems_maximum_priority; + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/priority.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/prioritybitmap.h b/cpukit/score/include/rtems/score/prioritybitmap.h new file mode 100644 index 0000000000..bba5b428b6 --- /dev/null +++ b/cpukit/score/include/rtems/score/prioritybitmap.h @@ -0,0 +1,124 @@ +/** + * @file rtems/score/prioritybitmap.h + * + * This include file contains all thread priority manipulation routines for + * the bit map priority queue implementation. + */ + +/* + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_PRIORITYBITMAP_H +#define _RTEMS_SCORE_PRIORITYBITMAP_H + +/** + * @addtogroup ScorePriority + * + */ +/**@{*/ + +/* + * Processor specific information. + */ +#include <rtems/score/cpu.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/priority.h> + + +/* + * The Priority_bit_map_Control variables are instantiated only + * if using the bit map handler. + */ + +/** + * Each sixteen bit entry in this array is associated with one of + * the sixteen entries in the Priority Bit map. + */ +extern volatile Priority_bit_map_Control _Priority_Major_bit_map; + +/** Each bit in the Priority Bitmap indicates whether or not there are + * threads ready at a particular priority. The mapping of + * individual priority levels to particular bits is processor + * dependent as is the value of each bit used to indicate that + * threads are ready at that priority. + */ +extern Priority_bit_map_Control + _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT; + +/* + * The definition of the Priority_bit_map_Control type is CPU dependent. + * + */ + +/** + * The following record defines the information associated with + * each thread to manage its interaction with the priority bit maps. + */ +typedef struct { + /** This is the address of minor bit map slot. */ + Priority_bit_map_Control *minor; + /** This is the priority bit map ready mask. */ + Priority_bit_map_Control ready_major; + /** This is the priority bit map ready mask. */ + Priority_bit_map_Control ready_minor; + /** This is the priority bit map block mask. */ + Priority_bit_map_Control block_major; + /** This is the priority bit map block mask. */ + Priority_bit_map_Control block_minor; +} Priority_bit_map_Information; + + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE ) +/** + * This method returns the priority bit mask for the specified major + * or minor bit number. + * + * @param[in] _bit_number is the bit number for which we need a mask + * + * @return the priority bit mask + * + * @note This may simply be a pass through to a CPU dependent implementation. + */ +#define _Priority_Mask( _bit_number ) \ + _CPU_Priority_Mask( _bit_number ) +#endif + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE ) +/** + * This method returns the bit index position for the specified priority. + * + * @param[in] _priority is the priority for which we need the index. + * + * @return This method returns the array index into the priority bit map. + * + * @note This may simply be a pass through to a CPU dependent implementation. + */ +#define _Priority_Bits_index( _priority ) \ + _CPU_Priority_bits_index( _priority ) +#endif + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/prioritybitmap.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/protectedheap.h b/cpukit/score/include/rtems/score/protectedheap.h new file mode 100644 index 0000000000..01c736d6ae --- /dev/null +++ b/cpukit/score/include/rtems/score/protectedheap.h @@ -0,0 +1,165 @@ +/** + * @file + * + * @ingroup ScoreProtHeap + * + * @brief Protected Heap Handler API. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_PROTECTED_HEAP_H +#define _RTEMS_SCORE_PROTECTED_HEAP_H + +#include <rtems/score/heap.h> +#include <rtems/score/apimutex.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup ScoreProtHeap Protected Heap Handler + * + * @ingroup ScoreHeap + * + * @brief Provides protected heap services. + * + * The @ref ScoreAllocatorMutex is used to protect the heap accesses. + * + * @{ + */ + +/** + * @brief See _Heap_Initialize(). + */ +RTEMS_INLINE_ROUTINE uintptr_t _Protected_heap_Initialize( + Heap_Control *heap, + void *area_begin, + uintptr_t area_size, + uintptr_t page_size +) +{ + return _Heap_Initialize( heap, area_begin, area_size, page_size ); +} + +/** + * @brief See _Heap_Extend(). + * + * Returns @a true in case of success, and @a false otherwise. + */ +bool _Protected_heap_Extend( + Heap_Control *heap, + void *area_begin, + uintptr_t area_size +); + +/** + * @brief See _Heap_Allocate_aligned_with_boundary(). + */ +void *_Protected_heap_Allocate_aligned_with_boundary( + Heap_Control *heap, + uintptr_t size, + uintptr_t alignment, + uintptr_t boundary +); + +/** + * @brief See _Heap_Allocate_aligned_with_boundary() with boundary equals zero. + */ +RTEMS_INLINE_ROUTINE void *_Protected_heap_Allocate_aligned( + Heap_Control *heap, + uintptr_t size, + uintptr_t alignment +) +{ + return + _Protected_heap_Allocate_aligned_with_boundary( heap, size, alignment, 0 ); +} + +/** + * @brief See _Heap_Allocate_aligned_with_boundary() with alignment and + * boundary equals zero. + */ +RTEMS_INLINE_ROUTINE void *_Protected_heap_Allocate( + Heap_Control *heap, + uintptr_t size +) +{ + return _Protected_heap_Allocate_aligned_with_boundary( heap, size, 0, 0 ); +} + +/** + * @brief See _Heap_Size_of_alloc_area(). + */ +bool _Protected_heap_Get_block_size( + Heap_Control *heap, + void *addr, + uintptr_t *size +); + +/** + * @brief See _Heap_Resize_block(). + * + * Returns @a true in case of success, and @a false otherwise. + */ +bool _Protected_heap_Resize_block( + Heap_Control *heap, + void *addr, + uintptr_t size +); + +/** + * @brief See _Heap_Free(). + * + * Returns @a true in case of success, and @a false otherwise. + */ +bool _Protected_heap_Free( Heap_Control *heap, void *addr ); + +/** + * @brief See _Heap_Walk(). + */ +bool _Protected_heap_Walk( Heap_Control *heap, int source, bool dump ); + +/** + * @brief See _Heap_Get_information(). + * + * Returns @a true in case of success, and @a false otherwise. + */ +bool _Protected_heap_Get_information( + Heap_Control *heap, + Heap_Information_block *info +); + +/** + * @brief See _Heap_Get_free_information(). + * + * Returns @a true in case of success, and @a false otherwise. + */ +bool _Protected_heap_Get_free_information( + Heap_Control *heap, + Heap_Information *info +); + +/** + * @brief See _Heap_Get_size(). + */ +uintptr_t _Protected_heap_Get_size( Heap_Control *heap ); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h new file mode 100644 index 0000000000..c094b9400a --- /dev/null +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -0,0 +1,122 @@ +/** + * @file rtems/score/scheduler.h + * + * This include file contains all the constants and structures associated + * with the scheduler. + */ + +/* + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_SCHEDULER_H +#define _RTEMS_SCORE_SCHEDULER_H + +#include <rtems/score/percpu.h> +#include <rtems/score/chain.h> +#include <rtems/score/priority.h> +#include <rtems/score/prioritybitmap.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup ScoreScheduler Scheduler Handler + * + * This handler encapsulates functionality related to managing sets of threads + * that are ready for execution. + */ +/**@{*/ + +/** + * function jump table that holds pointers to the functions that + * implement specific schedulers. + */ +typedef struct { + /** Implements the scheduling decision logic (policy). */ + void ( *initialize )(void); + + /** Implements the scheduling decision logic (policy). */ + void ( *schedule )(void); + + /** Voluntarily yields the processor per the scheduling policy. */ + void ( *yield )(void); + + /** Removes the given thread from scheduling decisions. */ + void ( *block )(Thread_Control *); + + /** Adds the given thread to scheduling decisions. */ + void ( *unblock )(Thread_Control *); + + /** allocates the scheduler field of the given thread */ + void * ( *allocate )(Thread_Control *); + + /** frees the scheduler field of the given thread */ + void ( *free )(Thread_Control *); + + /** updates the scheduler field of the given thread -- primarily used + * when changing the thread's priority. */ + void ( *update )(Thread_Control *); + + /** enqueue a thread as the last of its priority group */ + void ( *enqueue )(Thread_Control *); + + /** enqueue a thread as the first of its priority group */ + void ( *enqueue_first )(Thread_Control *); + + /** extract a thread from the ready set */ + void ( *extract )(Thread_Control *); +} Scheduler_Operations; + +/** + * This is the structure used to manage the scheduler. + */ +typedef struct { + /** + * This points to the data structure used to manage the ready set of + * tasks. The pointer varies based upon the type of + * ready queue required by the scheduler. + */ + void *information; + + /** The jump table for scheduler-specific functions */ + Scheduler_Operations Operations; +} Scheduler_Control; + +/** + * The _Scheduler holds the structures used to manage the + * scheduler. + * + * @note Can we make this per-cpu? then _Scheduler will be a macro. + * + * @note This is instantiated and initialized in confdefs.h. + */ +extern Scheduler_Control _Scheduler; + +/** + * This routine initializes the scheduler to the policy chosen by the user + * through confdefs, or to the priority scheduler with ready chains by + * default. + */ +void _Scheduler_Handler_initialization( void ); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/scheduler.inl> +#endif + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h new file mode 100644 index 0000000000..58ccc795e1 --- /dev/null +++ b/cpukit/score/include/rtems/score/schedulerpriority.h @@ -0,0 +1,194 @@ +/** + * @file rtems/score/schedulerpriority.h + * + * This include file contains all the constants and structures associated + * with the manipulation of threads for the priority-based scheduler. + */ + +/* + * Copryight (c) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_SCHEDULERPRIORITY_H +#define _RTEMS_SCORE_SCHEDULERPRIORITY_H + +#include <rtems/score/chain.h> +#include <rtems/score/priority.h> +#include <rtems/score/scheduler.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup ScoreScheduler + * + */ +/**@{*/ + +/** + * Entry points for the Deterministic Priority Based Scheduler. + */ +#define SCHEDULER_PRIORITY_ENTRY_POINTS \ + { \ + _Scheduler_priority_Initialize, /* initialize entry point */ \ + _Scheduler_priority_Schedule, /* schedule entry point */ \ + _Scheduler_priority_Yield, /* yield entry point */ \ + _Scheduler_priority_Block, /* block entry point */ \ + _Scheduler_priority_Unblock, /* unblock entry point */ \ + _Scheduler_priority_Allocate, /* allocate entry point */ \ + _Scheduler_priority_Free, /* free entry point */ \ + _Scheduler_priority_Update, /* update entry point */ \ + _Scheduler_priority_Enqueue, /* enqueue entry point */ \ + _Scheduler_priority_Enqueue_first, /* enqueue_first entry point */ \ + _Scheduler_priority_Extract /* extract entry point */ \ + } + +/** + * Per-thread data related to the _Scheduler_PRIORITY scheduling policy. + */ +typedef struct { + /** This field points to the Ready FIFO for this thread's priority. */ + Chain_Control *ready_chain; + + /** This field contains precalculated priority map indices. */ + Priority_bit_map_Information Priority_map; +} Scheduler_priority_Per_thread; + +/** + * This routine initializes the priority scheduler. + */ +void _Scheduler_priority_Initialize(void); + +/** + * This routine removes @a the_thread from the scheduling decision, + * that is, removes it from the ready queue. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_priority_Block( + Thread_Control *the_thread +); + +/** + * This kernel routine sets the heir thread to be the next ready thread + * by invoking the_scheduler->ready_queue->operations->first(). + */ +void _Scheduler_priority_Schedule(void); + +/** + * This routine allocates @a the_thread->scheduler. + * + * @param[in] the_thread is the thread the scheduler is allocating + * management memory for + */ +void * _Scheduler_priority_Allocate( + Thread_Control *the_thread +); + +/** + * This routine frees @a the_thread->scheduler. + * + * @param[in] the_thread is the thread whose scheduler specific information + * will be deallocated. + */ +void _Scheduler_priority_Free( + Thread_Control *the_thread +); + +/** + * This routine updates @a the_thread->scheduler based on @a the_scheduler + * structures and thread state. + * + * @param[in] the_thread will have its scheduler specific information + * structure updated. + */ +void _Scheduler_priority_Update( + Thread_Control *the_thread +); + +/** + * This routine adds @a the_thread to the scheduling decision, + * that is, adds it to the ready queue and + * updates any appropriate scheduling variables, for example the heir thread. + * + * @param[in] the_thread will be unblocked + */ +void _Scheduler_priority_Unblock( + Thread_Control *the_thread +); + +/** + * This routine is invoked when a thread wishes to voluntarily + * transfer control of the processor to another thread in the queue. + * + * This routine will remove the running THREAD from the ready queue + * and place it immediately at the rear of this chain. Reset timeslice + * and yield the processor functions both use this routine, therefore if + * reset is true and this is the only thread on the queue then the + * timeslice counter is reset. The heir THREAD will be updated if the + * running is also the currently the heir. + */ +void _Scheduler_priority_Yield( void ); + +/** + * This routine puts @a the_thread on to the priority-based ready queue. + * + * @param[in] the_thread will be enqueued at the TAIL of its priority. + */ +void _Scheduler_priority_Enqueue( + Thread_Control *the_thread +); + +/** + * This routine puts @a the_thread to the head of the ready queue. + * For priority-based ready queues, the thread will be the first thread + * at its priority level. + * + * @param[in] the_thread will be enqueued at the HEAD of its priority. + */ +void _Scheduler_priority_Enqueue_first( + Thread_Control *the_thread +); + +/** + * This routine removes a specific thread from the scheduler's set + * of ready threads. + * + * @param[in] the_thread will be extracted from the ready set. + */ +void _Scheduler_priority_Extract( + Thread_Control *the_thread +); + +/** + * This is the major bit map. + */ +extern volatile Priority_bit_map_Control _Priority_Major_bit_map; + +/** + * This is the minor bit map. + */ +extern Priority_bit_map_Control _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT; + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/schedulerpriority.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h new file mode 100644 index 0000000000..ea060ea59c --- /dev/null +++ b/cpukit/score/include/rtems/score/schedulersimple.h @@ -0,0 +1,199 @@ +/** + * @file rtems/score/schedulersimple.h + * + * This include file contains all the constants and structures associated + * with the manipulation of threads on a simple-priority-based ready queue. + * + * + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_SCHEDULERSIMPLE_H +#define _RTEMS_SCORE_SCHEDULERSIMPLE_H + +/** + * @addtogroup ScoreScheduler + * + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/scheduler.h> + +/** + * Entry points for Scheduler Simple + */ +#define SCHEDULER_SIMPLE_ENTRY_POINTS \ + { \ + _Scheduler_simple_Initialize, /* initialize entry point */ \ + _Scheduler_simple_Schedule, /* schedule entry point */ \ + _Scheduler_simple_Yield, /* yield entry point */ \ + _Scheduler_simple_Block, /* block entry point */ \ + _Scheduler_simple_Unblock, /* unblock entry point */ \ + _Scheduler_simple_Allocate, /* allocate entry point */ \ + _Scheduler_simple_Free, /* free entry point */ \ + _Scheduler_simple_Update, /* update entry point */ \ + _Scheduler_simple_Enqueue, /* enqueue entry point */ \ + _Scheduler_simple_Enqueue_first, /* enqueue_first entry point */ \ + _Scheduler_simple_Extract /* extract entry point */ \ + } + +/** + * This routine initializes the simple scheduler. + */ +void _Scheduler_simple_Initialize( void ); + +/** + * This routine sets the heir thread to be the next ready thread + * on the ready queue by getting the first node in the scheduler + * information. + */ +void _Scheduler_simple_Schedule( void ); + +/** + * This routine is invoked when a thread wishes to voluntarily + * transfer control of the processor to another thread in the queue. + * It will remove the running THREAD from the scheduler.informaiton + * (where the ready queue is stored) and place it immediately at the + * between the last entry of its priority and the next priority thread. + * Reset timeslice and yield the processor functions both use this routine, + * therefore if reset is true and this is the only thread on the queue then + * the timeslice counter is reset. The heir THREAD will be updated if the + * running is also the currently the heir. +*/ +void _Scheduler_simple_Yield( void ); + +/** + * This routine removes @a the_thread from the scheduling decision, + * that is, removes it from the ready queue. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + * + * @param[in] the_thread is the thread that is to be blocked + */ +void _Scheduler_simple_Block( + Thread_Control *the_thread +); + +/** + * This routine adds @a the_thread to the scheduling decision, + * that is, adds it to the ready queue and + * updates any appropriate scheduling variables, for example the heir thread. + * + * @param[in] the_thread is the thread that is to be unblocked + */ +void _Scheduler_simple_Unblock( + Thread_Control *the_thread +); + +/** + * This routine removes a specific thread from the specified + * simple-based ready queue. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_simple_Extract( + Thread_Control *the_thread +); + +/** + * This routine puts @a the_thread on to the ready queue. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_simple_Enqueue( + Thread_Control *the_thread +); + +/** + * This routine puts @a the_thread to the head of the ready queue. + * The thread will be the first thread at its priority level. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_simple_Enqueue_first( + Thread_Control *the_thread +); + +/** + * This routine is a place holder for any memeory allocation needed + * by the scheduler. For the simple scheduler the routine is an empty + * place holder. + * + * @param[in] the_thread is the thread the scheduler is allocating + * management memory for + * + * @return this routine returns -1 since this is just an empty placeholder + * and the return value may be defined differently by each scheduler. + */ +void *_Scheduler_simple_Allocate( + Thread_Control *the_thread +); + +/** + * This routine does nothing, and is used as a stub for Schedule update + * + * The overhead of a function call will still be imposed. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_simple_Update( + Thread_Control *the_thread +); + +/** + * This routine does nothing, and is used as a stub for Schedule free + * + * The overhead of a function call will still be imposed. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_simple_Free( + Thread_Control *the_thread +); + +/** + * _Scheduler_simple_Ready_queue_Enqueue + * + * This routine puts @a the_thread on the ready queue + * at the end of its priority group. + * + * @param[in] the_thread - pointer to a thread control block + */ +void _Scheduler_simple_Ready_queue_Enqueue( + Thread_Control *the_thread +); + +/** + * _Scheduler_simple_Ready_queue_Enqueue_first + * + * This routine puts @a the_thread on to the ready queue + * at the beginning of its priority group. + * + * @param[in] the_thread - pointer to a thread control block + */ +void _Scheduler_simple_Ready_queue_Enqueue_first( + Thread_Control *the_thread +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/schedulersimple.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/smplock.h b/cpukit/score/include/rtems/score/smplock.h new file mode 100644 index 0000000000..a20d9260a4 --- /dev/null +++ b/cpukit/score/include/rtems/score/smplock.h @@ -0,0 +1,95 @@ +/** + * @file rtems/score/smplock.h + * + * This include file defines the interface for atomic locks + * which can be used in multiprocessor configurations. + */ + +/* + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_LOCK_H +#define _RTEMS_LOCK_H + +#include <rtems/score/isr.h> + +/** + * @defgroup RTEMS Lock Interface + * + */ + +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This type is used to lock elements for atomic access. + * + * @note This type may move to RTEMS. + */ +typedef volatile uint32_t SMP_lock_Control; + +/** + * @brief Initialize a Lock + * + * This method is used to initialize the lock at @a lock. + * + * @param [in] lock is the address of the lock to obtain. + * + * @note This lock may be "too low" here. It may need to move + * out of the BSP area. + */ +void _SMP_lock_Spinlock_Initialize( + SMP_lock_Control *lock +); + +/** + * @brief Obtain a Lock + * + * This method is used to obtain the lock at @a lock. + * + * @param [in] lock is the address of the lock to obtain. + * + * @return This method returns with processor interrupts disabled. + * The previous level is returned. + * + * @note This lock may be "too low" here. It may need to move + * out of the BSP area. + */ +ISR_Level _SMP_lock_Spinlock_Obtain( + SMP_lock_Control *lock +); + +/** + * @brief Release a Lock + * + * This method is used to release the lock at @a lock. + * + * @param [in] lock is the address of the lock to obtain. + * + * @note This lock may be "too low" here. It may need to move + * out of the BSP area. + */ +void _SMP_lock_Spinlock_Release( + SMP_lock_Control *lock, + ISR_Level level +); + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/stack.h b/cpukit/score/include/rtems/score/stack.h new file mode 100644 index 0000000000..8f5a0173f3 --- /dev/null +++ b/cpukit/score/include/rtems/score/stack.h @@ -0,0 +1,69 @@ +/** + * @file rtems/score/stack.h + * + * This include file contains all information about the thread + * Stack Handler. This Handler provides mechanisms which can be used to + * initialize and utilize stacks. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_STACK_H +#define _RTEMS_SCORE_STACK_H + +/** + * @defgroup ScoreStack Stack Handler + * + * This handler encapsulates functionality which is used in the management + * of thread stacks. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The following constant defines the minimum stack size which every + * thread must exceed. + */ +#define STACK_MINIMUM_SIZE CPU_STACK_MINIMUM_SIZE + +/** + * The following defines the control block used to manage each stack. + */ +typedef struct { + /** This is the stack size. */ + size_t size; + /** This is the low memory address of stack. */ + void *area; +} Stack_Control; + +/** + * This variable contains the the minimum stack size; + * + * @note It is instantiated and set by User Configuration via confdefs.h. + */ +extern uint32_t rtems_minimum_stack_size; + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/stack.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/states.h b/cpukit/score/include/rtems/score/states.h new file mode 100644 index 0000000000..fc56924d8a --- /dev/null +++ b/cpukit/score/include/rtems/score/states.h @@ -0,0 +1,127 @@ +/** + * @file rtems/score/states.h + * + * This include file contains thread execution state information. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_STATES_H +#define _RTEMS_SCORE_STATES_H + +/** + * @defgroup ScoreStates Thread States Handler + * + * This handler encapsulates functionality which relates to the management of + * the state bitmap associated with each thread. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The following type defines the control block used to manage a + * thread's state. + */ +typedef uint32_t States_Control; + +/* + * The following constants define the individual states which may be + * be used to compose and manipulate a thread's state. + */ + +/** This macro corresponds to all states being set. */ +#define STATES_ALL_SET 0xfffff +/** This macro corresponds to a task being ready. */ +#define STATES_READY 0x00000 +/** This macro corresponds to a task being created but not yet started. */ +#define STATES_DORMANT 0x00001 +/** This macro corresponds to a task being suspended. */ +#define STATES_SUSPENDED 0x00002 +/** This macro corresponds to a task being in an internal state transition. */ +#define STATES_TRANSIENT 0x00004 +/** This macro corresponds to a task which is waiting for a timeout. */ +#define STATES_DELAYING 0x00008 +/** This macro corresponds to a task waiting until a specific TOD. */ +#define STATES_WAITING_FOR_TIME 0x00010 +/** This macro corresponds to a task waiting for a variable length buffer. */ +#define STATES_WAITING_FOR_BUFFER 0x00020 +/** This macro corresponds to a task waiting for a fixed size segment. */ +#define STATES_WAITING_FOR_SEGMENT 0x00040 +/** This macro corresponds to a task waiting for a message. */ +#define STATES_WAITING_FOR_MESSAGE 0x00080 +/** This macro corresponds to a task waiting for an event. */ +#define STATES_WAITING_FOR_EVENT 0x00100 +/** This macro corresponds to a task waiting for a semaphore. */ +#define STATES_WAITING_FOR_SEMAPHORE 0x00200 +/** This macro corresponds to a task waiting for a mutex. */ +#define STATES_WAITING_FOR_MUTEX 0x00400 +/** This macro corresponds to a task waiting for a condition variable. */ +#define STATES_WAITING_FOR_CONDITION_VARIABLE 0x00800 +/** This macro corresponds to a task waiting for a join while exiting. */ +#define STATES_WAITING_FOR_JOIN_AT_EXIT 0x01000 +/** This macro corresponds to a task waiting for a reply to an MPCI request. */ +#define STATES_WAITING_FOR_RPC_REPLY 0x02000 +/** This macro corresponds to a task waiting for a period. */ +#define STATES_WAITING_FOR_PERIOD 0x04000 +/** This macro corresponds to a task waiting for a signal. */ +#define STATES_WAITING_FOR_SIGNAL 0x08000 +/** This macro corresponds to a task waiting for a barrier. */ +#define STATES_WAITING_FOR_BARRIER 0x10000 +/** This macro corresponds to a task waiting for a RWLock. */ +#define STATES_WAITING_FOR_RWLOCK 0x20000 + +/** This macro corresponds to a task which is in an interruptible + * blocking state. + */ +#define STATES_INTERRUPTIBLE_BY_SIGNAL 0x10000000 + +/** This macro corresponds to a task waiting for a local object operation. */ +#define STATES_LOCALLY_BLOCKED ( STATES_WAITING_FOR_BUFFER | \ + STATES_WAITING_FOR_SEGMENT | \ + STATES_WAITING_FOR_MESSAGE | \ + STATES_WAITING_FOR_SEMAPHORE | \ + STATES_WAITING_FOR_MUTEX | \ + STATES_WAITING_FOR_CONDITION_VARIABLE | \ + STATES_WAITING_FOR_JOIN_AT_EXIT | \ + STATES_WAITING_FOR_SIGNAL | \ + STATES_WAITING_FOR_BARRIER | \ + STATES_WAITING_FOR_RWLOCK ) + +/** This macro corresponds to a task waiting which is blocked on + * a thread queue. */ +#define STATES_WAITING_ON_THREAD_QUEUE \ + ( STATES_LOCALLY_BLOCKED | \ + STATES_WAITING_FOR_RPC_REPLY ) + +/** This macro corresponds to a task waiting which is blocked. */ +#define STATES_BLOCKED ( STATES_DELAYING | \ + STATES_WAITING_FOR_TIME | \ + STATES_WAITING_FOR_PERIOD | \ + STATES_WAITING_FOR_EVENT | \ + STATES_WAITING_ON_THREAD_QUEUE | \ + STATES_INTERRUPTIBLE_BY_SIGNAL ) + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/states.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/sysstate.h b/cpukit/score/include/rtems/score/sysstate.h new file mode 100644 index 0000000000..1164367ebb --- /dev/null +++ b/cpukit/score/include/rtems/score/sysstate.h @@ -0,0 +1,98 @@ +/** + * @file + * + * @ingroup ScoreSysState + * + * @brief System State Handler API. + */ + +/* + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_SYSSTATE_H +#define _RTEMS_SCORE_SYSSTATE_H + +#include <rtems/score/basedefs.h> /* SCORE_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup ScoreSysState System State Handler + * + * @ingroup Score + * + * @brief Management of the internal system state of RTEMS. + * + * @{ + */ + +/** + * @brief System states. + */ +typedef enum { + /** + * @brief The system is before the end of the first phase of initialization. + */ + SYSTEM_STATE_BEFORE_INITIALIZATION, + + /** + * @brief The system is between end of the first phase of initialization but + * before multitasking is started. + */ + SYSTEM_STATE_BEFORE_MULTITASKING, + + /** + * @brief The system is attempting to initiate multitasking. + */ + SYSTEM_STATE_BEGIN_MULTITASKING, + + /** + * @brief The system is up and operating normally. + */ + SYSTEM_STATE_UP, + + /** + * @brief The system is in the midst of a shutdown. + */ + SYSTEM_STATE_SHUTDOWN, + + /** + * @brief A fatal error has occurred. + */ + SYSTEM_STATE_FAILED +} System_state_Codes; + +#define SYSTEM_STATE_CODES_FIRST SYSTEM_STATE_BEFORE_INITIALIZATION + +#define SYSTEM_STATE_CODES_LAST SYSTEM_STATE_FAILED + +#if defined(RTEMS_MULTIPROCESSING) +SCORE_EXTERN bool _System_state_Is_multiprocessing; +#endif + +SCORE_EXTERN System_state_Codes _System_state_Current; + +/* + * Make it possible for the application to get the system state information. + */ + +#include <rtems/score/sysstate.inl> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h new file mode 100644 index 0000000000..8754ee931d --- /dev/null +++ b/cpukit/score/include/rtems/score/thread.h @@ -0,0 +1,790 @@ +/** + * @file rtems/score/thread.h + * + * This include file contains all constants and structures associated + * with the thread control block. + */ + +/* + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_THREAD_H +#define _RTEMS_SCORE_THREAD_H + +/** + * @defgroup ScoreThread Thread Handler + * + * This handler encapsulates functionality related to the management of + * threads. This includes the creation, deletion, and scheduling of threads. + * + * The following variables are maintained as part of the per cpu data + * structure. + * + * + Idle thread pointer + * + Executing thread pointer + * + Heir thread pointer + */ +/**@{*/ + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE +#endif + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT +#endif + +#if defined(RTEMS_POSIX_API) + #define RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The user can define this at configure time and go back to ticks + * resolution. + */ +#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + #include <rtems/score/timestamp.h> + + typedef Timestamp_Control Thread_CPU_usage_t; +#else + typedef uint32_t Thread_CPU_usage_t; +#endif + +#include <rtems/score/percpu.h> +#include <rtems/score/context.h> +#include <rtems/score/cpu.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mppkt.h> +#endif +#include <rtems/score/object.h> +#include <rtems/score/priority.h> +#include <rtems/score/scheduler.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/score/tod.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/watchdog.h> + +/** + * The following defines the "return type" of a thread. + * + * @note This cannot always be right. Some APIs have void + * tasks/threads, others return pointers, others may + * return a numeric value. Hopefully a pointer is + * always at least as big as an uint32_t . :) + */ +typedef void *Thread; + +/** + * @brief Type of the numeric argument of a thread entry function with at + * least one numeric argument. + * + * This numeric argument type designates an unsigned integer type with the + * property that any valid pointer to void can be converted to this type and + * then converted back to a pointer to void. The result will compare equal to + * the original pointer. + */ +typedef uintptr_t Thread_Entry_numeric_type; + +/** + * The following defines the ways in which the entry point for a + * thread can be invoked. Basically, it can be passed any + * combination/permutation of a pointer and an uint32_t value. + * + * @note For now, we are ignoring the return type. + */ +typedef enum { + THREAD_START_NUMERIC, + THREAD_START_POINTER, + #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + THREAD_START_BOTH_POINTER_FIRST, + THREAD_START_BOTH_NUMERIC_FIRST + #endif +} Thread_Start_types; + +/** This type corresponds to a very simple style thread entry point. */ +typedef Thread ( *Thread_Entry )( void ); /* basic type */ + +/** This type corresponds to a thread entry point which takes a single + * unsigned thirty-two bit integer as an argument. + */ +typedef Thread ( *Thread_Entry_numeric )( Thread_Entry_numeric_type ); + +/** This type corresponds to a thread entry point which takes a single + * untyped pointer as an argument. + */ +typedef Thread ( *Thread_Entry_pointer )( void * ); + +/** This type corresponds to a thread entry point which takes a single + * untyped pointer and an unsigned thirty-two bit integer as arguments. + */ +typedef Thread ( *Thread_Entry_both_pointer_first )( void *, Thread_Entry_numeric_type ); + +/** This type corresponds to a thread entry point which takes a single + * unsigned thirty-two bit integer and an untyped pointer and an + * as arguments. + */ +typedef Thread ( *Thread_Entry_both_numeric_first )( Thread_Entry_numeric_type, void * ); + +/** + * The following lists the algorithms used to manage the thread cpu budget. + * + * Reset Timeslice: At each context switch, reset the time quantum. + * Exhaust Timeslice: Only reset the quantum once it is consumed. + * Callout: Execute routine when budget is consumed. + */ +typedef enum { + THREAD_CPU_BUDGET_ALGORITHM_NONE, + THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE, + #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE) + THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE, + #endif + #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) + THREAD_CPU_BUDGET_ALGORITHM_CALLOUT + #endif +} Thread_CPU_budget_algorithms; + +/** This defines thes the entry point for the thread specific timeslice + * budget management algorithm. + */ +typedef void (*Thread_CPU_budget_algorithm_callout )( Thread_Control * ); + +/** @brief Per Task Variable Manager Structure Forward Reference + * + * Forward reference to the per task variable structure. + */ +struct rtems_task_variable_tt; + +/** @brief Per Task Variable Manager Structure + * + * This is the internal structure used to manager per Task Variables. + */ +typedef struct { + /** This field points to the next per task variable for this task. */ + struct rtems_task_variable_tt *next; + /** This field points to the physical memory location of this per + * task variable. + */ + void **ptr; + /** This field is to the global value for this per task variable. */ + void *gval; + /** This field is to this thread's value for this per task variable. */ + void *tval; + /** This field points to the destructor for this per task variable. */ + void (*dtor)(void *); +} rtems_task_variable_t; + +/** + * The following structure contains the information which defines + * the starting state of a thread. + */ +typedef struct { + /** This field is the starting address for the thread. */ + Thread_Entry entry_point; + /** This field indicates the how task is invoked. */ + Thread_Start_types prototype; + /** This field is the pointer argument passed at thread start. */ + void *pointer_argument; + /** This field is the numeric argument passed at thread start. */ + Thread_Entry_numeric_type numeric_argument; + /*-------------- initial execution modes ----------------- */ + /** This field indicates whether the thread was preemptible when + * it started. + */ + bool is_preemptible; + /** This field indicates the CPU budget algorith. */ + Thread_CPU_budget_algorithms budget_algorithm; + /** This field is the routine to invoke when the CPU allotment is + * consumed. + */ + Thread_CPU_budget_algorithm_callout budget_callout; + /** This field is the initial ISR disable level of this thread. */ + uint32_t isr_level; + /** This field is the initial priority. */ + Priority_Control initial_priority; + #if defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API) + /** This field indicates whether the SuperCore allocated the stack. */ + bool core_allocated_stack; + #endif + /** This field is the stack information. */ + Stack_Control Initial_stack; + #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) + /** This field is the initial FP context area address. */ + Context_Control_fp *fp_context; + #endif + /** This field is the initial stack area address. */ + void *stack; +} Thread_Start_information; + +/** + * The following structure contains the information necessary to manage + * a thread which it is waiting for a resource. + */ +#define THREAD_STATUS_PROXY_BLOCKING 0x1111111 + +/** + * @brief Union type to hold a pointer to an immutable or a mutable object. + * + * The main purpose is to enable passing of pointers to read-only send buffers + * in the message passing subsystem. This approach is somewhat fragile since + * it prevents the compiler to check if the operations on objects are valid + * with respect to the constant qualifier. An alternative would be to add a + * third pointer argument for immutable objects, but this would increase the + * structure size. + */ +typedef union { + void *mutable_object; + const void *immutable_object; +} Thread_Wait_information_Object_argument_type; + +/** @brief Thread Blocking Management Information + * + * This contains the information required to manage a thread while it is + * blocked and to return information to it. + */ +typedef struct { + /** This field is the Id of the object this thread is waiting upon. */ + Objects_Id id; + /** This field is used to return an integer while when blocked. */ + uint32_t count; + /** This field is for a pointer to a user return argument. */ + void *return_argument; + /** This field is for a pointer to a second user return argument. */ + Thread_Wait_information_Object_argument_type + return_argument_second; + /** This field contains any options in effect on this blocking operation. */ + uint32_t option; + /** This field will contain the return status from a blocking operation. + * + * @note The following assumes that all API return codes can be + * treated as an uint32_t. + */ + uint32_t return_code; + + /** This field is the chain header for the second through Nth tasks + * of the same priority blocked waiting on the same object. + */ + Chain_Control Block2n; + /** This field points to the thread queue on which this thread is blocked. */ + Thread_queue_Control *queue; +} Thread_Wait_information; + +/** + * The following defines the control block used to manage + * each thread proxy. + * + * @note It is critical that proxies and threads have identical + * memory images for the shared part. + */ +typedef struct { + /** This field is the object management structure for each proxy. */ + Objects_Control Object; + /** This field is the current execution state of this proxy. */ + States_Control current_state; + /** This field is the current priority state of this proxy. */ + Priority_Control current_priority; + /** This field is the base priority of this proxy. */ + Priority_Control real_priority; + /** This field is the number of mutexes currently held by this proxy. */ + uint32_t resource_count; + + /** This field is the blocking information for this proxy. */ + Thread_Wait_information Wait; + /** This field is the Watchdog used to manage proxy delays and timeouts. */ + Watchdog_Control Timer; +#if defined(RTEMS_MULTIPROCESSING) + /** This field is the received response packet in an MP system. */ + MP_packet_Prefix *receive_packet; +#endif + /****************** end of common block ********************/ + /** This field is used to manage the set of proxies in the system. */ + Chain_Node Active; +} Thread_Proxy_control; + +/** + * The following record defines the control block used + * to manage each thread. + * + * @note It is critical that proxies and threads have identical + * memory images for the shared part. + */ +typedef enum { + /** This value is for the Classic RTEMS API. */ + THREAD_API_RTEMS, + /** This value is for the POSIX API. */ + THREAD_API_POSIX +} Thread_APIs; + +/** This macro defines the first API which has threads. */ +#define THREAD_API_FIRST THREAD_API_RTEMS + +/** This macro defines the last API which has threads. */ +#define THREAD_API_LAST THREAD_API_POSIX + +/** + * This structure defines the Thread Control Block (TCB). + */ +struct Thread_Control_struct { + /** This field is the object management structure for each thread. */ + Objects_Control Object; + /** This field is the current execution state of this thread. */ + States_Control current_state; + /** This field is the current priority state of this thread. */ + Priority_Control current_priority; + /** This field is the base priority of this thread. */ + Priority_Control real_priority; + /** This field is the number of mutexes currently held by this thread. */ + uint32_t resource_count; + /** This field is the blocking information for this thread. */ + Thread_Wait_information Wait; + /** This field is the Watchdog used to manage thread delays and timeouts. */ + Watchdog_Control Timer; +#if defined(RTEMS_MULTIPROCESSING) + /** This field is the received response packet in an MP system. */ + MP_packet_Prefix *receive_packet; +#endif +#ifdef __RTEMS_STRICT_ORDER_MUTEX__ + /** This field is the head of queue of priority inheritance mutex + * held by the thread. + */ + Chain_Control lock_mutex; +#endif + /*================= end of common block =================*/ + /** This field is the number of nested suspend calls. */ + uint32_t suspend_count; +#if defined(RTEMS_MULTIPROCESSING) + /** This field is true if the thread is offered globally */ + bool is_global; +#endif + /** This field is true if the thread is preemptible. */ + bool is_preemptible; +#if __RTEMS_ADA__ + /** This field is the GNAT self context pointer. */ + void *rtems_ada_self; +#endif + /** This field is the length of the time quantum that this thread is + * allowed to consume. The algorithm used to manage limits on CPU usage + * is specified by budget_algorithm. + */ + uint32_t cpu_time_budget; + /** This field is the algorithm used to manage this thread's time + * quantum. The algorithm may be specified as none which case, + * no limit is in place. + */ + Thread_CPU_budget_algorithms budget_algorithm; + /** This field is the method invoked with the budgeted time is consumed. */ + Thread_CPU_budget_algorithm_callout budget_callout; + /** This field is the amount of CPU time consumed by this thread + * since it was created. + */ + Thread_CPU_usage_t cpu_time_used; + + /** This pointer holds per-thread data for the scheduler and ready queue. */ + void *scheduler_info; + + /** This field contains information about the starting state of + * this thread. + */ + Thread_Start_information Start; + /** This field contains the context of this thread. */ + Context_Control Registers; +#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) + /** This field points to the floating point context for this thread. + * If NULL, the thread is integer only. + */ + Context_Control_fp *fp_context; +#endif + /** This field points to the newlib reentrancy structure for this thread. */ + struct _reent *libc_reent; + /** This array contains the API extension area pointers. */ + void *API_Extensions[ THREAD_API_LAST + 1 ]; + /** This field points to the user extension pointers. */ + void **extensions; + /** This field points to the set of per task variables. */ + rtems_task_variable_t *task_variables; +}; + +/** + * Self for the GNU Ada Run-Time + */ +SCORE_EXTERN void *rtems_ada_self; + +/** + * The following defines the information control block used to + * manage this class of objects. + */ +SCORE_EXTERN Objects_Information _Thread_Internal_information; + +/** + * The following context area contains the context of the "thread" + * which invoked the start multitasking routine. This context is + * restored as the last action of the stop multitasking routine. Thus + * control of the processor can be returned to the environment + * which initiated the system. + */ +SCORE_EXTERN Context_Control _Thread_BSP_context; + +/** + * The following declares the dispatch critical section nesting + * counter which is used to prevent context switches at inopportune + * moments. + */ +SCORE_EXTERN volatile uint32_t _Thread_Dispatch_disable_level; + +/** + * The following holds how many user extensions are in the system. This + * is used to determine how many user extension data areas to allocate + * per thread. + */ +SCORE_EXTERN uint32_t _Thread_Maximum_extensions; + +/** + * The following is used to manage the length of a timeslice quantum. + */ +SCORE_EXTERN uint32_t _Thread_Ticks_per_timeslice; + +/** + * The following points to the thread whose floating point + * context is currently loaded. + */ +#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) +SCORE_EXTERN Thread_Control *_Thread_Allocated_fp; +#endif + +/** + * The C library re-enter-rant global pointer. Some C library implementations + * such as newlib have a single global pointer that changed during a context + * switch. The pointer points to that global pointer. The Thread control block + * holds a pointer to the task specific data. + */ +SCORE_EXTERN struct _reent **_Thread_libc_reent; + +#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + + /** + * This contains the time since boot when the last context switch occurred. + * By placing it in the BSS, it will automatically be zeroed out at + * system initialization and does not need to be known outside this + * file. + */ + SCORE_EXTERN Timestamp_Control _Thread_Time_of_last_context_switch; +#endif + +/** + * This routine performs the initialization necessary for this handler. + */ +void _Thread_Handler_initialization(void); + +/** + * This routine creates the idle thread. + * + * @warning No thread should be created before this one. + */ +void _Thread_Create_idle(void); + +/** + * This routine initiates multitasking. It is invoked only as + * part of initialization and its invocation is the last act of + * the non-multitasking part of the system initialization. + */ +void _Thread_Start_multitasking( void ); + +/** + * This routine is responsible for transferring control of the + * processor from the executing thread to the heir thread. As part + * of this process, it is responsible for the following actions: + * + * + saving the context of the executing thread + * + restoring the context of the heir thread + * + dispatching any signals for the resulting executing thread + */ +void _Thread_Dispatch( void ); + +/** + * Allocate the requested stack space for the thread. + * return the actual size allocated after any adjustment + * or return zero if the allocation failed. + * Set the Start.stack field to the address of the stack + */ + +size_t _Thread_Stack_Allocate( + Thread_Control *the_thread, + size_t stack_size +); + +/** + * Deallocate the Thread's stack. + */ +void _Thread_Stack_Free( + Thread_Control *the_thread +); + +/** + * This routine initializes the specified the thread. It allocates + * all memory associated with this thread. It completes by adding + * the thread to the local object table so operations on this + * thread id are allowed. + * + * @note If stack_area is NULL, it is allocated from the workspace. + * + * @note If the stack is allocated from the workspace, then it is + * guaranteed to be of at least minimum size. + */ +bool _Thread_Initialize( + Objects_Information *information, + Thread_Control *the_thread, + void *stack_area, + size_t stack_size, + bool is_fp, + Priority_Control priority, + bool is_preemptible, + Thread_CPU_budget_algorithms budget_algorithm, + Thread_CPU_budget_algorithm_callout budget_callout, + uint32_t isr_level, + Objects_Name name +); + +/** + * This routine initializes the executable information for a thread + * and makes it ready to execute. After this routine executes, the + * thread competes with all other threads for CPU time. + */ +bool _Thread_Start( + Thread_Control *the_thread, + Thread_Start_types the_prototype, + void *entry_point, + void *pointer_argument, + Thread_Entry_numeric_type numeric_argument +); + +/** + * This support routine restarts the specified task in a way that the + * next time this thread executes, it will begin execution at its + * original starting point. + * + * TODO: multiple task arg profiles + */ +bool _Thread_Restart( + Thread_Control *the_thread, + void *pointer_argument, + Thread_Entry_numeric_type numeric_argument +); + +/** + * This routine resets a thread to its initial state but does + * not restart it. + */ +void _Thread_Reset( + Thread_Control *the_thread, + void *pointer_argument, + Thread_Entry_numeric_type numeric_argument +); + +/** + * This routine frees all memory associated with the specified + * thread and removes it from the local object table so no further + * operations on this thread are allowed. + */ +void _Thread_Close( + Objects_Information *information, + Thread_Control *the_thread +); + +/** + * This routine removes any set states for the_thread. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + */ +void _Thread_Ready( + Thread_Control *the_thread +); + +/** + * This routine clears the indicated STATES for the_thread. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + */ +void _Thread_Clear_state( + Thread_Control *the_thread, + States_Control state +); + +/** + * This routine sets the indicated states for the_thread. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + */ +void _Thread_Set_state( + Thread_Control *the_thread, + States_Control state +); + +/** + * This routine sets the TRANSIENT state for the_thread. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + */ +void _Thread_Set_transient( + Thread_Control *the_thread +); + +/** + * This routine is invoked as part of processing each clock tick. + * It is responsible for determining if the current thread allows + * timeslicing and, if so, when its timeslice expires. + */ +void _Thread_Tickle_timeslice( void ); + +/** + * This routine initializes the context of the_thread to its + * appropriate starting state. + */ +void _Thread_Load_environment( + Thread_Control *the_thread +); + +/** + * This routine is the wrapper function for all threads. It is + * the starting point for all threads. The user provided thread + * entry point is invoked by this routine. Operations + * which must be performed immediately before and after the user's + * thread executes are found here. + */ +void _Thread_Handler( void ); + +/** + * This routine is invoked when a thread must be unblocked at the + * end of a time based delay (i.e. wake after or wake when). + */ +void _Thread_Delay_ended( + Objects_Id id, + void *ignored +); + +/** + * This routine changes the current priority of the_thread to + * new_priority. It performs any necessary scheduling operations + * including the selection of a new heir thread. + */ +void _Thread_Change_priority ( + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it +); + +/** + * This routine updates the priority related fields in the_thread + * control block to indicate the current priority is now new_priority. + */ +void _Thread_Set_priority( + Thread_Control *the_thread, + Priority_Control new_priority +); + +/** + * This routine updates the related suspend fields in the_thread + * control block to indicate the current nested level. + */ +#define _Thread_Suspend( _the_thread ) \ + _Thread_Set_state( _the_thread, STATES_SUSPENDED ) + +/** + * This routine updates the related suspend fields in the_thread + * control block to indicate the current nested level. A force + * parameter of true will force a resume and clear the suspend count. + */ +#define _Thread_Resume( _the_thread ) \ + _Thread_Clear_state( _the_thread, STATES_SUSPENDED ) + +#if (CPU_PROVIDES_IDLE_THREAD_BODY == FALSE) +/** + * This routine is the body of the system idle thread. + * + * NOTE: This routine is actually instantiated by confdefs.h when needed. + */ +void *_Thread_Idle_body( + uintptr_t ignored +); +#endif + +/** This defines the type for a method which operates on a single thread. + */ +typedef void (*rtems_per_thread_routine)( Thread_Control * ); + +/** + * This routine iterates over all threads regardless of API and + * invokes the specified routine. + */ +void rtems_iterate_over_all_threads( + rtems_per_thread_routine routine +); + +/** + * This function maps thread IDs to thread control + * blocks. If ID corresponds to a local thread, then it + * returns the_thread control pointer which maps to ID + * and location is set to OBJECTS_LOCAL. If the thread ID is + * global and resides on a remote node, then location is set + * to OBJECTS_REMOTE, and the_thread is undefined. + * Otherwise, location is set to OBJECTS_ERROR and + * the_thread is undefined. + * + * @note The performance of many RTEMS services depends upon + * the quick execution of the "good object" path in this + * routine. If there is a possibility of saving a few + * cycles off the execution time, this routine is worth + * further optimization attention. + */ +Thread_Control *_Thread_Get ( + Objects_Id id, + Objects_Locations *location +); + +/** + * @brief Cancel a blocking operation due to ISR + * + * This method is used to cancel a blocking operation that was + * satisfied from an ISR while the thread executing was in the + * process of blocking. + * + * @param[in] sync_state is the synchronization state + * @param[in] the_thread is the thread whose blocking is canceled + * @param[in] level is the previous ISR disable level + * + * @note This is a rare routine in RTEMS. It is called with + * interrupts disabled and only when an ISR completed + * a blocking condition in process. + */ +void _Thread_blocking_operation_Cancel( + Thread_blocking_operation_States sync_state, + Thread_Control *the_thread, + ISR_Level level +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/thread.inl> +#endif +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/threadmp.h> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/threadmp.h b/cpukit/score/include/rtems/score/threadmp.h new file mode 100644 index 0000000000..f3a3840f5d --- /dev/null +++ b/cpukit/score/include/rtems/score/threadmp.h @@ -0,0 +1,88 @@ +/** + * @file rtems/score/threadmp.h + * + * This include file contains the specification for all routines + * and data specific to the multiprocessing portion of the thread package. + */ + +/* + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_THREADMP_H +#define _RTEMS_SCORE_THREADMP_H + +/** + * @defgroup ScoreThreadMP Thread Handler Multiprocessing Support + * + * This handler encapsulates functionality which is related to managing + * threads in a multiprocessor system configuration. This handler must + * manage proxies which represent remote threads blocking on local + * operations. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief _Thread_MP_Handler_initialization + * + * This routine initializes the multiprocessing portion of the Thread Handler. + */ +void _Thread_MP_Handler_initialization ( + uint32_t maximum_proxies +); + +/** @brief _Thread_MP_Allocate_proxy + * + * This allocates a proxy control block from + * the inactive chain of free proxy control blocks. + * + * @note This function returns a thread control pointer + * because proxies are substitutes for remote threads. + */ +Thread_Control *_Thread_MP_Allocate_proxy ( + States_Control the_state +); + +/** @brief _Thread_MP_Find_proxy + * + * This function removes the proxy control block for the specified + * id from the active chain of proxy control blocks. + */ +Thread_Control *_Thread_MP_Find_proxy ( + Objects_Id the_id +); + +/** @brief Active Proxy Set + * + * The following chain is used to manage the active set proxies. + */ +SCORE_EXTERN Chain_Control _Thread_MP_Active_proxies; + +/** @brief Inactive Proxy Set + * + * The following chain is used to manage the inactive set of proxies. + */ +SCORE_EXTERN Chain_Control _Thread_MP_Inactive_proxies; + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/threadmp.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h new file mode 100644 index 0000000000..357bbf713c --- /dev/null +++ b/cpukit/score/include/rtems/score/threadq.h @@ -0,0 +1,300 @@ +/** + * @file rtems/score/threadq.h + * + * This include file contains all the constants and structures associated + * with the manipulation of objects. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_THREADQ_H +#define _RTEMS_SCORE_THREADQ_H + +/** + * @defgroup ScoreThreadQ Thread Queue Handler + * + * This handler encapsulates functionality related to managing sets of threads + * blocked waiting for resources. + */ +/**@{*/ + +#include <rtems/score/tqdata.h> + +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Constant for indefinite wait. + */ +#define THREAD_QUEUE_WAIT_FOREVER WATCHDOG_NO_TIMEOUT + +/** + * The following type defines the callout used when a remote task + * is extracted from a local thread queue. + */ +typedef void ( *Thread_queue_Flush_callout )( + Thread_Control * + ); + +/** + * + * The following type defines the callout used for timeout processing + * methods. + */ +typedef void ( *Thread_queue_Timeout_callout )( + Objects_Id, + void * + ); + +/** @brief Thread queue Dequeue + * + * This function returns a pointer to a thread waiting on + * the_thread_queue. The selection of this thread is based on + * the discipline of the_thread_queue. If no threads are waiting + * on the_thread_queue, then NULL is returned. + */ +Thread_Control *_Thread_queue_Dequeue( + Thread_queue_Control *the_thread_queue +); + +/** @brief Thread queue Enqueue Wrapper + * + * This routine enqueues the currently executing thread on + * the_thread_queue with an optional timeout. + */ +#define _Thread_queue_Enqueue( _the_thread_queue, _timeout ) \ + _Thread_queue_Enqueue_with_handler( \ + _the_thread_queue, \ + _timeout, \ + _Thread_queue_Timeout ) + + +/** @brief Thread queue Enqueue + * + * This routine enqueues the currently executing thread on + * the_thread_queue with an optional timeout. + */ +void _Thread_queue_Enqueue_with_handler( + Thread_queue_Control* the_thread_queue, + Watchdog_Interval timeout, + Thread_queue_Timeout_callout handler +); + +/** + * @brief Thread queue Requeue + * + * This routine is invoked when a thread changes priority and is + * blocked on a thread queue. If the queue is priority ordered, + * the_thread is removed from the_thread_queue and reinserted using + * its new priority. This method has no impact on the state of the_thread + * or of any timeouts associated with this blocking. + */ +void _Thread_queue_Requeue( + Thread_queue_Control *the_thread_queue, + Thread_Control *the_thread +); + +/** @brief Thread queue Extract + * + * This routine removes the_thread from the_thread_queue + * and cancels any timeouts associated with this blocking. + */ +void _Thread_queue_Extract( + Thread_queue_Control *the_thread_queue, + Thread_Control *the_thread +); + +/** @brief Thread queue Extract with proxy + * + * This routine extracts the_thread from the_thread_queue + * and ensures that if there is a proxy for this task on + * another node, it is also dealt with. + */ +bool _Thread_queue_Extract_with_proxy( + Thread_Control *the_thread +); + +/** @brief Thread queue First + * + * This function returns a pointer to the "first" thread + * on the_thread_queue. The "first" thread is selected + * based on the discipline of the_thread_queue. + */ +Thread_Control *_Thread_queue_First( + Thread_queue_Control *the_thread_queue +); + +/** @brief Thread queue Flush + * + * This routine unblocks all threads blocked on the_thread_queue + * and cancels any associated timeouts. + */ +void _Thread_queue_Flush( + Thread_queue_Control *the_thread_queue, + Thread_queue_Flush_callout remote_extract_callout, + uint32_t status +); + +/** @brief Thread queue Initialize + * + * This routine initializes the_thread_queue based on the + * discipline indicated in attribute_set. The state set on + * threads which block on the_thread_queue is state. + */ +void _Thread_queue_Initialize( + Thread_queue_Control *the_thread_queue, + Thread_queue_Disciplines the_discipline, + States_Control state, + uint32_t timeout_status +); + +/** @brief Thread queue Dequeue priority + * + * This function returns a pointer to the highest priority + * thread waiting on the_thread_queue. If no threads are waiting + * on the_thread_queue, then NULL is returned. + */ +Thread_Control *_Thread_queue_Dequeue_priority( + Thread_queue_Control *the_thread_queue +); + +/** @brief Thread queue Enqueue priority + * + * This routine enqueues the currently executing thread on + * the_thread_queue with an optional timeout using the + * priority discipline. + */ +Thread_blocking_operation_States _Thread_queue_Enqueue_priority ( + Thread_queue_Control *the_thread_queue, + Thread_Control *the_thread, + ISR_Level *level_p +); + +/** @brief Thread queue Extract priority Helper + * + * This routine removes the_thread from the_thread_queue + * and cancels any timeouts associated with this blocking. + */ +void _Thread_queue_Extract_priority_helper( + Thread_queue_Control *the_thread_queue, + Thread_Control *the_thread, + bool requeuing +); + +/** + * @brief Thread queue Extract priority + * + * This macro wraps the underlying call and hides the requeuing argument. + */ + +#define _Thread_queue_Extract_priority( _the_thread_queue, _the_thread ) \ + _Thread_queue_Extract_priority_helper( _the_thread_queue, _the_thread, false ) + + +/** @brief Thread queue First priority + * + * This function returns a pointer to the "first" thread + * on the_thread_queue. The "first" thread is the highest + * priority thread waiting on the_thread_queue. + */ +Thread_Control *_Thread_queue_First_priority( + Thread_queue_Control *the_thread_queue +); + +/** @brief Thread queue Dequeue FIFO + * + * This function returns a pointer to the thread which has + * been waiting the longest on the_thread_queue. If no + * threads are waiting on the_thread_queue, then NULL is returned. + */ +Thread_Control *_Thread_queue_Dequeue_fifo( + Thread_queue_Control *the_thread_queue +); + +/** @brief Thread queue Enqueue FIFO + * + * This routine enqueues the currently executing thread on + * the_thread_queue with an optional timeout using the + * FIFO discipline. + */ +Thread_blocking_operation_States _Thread_queue_Enqueue_fifo ( + Thread_queue_Control *the_thread_queue, + Thread_Control *the_thread, + ISR_Level *level_p +); + +/** @brief Thread queue Extract FIFO + * + * This routine removes the_thread from the_thread_queue + * and cancels any timeouts associated with this blocking. + */ +void _Thread_queue_Extract_fifo( + Thread_queue_Control *the_thread_queue, + Thread_Control *the_thread +); + +/** @brief Thread queue First FIFO + * + * This function returns a pointer to the "first" thread + * on the_thread_queue. The first thread is the thread + * which has been waiting longest on the_thread_queue. + */ +Thread_Control *_Thread_queue_First_fifo( + Thread_queue_Control *the_thread_queue +); + +/** @brief Thread queue timeout + * + * This routine is invoked when a task's request has not + * been satisfied after the timeout interval specified to + * enqueue. The task represented by ID will be unblocked and + * its status code will be set in it's control block to indicate + * that a timeout has occurred. + */ +void _Thread_queue_Timeout ( + Objects_Id id, + void *ignored +); + +/** + * @brief Process Thread Queue Timeout + * + * This is a shared helper routine which makes it easier to have multiple + * object class specific timeout routines. + * + * @param[in] the_thread is the thread to extract + * + * @note This method assumes thread dispatching is disabled + * and is expected to be called via the processing of + * a clock tick. + */ +void _Thread_queue_Process_timeout( + Thread_Control *the_thread +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/threadq.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/threadsync.h b/cpukit/score/include/rtems/score/threadsync.h new file mode 100644 index 0000000000..9b5e3dee96 --- /dev/null +++ b/cpukit/score/include/rtems/score/threadsync.h @@ -0,0 +1,58 @@ +/** + * @file rtems/score/threadsync.h + * + * This include file contains all constants and structures associated + * with synchronizing a thread blocking operation with potential + * actions in an ISR. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_THREAD_SYNC_H +#define _RTEMS_SCORE_THREAD_SYNC_H + +/** + * @defgroup ScoreThreadSync Thread Blocking Operation Synchronization Handler + * + * This handler encapsulates functionality related to the management of + * synchronization critical sections during blocking operations. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The following enumerated types indicate what happened while the thread + * blocking was in the synchronization window. + */ +typedef enum { + THREAD_BLOCKING_OPERATION_SYNCHRONIZED, + THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED, + THREAD_BLOCKING_OPERATION_TIMEOUT, + THREAD_BLOCKING_OPERATION_SATISFIED +} Thread_blocking_operation_States; + +/* + * Operations require a thread pointer so they are prototyped + * in thread.h + */ + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/timespec.h b/cpukit/score/include/rtems/score/timespec.h new file mode 100644 index 0000000000..06bbf4f373 --- /dev/null +++ b/cpukit/score/include/rtems/score/timespec.h @@ -0,0 +1,247 @@ +/** + * @file rtems/score/timespec.h + * + * This include file contains helpers for manipulating timespecs. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_TIMESPEC_H +#define _RTEMS_SCORE_TIMESPEC_H + +/** + * @defgroup Timespec Helpers + * + * This handler encapsulates functionality related to manipulating + * POSIX struct timespecs. + */ +/**@{*/ + +#include <stdbool.h> /* bool */ +#include <stdint.h> /* uint32_t */ +#include <time.h> /* struct timespec */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Set Timespec to Seconds Nanosecond + * + * This method sets the timespec to the specified seconds and nanoseconds + * value. + * + * @param[in] _time points to the timespec instance to validate. + * @param[in] _seconds is the seconds portion of the timespec + * @param[in] _nanoseconds is the nanoseconds portion of the timespec + */ +#define _Timespec_Set( _time, _seconds, _nanoseconds ) \ + do { \ + (_time)->tv_sec = (_seconds); \ + (_time)->tv_nsec = (_nanoseconds); \ + } while (0) + +/** @brief Zero Timespec + * + * This method sets the timespec to zero. + * value. + * + * @param[in] _time points to the timespec instance to zero. + */ +#define _Timespec_Set_to_zero( _time ) \ + do { \ + (_time)->tv_sec = 0; \ + (_time)->tv_nsec = 0; \ + } while (0) + +/** @brief Get Seconds Portion of Timespec + * + * This method returns the seconds portion of the specified timespec + * + * @param[in] _time points to the timespec + * + * @return The seconds portion of @a _time. + */ +#define _Timespec_Get_seconds( _time ) \ + ((_time)->tv_sec) + +/** @brief Get Nanoseconds Portion of Timespec + * + * This method returns the nanoseconds portion of the specified timespec + * + * @param[in] _time points to the timespec + * + * @return The nanoseconds portion of @a _time. + */ +#define _Timespec_Get_nanoseconds( _time ) \ + ((_time)->tv_nsec) + +/** @brief Is Timespec Valid + * + * This method determines the validity of a timespec. + * + * @param[in] time is the timespec instance to validate. + * + * @return This method returns true if @a time is valid and + * false otherwise. + */ +bool _Timespec_Is_valid( + const struct timespec *time +); + +/** @brief Timespec Less Than Operator + * + * This method is the less than operator for timespecs. + * + * @param[in] lhs is the left hand side timespec + * @param[in] rhs is the right hand side timespec + * + * @return This method returns true if @a lhs is less than the @a rhs and + * false otherwise. + */ +bool _Timespec_Less_than( + const struct timespec *lhs, + const struct timespec *rhs +); + +/** @brief Timespec Greater Than Operator + * + * This method is the greater than operator for timespecs. + * + * @param[in] lhs is the left hand side timespec + * @param[in] rhs is the right hand side timespec + * + * @return This method returns true if @a lhs is greater than the @a rhs and + * false otherwise. + */ +bool _Timespec_Greater_than( + const struct timespec *lhs, + const struct timespec *rhs +); + +/** @brief Timespec equal to Operator + * + * This method is the is equal to than operator for timespecs. + * + * @param[in] lhs is the left hand side timespec + * @param[in] rhs is the right hand side timespec + * + * @return This method returns true if @a lhs is equal to @a rhs and + * false otherwise. + */ +#define _Timespec_Equal_to( lhs, rhs ) \ + ( ((lhs)->tv_sec == (rhs)->tv_sec) && \ + ((lhs)->tv_nsec == (rhs)->tv_nsec) \ + ) + +/** @brief Add to a Timespec + * + * This routine adds two timespecs. The second argument is added + * to the first. + * + * @param[in] time is the base time to be added to + * @param[in] add is the timespec to add to the first argument + * + * @return This method returns the number of seconds @a time increased by. + */ +uint32_t _Timespec_Add_to( + struct timespec *time, + const struct timespec *add +); + +/** @brief Convert Timespec to Number of Ticks + * + * This routine convert the @a time timespec to the corresponding number + * of clock ticks. + * + * @param[in] time is the time to be converted + * + * @return This method returns the number of ticks computed. + */ +uint32_t _Timespec_To_ticks( + const struct timespec *time +); + +/** @brief Convert Ticks to Timespec + * + * This routine converts the @a ticks value to the corresponding + * timespec format @a time. + * + * @param[in] time is the timespec format time result + * @param[in] ticks is the number of ticks to convert + */ +void _Timespec_From_ticks( + uint32_t ticks, + struct timespec *time +); + +/** @brief Subtract Two Timespec + * + * This routine subtracts two timespecs. @a result is set to + * @a end - @a start. + * + * @param[in] start is the starting time + * @param[in] end is the ending time + * @param[in] result is the difference between starting and ending time. + * + * @return This method fills in @a result. + */ +void _Timespec_Subtract( + const struct timespec *start, + const struct timespec *end, + struct timespec *result +); + +/** @brief Divide Timespec By Integer + * + * This routine divides a timespec by an integer value. The expected + * use is to assist in benchmark calculations where you typically + * divide a duration by a number of iterations. + * + * @param[in] time is the total + * @param[in] iterations is the number of iterations + * @param[in] result is the average time. + * + * @return This method fills in @a result. + */ +void _Timespec_Divide_by_integer( + const struct timespec *time, + uint32_t iterations, + struct timespec *result +); + +/** @brief Divide Timespec + * + * This routine divides a timespec by another timespec. The + * intended use is for calculating percentages to three decimal points. + * + * @param[in] lhs is the left hand number + * @param[in] rhs is the right hand number + * @param[in] ival_percentage is the integer portion of the average + * @param[in] fval_percentage is the thousandths of percentage + * + * @return This method fills in @a result. + */ +void _Timespec_Divide( + const struct timespec *lhs, + const struct timespec *rhs, + uint32_t *ival_percentage, + uint32_t *fval_percentage +); + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/timestamp.h b/cpukit/score/include/rtems/score/timestamp.h new file mode 100644 index 0000000000..6789e83e93 --- /dev/null +++ b/cpukit/score/include/rtems/score/timestamp.h @@ -0,0 +1,426 @@ +/** + * @file rtems/score/timestamp.h + * + * This include file contains helpers for manipulating timestamps. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_TIMESTAMP_H +#define _RTEMS_SCORE_TIMESTAMP_H + +/** + * @defgroup SuperCore Timestamp + * + * This handler encapsulates functionality related to manipulating + * SuperCore Timestamps. SuperCore Timestamps may be used to + * represent time of day, uptime, or intervals. + * + * The key attribute of the SuperCore Timestamp handler is that it + * is a completely opaque handler. There can be multiple implementations + * of the required functionality and with a recompile, RTEMS can use + * any implementation. It is intended to be a simple wrapper. + * + * This handler can be implemented as either struct timespec or + * unsigned64 bit numbers. The use of a wrapper class allows the + * the implementation of timestamps to change on a per architecture + * basis. This is an important option as the performance of this + * handler is critical. + */ +/**@{*/ + +#include <rtems/score/timespec.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NOTE: Eventually each port should select what it should use!!! + * + * These control which implementation of SuperCore Timestamp is used. + * + * if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + * struct timespec is used + * else if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) + * int64_t is used + * + * When int64_t is used, then + * if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + * the methods are inlined + * else + * the methods are NOT inlined + * + * Performance of int64_t versus struct timespec + * ============================================= + * + * On PowerPC/psim, inlined int64_t saves ~50 instructions on each + * _Thread_Dispatch operation which results in a context switch. + * This works out to be about 10% faster dispatches and 7.5% faster + * blocking semaphore obtains. The following numbers are in instructions + * and from tm02 and tm26. + * + * timespec int64 inlined int64 + * dispatch: 446 446 400 + * blocking sem obtain: 627 626 581 + * + * On SPARC/sis, inlined int64_t shows the same percentage gains. + * The following numbers are in microseconds and from tm02 and tm26. + * + * timespec int64 inlined int64 + * dispatch: 59 61 53 + * blocking sem obtain: 98 100 92 + * + * Inlining appears to have a tendency to increase the size of + * some executables. + * Not inlining reduces the execution improvement but does not seem to + * be an improvement on the PowerPC and SPARC. The struct timespec + * and the executables with int64 not inlined are about the same size. + * + * Once there has some analysis of which algorithm and configuration + * is best suited to each target, these defines should be moved to + * the appropriate score/cpu cpu.h file. In the meantime, it is + * appropriate to select an implementation here using CPU macros. + */ + +#define CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC +/* +#define CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 +#define CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE +*/ + +/* + * Verify something is defined. + */ +#if !defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) && \ + !defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) + #error "No SuperCore Timestamp implementation selected." +#endif + +/* + * Verify that more than one is not defined. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) && \ + defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) + #error "Too many SuperCore Timestamp implementations selected." +#endif + +/** + * Include any implementation specific header files + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) + #include <rtems/score/timestamp64.h> +#endif + +/** + * Define the Timestamp control type. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + typedef struct timespec Timestamp_Control; +#else + typedef Timestamp64_Control Timestamp_Control; +#endif + +/** @brief Set Timestamp to Seconds Nanosecond + * + * This method sets the timestamp to the specified seconds and nanoseconds + * value. + * + * @param[in] _time points to the timestamp instance to validate. + * @param[in] _seconds is the seconds portion of the timestamp + * @param[in] _nanoseconds is the nanoseconds portion of the timestamp + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Set( _time, _seconds, _nanoseconds ) \ + _Timespec_Set( _time, _seconds, _nanoseconds ) +#else + #define _Timestamp_Set( _time, _seconds, _nanoseconds ) \ + _Timestamp64_Set( _time, _seconds, _nanoseconds ) +#endif + +/** @brief Zero Timestamp + * + * This method sets the timestamp to zero. + * value. + * + * @param[in] _time points to the timestamp instance to zero. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Set_to_zero( _time ) \ + _Timespec_Set_to_zero( _time ) +#else + #define _Timestamp_Set_to_zero( _time ) \ + _Timestamp64_Set_to_zero( _time ) +#endif + +/** @brief Is Timestamp Valid + * + * This method determines the validity of a timestamp. + * + * @param[in] _time points to the timestamp instance to validate. + * + * @return This method returns true if @a time is valid and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Is_valid( _time ) \ + _Timespec_Is_valid( _time ) +#else + #define _Timestamp_Is_valid( _time ) \ + _Timestamp64_Is_valid( _time ) +#endif + +/** @brief Timestamp Less Than Operator + * + * This method is the less than operator for timestamps. + * + * @param[in] _lhs points to the left hand side timestamp + * @param[in] _rhs points to the right hand side timestamp + * + * @return This method returns true if @a _lhs is less than the @a _rhs and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Less_than( _lhs, _rhs ) \ + _Timespec_Less_than( _lhs, _rhs ) +#else + #define _Timestamp_Less_than( _lhs, _rhs ) \ + _Timestamp64_Less_than( _lhs, _rhs ) +#endif + +/** @brief Timestamp Greater Than Operator + * + * This method is the greater than operator for timestamps. + * + * @param[in] _lhs points to the left hand side timestamp + * @param[in] _rhs points to the right hand side timestamp + * + * @return This method returns true if @a _lhs is greater than the @a _rhs and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Greater_than( _lhs, _rhs ) \ + _Timespec_Greater_than( _lhs, _rhs ) +#else + #define _Timestamp_Greater_than( _lhs, _rhs ) \ + _Timestamp64_Greater_than( _lhs, _rhs ) +#endif + +/** @brief Timestamp equal to Operator + * + * This method is the is equal to than operator for timestamps. + * + * @param[in] _lhs points to the left hand side timestamp + * @param[in] _rhs points to the right hand side timestamp + * + * @return This method returns true if @a _lhs is equal to @a _rhs and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Equal_to( _lhs, _rhs ) \ + _Timespec_Equal_to( _lhs, _rhs ) +#else + #define _Timestamp_Equal_to( _lhs, _rhs ) \ + _Timestamp64_Equal_to( _lhs, _rhs ) +#endif + +/** @brief Add to a Timestamp + * + * This routine adds two timestamps. The second argument is added + * to the first. + * + * @param[in] _time points to the base time to be added to + * @param[in] _add points to the timestamp to add to the first argument + * + * @return This method returns the number of seconds @a time increased by. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Add_to( _time, _add ) \ + _Timespec_Add_to( _time, _add ) +#else + #define _Timestamp_Add_to( _time, _add ) \ + _Timestamp64_Add_to( _time, _add ) +#endif + +/** @brief Add to a Timestamp (At Clock Tick) + * + * This routine adds two timestamps. The second argument is added + * to the first. + * + * @node This routine places a special requirement on the addition + * operation. It must return the number of units that the + * seconds field changed as the result of the addition. Since this + * operation is ONLY used as part of processing a clock tick, + * it is generally safe to assume that only one second changed. + * + * @param[in] _time points to the base time to be added to + * @param[in] _add points to the timestamp to add to the first argument + * + * @return This method returns the number of seconds @a time increased by. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Add_to_at_tick( _time, _add ) \ + _Timespec_Add_to( _time, _add ) +#else + #define _Timestamp_Add_to_at_tick( _time, _add ) \ + _Timestamp64_Add_to_at_tick( _time, _add ) +#endif + +/** @brief Convert Timestamp to Number of Ticks + * + * This routine convert the @a time timestamp to the corresponding number + * of clock ticks. + * + * @param[in] _time points to the time to be converted + * + * @return This method returns the number of ticks computed. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_To_ticks( _time ) \ + _Timespec_To_ticks( _time ) +#else + #define _Timestamp_To_ticks( _time ) \ + _Timestamp64_To_ticks( _time ) +#endif + +/** @brief Convert Ticks to Timestamp + * + * This routine converts the @a _ticks value to the corresponding + * timestamp format @a _time. + * + * @param[in] _time points to the timestamp format time result + * @param[in] _ticks points to the number of ticks to be filled in + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_From_ticks( _ticks, _time ) \ + _Timespec_From_ticks( _ticks, _time ) +#else + #define _Timestamp_From_ticks( _ticks, _time ) \ + _Timestamp64_From_ticks( _ticks, _time ) +#endif + +/** @brief Subtract Two Timestamp + * + * This routine subtracts two timestamps. @a result is set to + * @a end - @a start. + * + * @param[in] _start points to the starting time + * @param[in] _end points to the ending time + * @param[in] _result points to the difference between + * starting and ending time. + * + * @return This method fills in @a _result. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Subtract( _start, _end, _result ) \ + _Timespec_Subtract( _start, _end, _result ) +#else + #define _Timestamp_Subtract( _start, _end, _result ) \ + _Timestamp64_Subtract( _start, _end, _result ) +#endif + +/** @brief Divide Timestamp By Integer + * + * This routine divides a timestamp by an integer value. The expected + * use is to assist in benchmark calculations where you typically + * divide a duration by a number of iterations. + * + * @param[in] _time points to the total + * @param[in] _iterations is the number of iterations + * @param[in] _result points to the average time. + * + * @return This method fills in @a result. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Divide_by_integer( _time, _iterations, _result ) \ + _Timespec_Divide_by_integer(_time, _iterations, _result ) +#else + #define _Timestamp_Divide_by_integer( _time, _iterations, _result ) \ + _Timestamp64_Divide_by_integer( _time, _iterations, _result ) +#endif + +/** @brief Divide Timestamp + * + * This routine divides a timestamp by another timestamp. The + * intended use is for calculating percentages to three decimal points. + * + * @param[in] _lhs points to the left hand number + * @param[in] _rhs points to the right hand number + * @param[in] _ival_percentage points to the integer portion of the average + * @param[in] _fval_percentage points to the thousandths of percentage + * + * @return This method fills in @a result. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Divide( _lhs, _rhs, _ival_percentage, _fval_percentage ) \ + _Timespec_Divide( _lhs, _rhs, _ival_percentage, _fval_percentage ) +#else + #define _Timestamp_Divide( _lhs, _rhs, _ival_percentage, _fval_percentage ) \ + _Timestamp64_Divide( _lhs, _rhs, _ival_percentage, _fval_percentage ) +#endif + +/** @brief Get Seconds Portion of Timestamp + * + * This method returns the seconds portion of the specified timestamp + * + * @param[in] _time points to the timestamp + * + * @return The seconds portion of @a _time. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Get_seconds( _time ) \ + _Timespec_Get_seconds( _time ) +#else + #define _Timestamp_Get_seconds( _time ) \ + _Timestamp64_Get_seconds( _time ) +#endif + +/** @brief Get Nanoseconds Portion of Timestamp + * + * This method returns the nanoseconds portion of the specified timestamp + * + * @param[in] _time points to the timestamp + * + * @return The nanoseconds portion of @a _time. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + #define _Timestamp_Get_nanoseconds( _time ) \ + _Timespec_Get_nanoseconds( _time ) +#else + #define _Timestamp_Get_nanoseconds( _time ) \ + _Timestamp64_Get_nanoseconds( _time ) +#endif + +/** @brief Convert Timestamp to struct timespec + * + * This method returns the seconds portion of the specified timestamp + * + * @param[in] _timestamp points to the timestamp + * @param[in] _timespec points to the timespec + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_STRUCT_SPEC) + /* in this case we know they are the same type so use simple assignment */ + #define _Timestamp_To_timespec( _timestamp, _timespec ) \ + *(_timespec) = *(_timestamp) +#else + #define _Timestamp_To_timespec( _timestamp, _timespec ) \ + _Timestamp64_To_timespec( _timestamp, _timespec ) +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/timestamp64.h b/cpukit/score/include/rtems/score/timestamp64.h new file mode 100644 index 0000000000..3b4300c6fa --- /dev/null +++ b/cpukit/score/include/rtems/score/timestamp64.h @@ -0,0 +1,370 @@ +/** + * @file rtems/score/timestamp64.h + * + * This include file contains helpers for manipulating + * 64-bit integer timestamps. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_TIMESTAMP64_H +#define _RTEMS_SCORE_TIMESTAMP64_H + +/** + * @defgroup SuperCore Timestamp64 + * + * This handler encapsulates functionality related to manipulating + * the 64 bit integer implementation of SuperCore Timestamps. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This .h file is not for general use. It is an alternative + * implementation of Timestamps and should only be used that way. + */ +#ifndef _RTEMS_SCORE_TIMESTAMP_H + #error "Should only be included by rtems/score/timestamp.h" +#endif + +/* + * Verify something is defined. + */ +#if !defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) + #error "SuperCore Timestamp64 implementation included but not defined." +#endif + +/** + * Define the Timestamp control type. + */ +typedef int64_t Timestamp64_Control; + +/** @brief Set Timestamp to Seconds Nanosecond + * + * This method sets the timestamp to the specified seconds and nanoseconds + * value. + * + * @param[in] _time points to the timestamp instance to validate. + * @param[in] _seconds is the seconds portion of the timestamp + * @param[in] _nanoseconds is the nanoseconds portion of the timestamp + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Set( _time, _seconds, _nanoseconds ) \ + do { \ + *(_time) = ((int64_t)_seconds * 1000000000); \ + *(_time) += (int64_t)(_nanoseconds); \ + } while (0) +#else + void _Timestamp64_Set( + Timestamp64_Control *_time, + long _seconds, + long _nanoseconds + ); +#endif + +/** @brief Zero Timestamp + * + * This method sets the timestamp to zero. + * value. + * + * @param[in] _time points to the timestamp instance to zero. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Set_to_zero( _time ) \ + *(_time) = 0 +#else + void _Timestamp64_Set_to_zero( + Timestamp64_Control *_time + ); +#endif + +/** @brief Is Timestamp Valid + * + * This method determines the validity of a timestamp. + * + * @param[in] _time points to the timestamp instance to validate. + * + * @return This method returns true if @a time is valid and + * false otherwise. + */ +#define _Timestamp64_Is_valid( _time ) \ + (1) + +/** @brief Timestamp Less Than Operator + * + * This method is the less than operator for timestamps. + * + * @param[in] _lhs points to the left hand side timestamp + * @param[in] _rhs points to the right hand side timestamp + * + * @return This method returns true if @a _lhs is less than the @a _rhs and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Less_than( _lhs, _rhs ) \ + (*(_lhs) < *(_rhs)) +#else + bool _Timestamp64_Less_than( + Timestamp64_Control *_lhs, + Timestamp64_Control *_rhs + ); +#endif + +/** @brief Timestamp Greater Than Operator + * + * This method is the greater than operator for timestamps. + * + * @param[in] _lhs points to the left hand side timestamp + * @param[in] _rhs points to the right hand side timestamp + * + * @return This method returns true if @a _lhs is greater than the @a _rhs and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Greater_than( _lhs, _rhs ) \ + (*(_lhs) > *(_rhs)) +#else + bool _Timestamp64_Greater_than( + Timestamp64_Control *_lhs, + Timestamp64_Control *_rhs + ); +#endif + +/** @brief Timestamp equal to Operator + * + * This method is the is equal to than operator for timestamps. + * + * @param[in] _lhs points to the left hand side timestamp + * @param[in] _rhs points to the right hand side timestamp + * + * @return This method returns true if @a _lhs is equal to @a _rhs and + * false otherwise. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Equal_to( _lhs, _rhs ) \ + (*(_lhs) == *(_rhs)) +#else + bool _Timestamp64_Equal_to( + Timestamp64_Control *_lhs, + Timestamp64_Control *_rhs + ); +#endif + +/** @brief Add to a Timestamp + * + * This routine adds two timestamps. The second argument is added + * to the first. + * + * @param[in] _time points to the base time to be added to + * @param[in] _add points to the timestamp to add to the first argument + * + * @return This method returns the number of seconds @a time increased by. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Add_to( _time, _add ) \ + *(_time) += *(_add) +#else + void _Timestamp64_Add_to( + Timestamp64_Control *_time, + Timestamp64_Control *_add + ); +#endif + +/** @brief Add to a Timestamp (At Clock Tick) + * + * This routine adds two timestamps. The second argument is added + * to the first. + * + * @node This routine places a special requirement on the addition + * operation. It must return the number of units that the + * seconds field changed as the result of the addition. Since this + * operation is ONLY used as part of processing a clock tick, + * it is generally safe to assume that only one second changed. + * + * @param[in] _time points to the base time to be added to + * @param[in] _add points to the timestamp to add to the first argument + * + * @return This method returns the number of seconds @a time increased by. + */ +static inline uint32_t _Timestamp64_Add_to_at_tick( + Timestamp64_Control *_time, + Timestamp64_Control *_add +) +{ + Timestamp64_Control start = *_time / 1000000000; + *_time += *_add; + if ( ((*_time) / 1000000000) != start ) { + return 1; + } + return 0; +} + +/** @brief Convert Timestamp to Number of Ticks + * + * This routine convert the @a time timestamp to the corresponding number + * of clock ticks. + * + * @param[in] _time points to the time to be converted + * + * @return This method returns the number of ticks computed. + */ +uint32_t _Timestamp64_To_ticks( + const Timestamp64_Control *_time +); + +/** @brief Convert Ticks to Timestamp + * + * This routine converts the @a _ticks value to the corresponding + * timestamp format @a _time. + * + * @param[in] _time points to the timestamp format time result + * @param[in] _ticks points to the number of ticks to be filled in + */ +void _Timestamp64_From_ticks( + uint32_t _ticks, + Timestamp64_Control *_time +); + +/** @brief Subtract Two Timestamp + * + * This routine subtracts two timestamps. @a result is set to + * @a end - @a start. + * + * @param[in] _start points to the starting time + * @param[in] _end points to the ending time + * @param[in] _result points to the difference between + * starting and ending time. + * + * @return This method fills in @a _result. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Subtract( _start, _end, _result ) \ + do { \ + *(_result) = *(_end) - *(_start); \ + } while (0) +#else + void _Timestamp64_Subtract( + Timestamp64_Control *_start, + Timestamp64_Control *_end, + Timestamp64_Control *_result + ); +#endif + +/** @brief Divide Timestamp By Integer + * + * This routine divides a timestamp by an integer value. The expected + * use is to assist in benchmark calculations where you typically + * divide a duration by a number of iterations. + * + * @param[in] _time points to the total + * @param[in] _iterations is the number of iterations + * @param[in] _result points to the average time. + * + * @return This method fills in @a result. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Divide_by_integer( _time, _iterations, _result ) \ + do { \ + *(_result) = *(_time) / (_iterations); \ + } while (0) +#else + void _Timestamp64_Divide_by_integer( + Timestamp64_Control *_time, + uint32_t _iterations, + Timestamp64_Control *_result + ); +#endif + +/** @brief Divide Timestamp + * + * This routine divides a timestamp by another timestamp. The + * intended use is for calculating percentages to three decimal points. + * + * @param[in] _lhs points to the left hand number + * @param[in] _rhs points to the right hand number + * @param[in] _ival_percentage points to the integer portion of the average + * @param[in] _fval_percentage points to the thousandths of percentage + * + * @return This method fills in @a result. + */ +void _Timestamp64_Divide( + const Timestamp64_Control *_lhs, + const Timestamp64_Control *_rhs, + uint32_t *_ival_percentage, + uint32_t *_fval_percentage +); + +/** @brief Get Seconds Portion of Timestamp + * + * This method returns the seconds portion of the specified timestamp + * + * @param[in] _time points to the timestamp + * + * @return The seconds portion of @a _time. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Get_seconds( _time ) \ + (*(_time) / 1000000000) +#else + uint32_t _Timestamp64_Get_seconds( + Timestamp64_Control *_time + ); +#endif + +/** @brief Get Nanoseconds Portion of Timestamp + * + * This method returns the nanoseconds portion of the specified timestamp + * + * @param[in] _time points to the timestamp + * + * @return The nanoseconds portion of @a _time. + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_Get_nanoseconds( _time ) \ + (*(_time) % 1000000000) +#else + uint32_t _Timestamp64_Get_nanoseconds( + Timestamp64_Control *_time + ); +#endif + +/** @brief Convert Timestamp to struct timespec + * + * This method returns the seconds portion of the specified timestamp + * + * @param[in] _timestamp points to the timestamp + * @param[in] _timespec points to the timespec + */ +#if defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE) + #define _Timestamp64_To_timespec( _timestamp, _timespec ) \ + do { \ + (_timespec)->tv_sec = *(_timestamp) / 1000000000; \ + (_timespec)->tv_nsec = *(_timestamp) % 1000000000; \ + } while (0) +#else + void _Timestamp64_To_timespec( + Timestamp64_Control *_timestamp, + struct timespec *_timespec + ); +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/tod.h b/cpukit/score/include/rtems/score/tod.h new file mode 100644 index 0000000000..1208975cab --- /dev/null +++ b/cpukit/score/include/rtems/score/tod.h @@ -0,0 +1,255 @@ +/** + * @file rtems/score/tod.h + * + * This include file contains all the constants and structures associated + * with the Time of Day Handler. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_TOD_H +#define _RTEMS_SCORE_TOD_H + +#include <time.h> +#include <rtems/score/timestamp.h> +#include <rtems/score/basedefs.h> /* SCORE_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup ScoreTODConstants TOD Constants + * The following constants are related to the time of day and are + * independent of RTEMS. + */ +/**@{*/ + +/** + * This constant represents the number of seconds in a minute. + */ +#define TOD_SECONDS_PER_MINUTE (uint32_t)60 + +/** + * This constant represents the number of minutes per hour. + */ +#define TOD_MINUTES_PER_HOUR (uint32_t)60 + +/** + * This constant represents the number of months in a year. + */ +#define TOD_MONTHS_PER_YEAR (uint32_t)12 + +/** + * This constant represents the number of days in a non-leap year. + */ +#define TOD_DAYS_PER_YEAR (uint32_t)365 + +/** + * This constant represents the number of hours per day. + */ +#define TOD_HOURS_PER_DAY (uint32_t)24 + +/** + * This constant represents the number of seconds in a day which does + * not include a leap second. + */ +#define TOD_SECONDS_PER_DAY (uint32_t) (TOD_SECONDS_PER_MINUTE * \ + TOD_MINUTES_PER_HOUR * \ + TOD_HOURS_PER_DAY) + +/** + * This constant represents the number of seconds in a non-leap year. + */ +#define TOD_SECONDS_PER_NON_LEAP_YEAR (365 * TOD_SECONDS_PER_DAY) + +/** + * This constant represents the number of millisecond in a second. + */ +#define TOD_MILLISECONDS_PER_SECOND (uint32_t)1000 + +/** + * This constant represents the number of microseconds in a second. + */ +#define TOD_MICROSECONDS_PER_SECOND (uint32_t)1000000 + +/** + * This constant represents the number of nanoseconds in a second. + */ +#define TOD_NANOSECONDS_PER_SECOND (uint32_t)1000000000 + +/** + * This constant represents the number of nanoseconds in a mircosecond. + */ +#define TOD_NANOSECONDS_PER_MICROSECOND (uint32_t)1000 + +/**@}*/ + +/** + * Seconds from January 1, 1970 to January 1, 1988. Used to account for + * differences between POSIX API and RTEMS core. The timespec format time + * is kept in POSIX compliant form. + */ +#define TOD_SECONDS_1970_THROUGH_1988 \ + (((1987 - 1970 + 1) * TOD_SECONDS_PER_NON_LEAP_YEAR) + \ + (4 * TOD_SECONDS_PER_DAY)) + +/** @brief RTEMS Epoch Year + * + * The following constant define the earliest year to which an + * time of day can be initialized. This is considered the + * epoch. + */ +#define TOD_BASE_YEAR 1988 + +/** + * @defgroup ScoreTOD Time Of Day (TOD) Handler + * + * This handler encapsulates functionality used to manage time of day. + */ +/**@{*/ + +/** @brief Is the Time Of Day Set + * + * This is true if the application has set the current + * time of day, and false otherwise. + */ +SCORE_EXTERN bool _TOD_Is_set; + +/** @brief Current Time of Day (Timespec) + * The following contains the current time of day. + */ +SCORE_EXTERN Timestamp_Control _TOD_Now; + +/** @brief Current Time of Day (Timespec) + * The following contains the running uptime. + */ +SCORE_EXTERN Timestamp_Control _TOD_Uptime; + +/** @brief Seconds Since RTEMS Epoch + * The following contains the number of seconds from 00:00:00 + * January 1, TOD_BASE_YEAR until the current time of day. + */ +#define _TOD_Seconds_since_epoch() \ + _Timestamp_Get_seconds(&_TOD_Now) + +/** @brief _TOD_Handler_initialization + * + * This routine performs the initialization necessary for this handler. + */ +void _TOD_Handler_initialization(void); + +/** @brief _TOD_Set + * + * This routine sets the current time of day to @a time and + * the equivalent SECONDS_SINCE_EPOCH. + */ +void _TOD_Set( + const struct timespec *time +); + +/** @brief _TOD_Get + * + * This routine returns the current time of day with potential accuracy + * to the nanosecond. + * + * @param[in] time is a pointer to the time to be returned + */ +void _TOD_Get( + struct timespec *time +); + +/** @brief _TOD_Get_uptime + * + * This routine returns the system uptime with potential accuracy + * to the nanosecond. + * + * @param[in] time is a pointer to the uptime to be returned + */ +void _TOD_Get_uptime( + Timestamp_Control *time +); + +/** @brief _TOD_Get_uptime_as_timespec + * + * This routine returns the system uptime with potential accuracy + * to the nanosecond. + * + * @param[in] time is a pointer to the uptime to be returned + */ +void _TOD_Get_uptime_as_timespec( + struct timespec *time +); + +/** + * This routine increments the ticks field of the current time of + * day at each clock tick. + */ +void _TOD_Tickle_ticks( void ); + +/** @brief TOD_MILLISECONDS_TO_MICROSECONDS + * + * This routine converts an interval expressed in milliseconds to microseconds. + * + * @note This must be a macro so it can be used in "static" tables. + */ +#define TOD_MILLISECONDS_TO_MICROSECONDS(_ms) ((uint32_t)(_ms) * 1000L) + +/** @brief TOD_MICROSECONDS_TO_TICKS + * + * This routine converts an interval expressed in microseconds to ticks. + * + * @note This must be a macro so it can be used in "static" tables. + */ +uint32_t TOD_MICROSECONDS_TO_TICKS( + uint32_t microseconds +); + +/** @brief TOD_MILLISECONDS_TO_TICKS + * + * This routine converts an interval expressed in milliseconds to ticks. + * + * @note This must be a macro so it can be used in "static" tables. + */ +uint32_t TOD_MILLISECONDS_TO_TICKS( + uint32_t milliseconds +); + +/** @brief How many ticks in a second? + * + * This method returns the number of ticks in a second. + * + * @note If the clock tick value does not multiply evenly into a second + * then this number of ticks will be slightly shorter than a second. + */ +uint32_t TOD_TICKS_PER_SECOND_method(void); + +/** @brief Method to return number of ticks in a second + * + * This method exists to hide the fact that TOD_TICKS_PER_SECOND can not + * be implemented as a macro in a .h file due to visibility issues. + * The Configuration Table is not available to SuperCore .h files but + * is available to their .c files. + */ +#define TOD_TICKS_PER_SECOND TOD_TICKS_PER_SECOND_method() + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/tod.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/tqdata.h b/cpukit/score/include/rtems/score/tqdata.h new file mode 100644 index 0000000000..1531f7cbd8 --- /dev/null +++ b/cpukit/score/include/rtems/score/tqdata.h @@ -0,0 +1,116 @@ +/** + * @file rtems/score/tqdata.h + * + * This include file contains all the constants and structures + * needed to declare a thread queue. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_TQDATA_H +#define _RTEMS_SCORE_TQDATA_H + +/** + * @defgroup ScoreThreadQData Thread Queue Handler Data Definition + * + * This handler defines the data shared between the thread and thread + * queue handlers. Having this handler define these data structure + * avoids potentially circular references. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/chain.h> +#include <rtems/score/priority.h> +#include <rtems/score/states.h> +#include <rtems/score/threadsync.h> + +/** + * The following enumerated type details all of the disciplines + * supported by the Thread Queue Handler. + */ +typedef enum { + THREAD_QUEUE_DISCIPLINE_FIFO, /* FIFO queue discipline */ + THREAD_QUEUE_DISCIPLINE_PRIORITY /* PRIORITY queue discipline */ +} Thread_queue_Disciplines; + +/** + * This is one of the constants used to manage the priority queues. + * + * There are four chains used to maintain a priority -- each chain + * manages a distinct set of task priorities. The number of chains + * is determined by TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS. + * The following set must be consistent. + * + * The set below configures 4 headers -- each contains 64 priorities. + * Header x manages priority range (x*64) through ((x*64)+63). If + * the priority is more than half way through the priority range it + * is in, then the search is performed from the rear of the chain. + * This halves the search time to find the insertion point. + */ +#define TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS 4 + +/** + * This is one of the constants used to manage the priority queues. + * @ref TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS for more details. + */ +#define TASK_QUEUE_DATA_PRIORITIES_PER_HEADER 64 + +/** + * This is one of the constants used to manage the priority queues. + * @ref TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS for more details. + */ +#define TASK_QUEUE_DATA_REVERSE_SEARCH_MASK 0x20 + +/** + * This is the structure used to manage sets of tasks which are blocked + * waiting to acquire a resource. + */ +typedef struct { + /** This union contains the data structures used to manage the blocked + * set of tasks which varies based upon the discipline. + */ + union { + /** This is the FIFO discipline list. */ + Chain_Control Fifo; + /** This is the set of lists for priority discipline waiting. */ + Chain_Control Priority[TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS]; + } Queues; + /** This field is used to manage the critical section. */ + Thread_blocking_operation_States sync_state; + /** This field indicates the thread queue's blocking discipline. */ + Thread_queue_Disciplines discipline; + /** This indicates the blocking state for threads waiting on this + * thread queue. + */ + States_Control state; + /** This is the status value returned to threads which timeout while + * waiting on this thread queue. + */ + uint32_t timeout_status; +} Thread_queue_Control; + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/tqdata.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/userext.h b/cpukit/score/include/rtems/score/userext.h new file mode 100644 index 0000000000..b8604deae9 --- /dev/null +++ b/cpukit/score/include/rtems/score/userext.h @@ -0,0 +1,331 @@ +/** + * @file + * + * @ingroup ScoreUserExt + * + * @brief User Extension Handler API. + */ + +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_USEREXT_H +#define _RTEMS_SCORE_USEREXT_H + +#include <rtems/score/interr.h> +#include <rtems/score/chain.h> +#include <rtems/score/thread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void User_extensions_routine RTEMS_COMPILER_DEPRECATED_ATTRIBUTE; + +/** + * @defgroup ScoreUserExt User Extension Handler + * + * @ingroup Score + * + * @brief The User Extension Handler provides invocation of application + * dependent routines at critical points in the life of each thread and the + * system as a whole. + * + * @{ + */ + +/** + * @brief Task create extension. + * + * It corresponds to _Thread_Initialize() (used by the rtems_task_create() + * directive). The first parameter points to the currently executing thread + * which created the new thread. The second parameter points to the created + * thread. + * + * It is invoked after the new thread has been completely initialized, but + * before it is placed on a ready chain. + * + * Thread dispatching may be disabled. This depends on the context of the + * _Thread_Initialize() call. Thread dispatch is disabled during the creation + * of the idle thread and the initialization threads. It can be considered as + * an invalid API usage, if the application calls _Thread_Initialize() with + * disabled thread dispatching. Disabled thread dispatching is different from + * disabled preemption. + * + * It can be assumed that the executing thread locked the allocator mutex. + * The only exception is the creation of the idle thread. In this case the + * allocator mutex is not locked. Since the allocator mutex is non-recursive, + * it is prohibited to call the normal memory allocation routines. It is + * possible to use internal rountines like _Workspace_Allocate() or + * _Heap_Allocate() for heaps which are protected by the allocator mutex. + * + * @retval true The thread create extension was successful. + * @retval false A thread create user extension will frequently attempt to + * allocate resources. If this allocation fails, then the extension should + * return @a false and the entire thread create operation will fail. + */ +typedef bool ( *User_extensions_thread_create_extension )( + Thread_Control *, + Thread_Control * +); + +/** + * @brief Task delete extension. + * + * It corresponds to _Thread_Close() (used by the rtems_task_delete() + * directive). The first parameter points to the currently executing thread + * which deleted the thread. The second parameter points to the deleted + * thread. + * + * It is invoked before all resources of the thread are deleted. + * + * Thread dispatching is enabled. The executing thread locked the allocator + * mutex. + */ +typedef void( *User_extensions_thread_delete_extension )( + Thread_Control *, + Thread_Control * +); + +/** + * @brief Task start extension. + * + * It corresponds to _Thread_Start() (used by the rtems_task_start() + * directive). The first parameter points to the currently executing thread + * which started the thread. The second parameter points to the started + * thread. + * + * It is invoked after the environment of the thread has been loaded and the + * thread has been made ready. + * + * Thread dispatching is disabled. The executing thread is not the holder of + * the allocator mutex. + */ +typedef void( *User_extensions_thread_start_extension )( + Thread_Control *, + Thread_Control * +); + +/** + * @brief Task restart extension. + * + * It corresponds to _Thread_Restart() (used by the rtems_task_restart() + * directive). The first parameter points to the currently executing thread + * which restarted the thread. The second parameter points to the restarted + * thread. + * + * It is invoked after the environment of the thread has been loaded and the + * thread has been made ready. + * + * Thread dispatching is disabled. The executing thread is not the holder of + * the allocator mutex. + */ +typedef void( *User_extensions_thread_restart_extension )( + Thread_Control *, + Thread_Control * +); + +/** + * @brief Task switch extension. + * + * It corresponds to _Thread_Dispatch(). The first parameter points to the + * currently executing thread. The second parameter points to the heir thread. + * + * It is invoked before the context switch from the executing to the heir + * thread. + * + * Thread dispatching is disabled. The state of the allocator mutex is + * arbitrary. + * + * The context switches initiated through _Thread_Start_multitasking() and + * _Thread_Stop_multitasking() are not covered by this extension. The + * executing thread may run with a minimal setup, for example with a freed task + * stack. + */ +typedef void( *User_extensions_thread_switch_extension )( + Thread_Control *, + Thread_Control * +); + +/** + * @brief Task begin extension. + * + * It corresponds to _Thread_Handler(). The first parameter points to the + * currently executing thread which begins now execution. + * + * Thread dispatching is disabled. The executing thread is not the holder of + * the allocator mutex. + */ +typedef void( *User_extensions_thread_begin_extension )( + Thread_Control * +); + +/** + * @brief Task exitted extension. + * + * It corresponds to _Thread_Handler(). The first parameter points to the + * currently executing thread which exitted before. + * + * Thread dispatching is disabled. The state of the allocator mutex is + * arbitrary. + */ +typedef void( *User_extensions_thread_exitted_extension )( + Thread_Control * +); + +/** + * @brief Fatal error extension. + * + * It corresponds to _Internal_error_Occurred() (used by the + * rtems_fatal_error_occurred() directive). The first parameter contains the + * error source. The second parameter indicates if it was an internal error. + * The third parameter contains the error code. + * + * This extension should not call any RTEMS directives. + */ +typedef void( *User_extensions_fatal_extension )( + Internal_errors_Source, + bool, + Internal_errors_t +); + +/** + * @brief User extension table. + */ +typedef struct { + User_extensions_thread_create_extension thread_create; + User_extensions_thread_start_extension thread_start; + User_extensions_thread_restart_extension thread_restart; + User_extensions_thread_delete_extension thread_delete; + User_extensions_thread_switch_extension thread_switch; + User_extensions_thread_begin_extension thread_begin; + User_extensions_thread_exitted_extension thread_exitted; + User_extensions_fatal_extension fatal; +} User_extensions_Table; + +/** + * @brief Manages the switch callouts. + * + * They are managed separately from other extensions for performance reasons. + */ +typedef struct { + Chain_Node Node; + User_extensions_thread_switch_extension thread_switch; +} User_extensions_Switch_control; + +/** + * @brief Manages each user extension set. + * + * The switch control is part of the extensions control even if not used due to + * the extension not having a switch handler. + */ +typedef struct { + Chain_Node Node; + User_extensions_Switch_control Switch; + User_extensions_Table Callouts; +} User_extensions_Control; + +/** + * @brief List of active extensions. + */ +SCORE_EXTERN Chain_Control _User_extensions_List; + +/** + * @brief List of active task switch extensions. + */ +SCORE_EXTERN Chain_Control _User_extensions_Switches_list; + +/** + * @name Extension Maintainance + * + * @{ + */ + +void _User_extensions_Handler_initialization( void ); + +void _User_extensions_Add_set( + User_extensions_Control *extension +); + +RTEMS_INLINE_ROUTINE void _User_extensions_Add_API_set( + User_extensions_Control *extension +) +{ + _User_extensions_Add_set( extension ); +} + +RTEMS_INLINE_ROUTINE void _User_extensions_Add_set_with_table( + User_extensions_Control *extension, + const User_extensions_Table *extension_table +) +{ + extension->Callouts = *extension_table; + + _User_extensions_Add_set( extension ); +} + +void _User_extensions_Remove_set( + User_extensions_Control *extension +); + +/** @} */ + +/** + * @name Extension Callout Dispatcher + * + * @{ + */ + +bool _User_extensions_Thread_create( + Thread_Control *created +); + +void _User_extensions_Thread_delete( + Thread_Control *deleted +); + +void _User_extensions_Thread_start( + Thread_Control *started +); + +void _User_extensions_Thread_restart( + Thread_Control *restarted +); + +void _User_extensions_Thread_begin( + Thread_Control *executing +); + +void _User_extensions_Thread_switch( + Thread_Control *executing, + Thread_Control *heir +); + +void _User_extensions_Thread_exitted( + Thread_Control *executing +); + +void _User_extensions_Fatal( + Internal_errors_Source source, + bool is_internal, + Internal_errors_t error +); + +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h new file mode 100644 index 0000000000..33c2739633 --- /dev/null +++ b/cpukit/score/include/rtems/score/watchdog.h @@ -0,0 +1,323 @@ +/** + * @file rtems/score/watchdog.h + * + * This include file contains all the constants and structures associated + * with watchdog timers. This Handler provides mechanisms which can be + * used to initialize and manipulate watchdog timers. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_WATCHDOG_H +#define _RTEMS_SCORE_WATCHDOG_H + +/** + * @defgroup ScoreWatchdog Watchdog Handler + * + * This handler encapsulates functionality related to the scheduling of + * watchdog functions to be called at specific times in the future. + * + * @note This handler does not have anything to do with hardware watchdog + * timers. + */ +/**@{*/ + +#include <rtems/score/object.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Maximum Interval Length + * + * The following type defines the control block used to manage + * intervals. + */ +#define WATCHDOG_MAXIMUM_INTERVAL ((Watchdog_Interval) 0xffffffff) + +/** @brief Watchdog Interval Type + * + * This type is used to specify the length of intervals. + */ +typedef uint32_t Watchdog_Interval; + +/** @brief Watchdog Nanoseconds Since Last Tick Extension + * + * This type defines a pointer to the BSP plugin to obtain the number + * of nanoseconds since the last clock tick. + */ +typedef uint32_t (*Watchdog_Nanoseconds_since_last_tick_routine)(void); + +/** @brief Watchdog Service Routine Return Type + * + * This type defines the return type from a Watchdog Service Routine. + */ +typedef void Watchdog_Service_routine; + +/** @brief Watchdog Service Routine Pointer Type + * + * This type define a pointer to a watchdog service routine. + */ +typedef Watchdog_Service_routine ( *Watchdog_Service_routine_entry )( + Objects_Id, + void * + ); + +/** @brief No timeout constant + * + * This is the constant for indefinite wait. It is actually an + * illegal interval. + */ +#define WATCHDOG_NO_TIMEOUT 0 + +/** @brief Watchdog States Type + * + * This enumerated type is the set of the states in which a + * watchdog timer may be at any given time. + */ + +typedef enum { + /** This is the state when the watchdog is off all chains */ + WATCHDOG_INACTIVE, + /** This is the state when the watchdog is off all chains, but we are + * currently searching for the insertion point. + */ + WATCHDOG_BEING_INSERTED, + /** This is the state when the watchdog is on a chain, and allowed to fire. */ + WATCHDOG_ACTIVE, + /** This is the state when the watchdog is on a chain, but we should + * remove without firing if it expires. + */ + WATCHDOG_REMOVE_IT +} Watchdog_States; + +/** @brief Watchdog Adjustment Directions Type + * + * The following enumerated type details the manner in which + * a watchdog chain may be adjusted by the @ref _Watchdog_Adjust + * routine. The direction indicates a movement FORWARD + * or BACKWARD in time. + */ +typedef enum { + /** adjust delta value forward */ + WATCHDOG_FORWARD, + /** adjust delta value backward */ + WATCHDOG_BACKWARD +} Watchdog_Adjust_directions; + +/** @brief Watchdog Control Structure + * + * The following record defines the control block used + * to manage each watchdog timer. + */ +typedef struct { + /** This field is a Chain Node structure and allows this to be placed on + * chains for set management. + */ + Chain_Node Node; + /** This field is the state of the watchdog. */ + Watchdog_States state; + /** This field is the initially requested interval. */ + Watchdog_Interval initial; + /** This field is the remaining portion of the interval. */ + Watchdog_Interval delta_interval; + /** This field is the number of system clock ticks when this was scheduled. */ + Watchdog_Interval start_time; + /** This field is the number of system clock ticks when this was suspended. */ + Watchdog_Interval stop_time; + /** This field is the function to invoke. */ + Watchdog_Service_routine_entry routine; + /** This field is the Id to pass as an argument to the routine. */ + Objects_Id id; + /** This field is an untyped pointer to user data that is passed to the + * watchdog handler routine. + */ + void *user_data; +} Watchdog_Control; + +/** @brief Watchdog Synchronization Level + * + * This used for synchronization purposes + * during an insert on a watchdog delta chain. + */ +SCORE_EXTERN volatile uint32_t _Watchdog_Sync_level; + +/** @brief Watchdog Synchronization Count + * + * This used for synchronization purposes + * during an insert on a watchdog delta chain. + */ +SCORE_EXTERN volatile uint32_t _Watchdog_Sync_count; + +/** @brief Ticks Since System Boot + * + * This contains the number of ticks since the system was booted. + */ + +SCORE_EXTERN volatile Watchdog_Interval _Watchdog_Ticks_since_boot; + +/** @brief Watchdog Nanoseconds Since Last Tick Handler + * + * This is a pointer to the optional BSP plugin to obtain the number + * of nanoseconds since the last clock tick. + */ +extern Watchdog_Nanoseconds_since_last_tick_routine + _Watchdog_Nanoseconds_since_tick_handler; + +/** @brief Per Ticks Watchdog List + * + * This is the watchdog chain which is managed at ticks. + */ +SCORE_EXTERN Chain_Control _Watchdog_Ticks_chain; + +/** @brief Per Seconds Watchdog List + * + * This is the watchdog chain which is managed at second boundaries. + */ +SCORE_EXTERN Chain_Control _Watchdog_Seconds_chain; + +/** @brief Watchdog Handler Initialization + * + * This routine initializes the watchdog handler. The watchdog + * synchronization flag is initialized and the watchdog chains are + * initialized and emptied. + */ +void _Watchdog_Handler_initialization( void ); + +/** @brief Remove Watchdog from List + * + * This routine removes @a the_watchdog from the watchdog chain on which + * it resides and returns the state @a the_watchdog timer was in. + * + * @param[in] the_watchdog will be removed + * @return the state in which @a the_watchdog was in when removed + */ +Watchdog_States _Watchdog_Remove ( + Watchdog_Control *the_watchdog +); + +/** @brief Watchdog Adjust + * + * This routine adjusts the @a header watchdog chain in the forward + * or backward @a direction for @a units ticks. + * + * @param[in] header is the watchdog chain to adjust + * @param[in] direction is the direction to adjust @a header + * @param[in] units is the number of units to adjust @a header + */ +void _Watchdog_Adjust ( + Chain_Control *header, + Watchdog_Adjust_directions direction, + Watchdog_Interval units +); + +/** @brief Watchdog Adjust to Chain + * + * This routine adjusts the @a header watchdog chain in the forward + * @a direction for @a units_arg ticks. + * + * @param[in] header is the watchdog chain to adjust + * @param[in] units_arg is the number of units to adjust @a header + * @param[in] to_fire is a pointer to an initialized Chain_Control to which + * all watchdog instances that are to be fired will be placed. + * + * @note This always adjusts forward. + */ +void _Watchdog_Adjust_to_chain( + Chain_Control *header, + Watchdog_Interval units_arg, + Chain_Control *to_fire + +); + +/** @brief Watchdog Insert + * + * This routine inserts @a the_watchdog into the @a header watchdog chain + * for a time of @a units. + * + * @param[in] header is @a the_watchdog list to insert @a the_watchdog on + * @param[in] the_watchdog is the watchdog to insert + */ +void _Watchdog_Insert ( + Chain_Control *header, + Watchdog_Control *the_watchdog +); + +/** @brief Watchdog Tickle + * + * This routine is invoked at appropriate intervals to update + * the @a header watchdog chain. + * + * @param[in] header is the watchdog chain to tickle + */ +void _Watchdog_Tickle ( + Chain_Control *header +); + +/** + * @brief Report Information on a Single Watchdog Instance + * + * This method prints a one line report on the watchdog instance + * provided. The @a name may be used to identify the watchdog and + * a space will be printed after @a name if it is not NULL. + * + * @param[in] name is a string to prefix the line with. If NULL, + * nothing is printed. + * @param[in] watch is the watchdog instance to be printed. + * + * @note This is a debug routine. It uses printk() and prudence should + * exercised when using it. + */ +void _Watchdog_Report( + const char *name, + Watchdog_Control *watch +); + +/** + * @brief Report Information on a Watchdog Chain + * + * This method prints report on the watchdog chain provided. + * The @a name may be used to identify the watchdog chain and + * a space will be printed after @a name if it is not NULL. + * + * @param[in] name is a string to prefix the line with. If NULL, + * nothing is printed. + * @param[in] header is the watchdog chain to be printed. + * + * @note This is a debug routine. It uses printk() and prudence should + * exercised when using it. It also disables interrupts so the + * chain can be traversed in a single atomic pass. + */ +void _Watchdog_Report_chain( + const char *name, + Chain_Control *header +); + +/** + * @brief Default nanoseconds since last tick handler. + * + * @retval 0 Always. + */ +uint32_t _Watchdog_Nanoseconds_since_tick_default_handler( void ); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/watchdog.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/wkspace.h b/cpukit/score/include/rtems/score/wkspace.h new file mode 100644 index 0000000000..c3a0700a01 --- /dev/null +++ b/cpukit/score/include/rtems/score/wkspace.h @@ -0,0 +1,106 @@ +/** + * @file rtems/score/wkspace.h + * + * This include file contains information related to the + * RAM Workspace. This Handler provides mechanisms which can be used to + * define, initialize and manipulate the workspace. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_SCORE_WKSPACE_H +#define _RTEMS_SCORE_WKSPACE_H + +/** + * @defgroup ScoreWorkspace Workspace Handler + * + * This handler encapsulates functionality related to the management of + * the RTEMS Executive Workspace. + */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/score/heap.h> +#include <rtems/score/interr.h> + +/** @brief Executive Workspace Control + * + * The is the heap control structure that used to manage the + * RTEMS Executive Workspace. + */ +SCORE_EXTERN Heap_Control _Workspace_Area; /* executive heap header */ + +/** @brief Workspace Handler Initialization + * + * This routine performs the initialization necessary for this handler. + */ +void _Workspace_Handler_initialization(void); + +/** @brief Allocate Memory from Workspace + * + * This routine returns the address of a block of memory of size + * bytes. If a block of the appropriate size cannot be allocated + * from the workspace, then NULL is returned. + * + * @param size is the requested size + * + * @return a pointer to the requested memory or NULL. + */ +void *_Workspace_Allocate( + size_t size +); + +/** @brief Free Memory to the Workspace + * + * This function frees the specified block of memory. If the block + * belongs to the Workspace and can be successfully freed, then + * true is returned. Otherwise false is returned. + * + * @param block is the memory to free + * + * @note If @a block is equal to NULL, then the request is ignored. + * This allows the caller to not worry about whether or not + * a pointer is NULL. + */ + +void _Workspace_Free( + void *block +); + +/** @brief Workspace Allocate or Fail with Fatal Error + * + * This routine returns the address of a block of memory of @a size + * bytes. If a block of the appropriate size cannot be allocated + * from the workspace, then the internal error handler is invoked. + * + * @param[in] size is the desired number of bytes to allocate + * @return If successful, the starting address of the allocated memory + */ +void *_Workspace_Allocate_or_fatal_error( + size_t size +); + +#ifndef __RTEMS_APPLICATION__ +#include <rtems/score/wkspace.inl> +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ |