diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index d4d639de1..d15d5348d 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -1877,9 +1877,11 @@ int32 CFE_ES_RestoreFromCDS(void *RestoreToMemory, CFE_ES_CDSHandle_t Handle) return CFE_ES_CDSBlockRead(RestoreToMemory, Handle); } /* End of CFE_ES_RestoreFromCDS() */ -/* end of file */ - - +/* +** Function: CFE_ES_RegisterGenCounter +** +** Purpose: Allocates a generic counter resource and assigns ID +*/ int32 CFE_ES_RegisterGenCounter(CFE_ES_ResourceID_t *CounterIdPtr, const char *CounterName) { CFE_ES_GenCounterRecord_t *CountRecPtr; @@ -1912,7 +1914,7 @@ int32 CFE_ES_RegisterGenCounter(CFE_ES_ResourceID_t *CounterIdPtr, const char *C else { /* scan for a free slot */ - PendingCounterId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastCounterId, CFE_PLATFORM_ES_MAX_GEN_COUNTERS); + PendingCounterId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastCounterId, CFE_PLATFORM_ES_MAX_GEN_COUNTERS, CFE_ES_CheckCounterIdSlotUsed); CountRecPtr = CFE_ES_LocateCounterRecordByID(PendingCounterId); if (CountRecPtr == NULL) @@ -2108,7 +2110,7 @@ CFE_Status_t CFE_ES_GetGenCounterName(char *CounterName, CFE_ES_ResourceID_t Cou */ int32 CFE_ES_AppID_ToIndex(CFE_ES_ResourceID_t AppID, uint32 *Idx) { - return CFE_ES_ResourceID_ToIndex_Internal( + return CFE_ES_ResourceID_ToIndex( CFE_ES_ResourceID_ToInteger(AppID) - CFE_ES_APPID_BASE, CFE_PLATFORM_ES_MAX_APPLICATIONS, Idx); @@ -2120,7 +2122,7 @@ int32 CFE_ES_AppID_ToIndex(CFE_ES_ResourceID_t AppID, uint32 *Idx) */ int32 CFE_ES_LibID_ToIndex(CFE_ES_ResourceID_t LibId, uint32 *Idx) { - return CFE_ES_ResourceID_ToIndex_Internal( + return CFE_ES_ResourceID_ToIndex( CFE_ES_ResourceID_ToInteger(LibId) - CFE_ES_LIBID_BASE, CFE_PLATFORM_ES_MAX_LIBRARIES, Idx); @@ -2160,7 +2162,7 @@ int32 CFE_ES_TaskID_ToIndex(CFE_ES_ResourceID_t TaskID, uint32 *Idx) */ int32 CFE_ES_CounterID_ToIndex(CFE_ES_ResourceID_t CounterId, uint32 *Idx) { - return CFE_ES_ResourceID_ToIndex_Internal( + return CFE_ES_ResourceID_ToIndex( CFE_ES_ResourceID_ToInteger(CounterId) - CFE_ES_COUNTID_BASE, CFE_PLATFORM_ES_MAX_GEN_COUNTERS, Idx); diff --git a/fsw/cfe-core/src/es/cfe_es_apps.c b/fsw/cfe-core/src/es/cfe_es_apps.c index c38ee545f..66c430c49 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.c +++ b/fsw/cfe-core/src/es/cfe_es_apps.c @@ -688,7 +688,7 @@ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, else { /* scan for a free slot */ - PendingAppId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastAppId, CFE_PLATFORM_ES_MAX_APPLICATIONS); + PendingAppId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastAppId, CFE_PLATFORM_ES_MAX_APPLICATIONS, CFE_ES_CheckAppIdSlotUsed); AppRecPtr = CFE_ES_LocateAppRecordByID(PendingAppId); if (AppRecPtr == NULL) @@ -795,6 +795,7 @@ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, return Status; } /* End Function */ + /* **--------------------------------------------------------------------------------------- ** Name: CFE_ES_LoadLibrary @@ -864,7 +865,7 @@ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, else { /* scan for a free slot */ - PendingLibId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastLibId, CFE_PLATFORM_ES_MAX_LIBRARIES); + PendingLibId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastLibId, CFE_PLATFORM_ES_MAX_LIBRARIES, CFE_ES_CheckLibIdSlotUsed); LibSlotPtr = CFE_ES_LocateLibRecordByID(PendingLibId); if (LibSlotPtr == NULL) diff --git a/fsw/cfe-core/src/es/cfe_es_cds.c b/fsw/cfe-core/src/es/cfe_es_cds.c index 6d1485f81..2c6ff0248 100644 --- a/fsw/cfe-core/src/es/cfe_es_cds.c +++ b/fsw/cfe-core/src/es/cfe_es_cds.c @@ -163,12 +163,24 @@ int32 CFE_ES_CDS_EarlyInit(void) /*******************************************************************/ int32 CFE_ES_CDSBlockID_ToIndex(CFE_ES_ResourceID_t BlockID, uint32 *Idx) { - return CFE_ES_ResourceID_ToIndex_Internal( + return CFE_ES_ResourceID_ToIndex( CFE_ES_ResourceID_ToInteger(BlockID) - CFE_ES_CDSBLOCKID_BASE, CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES, Idx); } +/*--------------------------------------------------------------------------------------- + * Function: CFE_ES_CheckCDSBlockIdSlotUsed + * + * Purpose: Helper function, Aids in allocating a new ID by checking if + * a given ID is available. Must be called while locked. + *--------------------------------------------------------------------------------------- + */ +bool CFE_ES_CheckCDSBlockIdSlotUsed(CFE_ES_ResourceID_t CheckId) +{ + return CFE_ES_CDSBlockRecordIsUsed(CFE_ES_LocateCDSBlockRecordByID(CheckId)); +} + /*******************************************************************/ /* * CFE_ES_LocateCDSBlockRecordByID @@ -347,7 +359,7 @@ int32 CFE_ES_RegisterCDSEx(CFE_ES_CDSHandle_t *HandlePtr, size_t UserBlockSize, else { /* scan for a free slot */ - PendingBlockId = CFE_ES_FindNextAvailableId(CDS->LastCDSBlockId, CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES); + PendingBlockId = CFE_ES_FindNextAvailableId(CDS->LastCDSBlockId, CFE_PLATFORM_ES_CDS_MAX_NUM_ENTRIES, CFE_ES_CheckCDSBlockIdSlotUsed); RegRecPtr = CFE_ES_LocateCDSBlockRecordByID(PendingBlockId); if (RegRecPtr != NULL) diff --git a/fsw/cfe-core/src/es/cfe_es_cds.h b/fsw/cfe-core/src/es/cfe_es_cds.h index 5b6ff3132..e0564a4be 100644 --- a/fsw/cfe-core/src/es/cfe_es_cds.h +++ b/fsw/cfe-core/src/es/cfe_es_cds.h @@ -391,6 +391,20 @@ static inline size_t CFE_ES_CDSBlockRecordGetUserSize(const CFE_ES_CDS_RegRec_t return (CDSBlockRecPtr->BlockSize - sizeof(CFE_ES_CDS_BlockHeader_t)); } +/** + * @brief Check if a CDS Block ID table slot is used + * + * Checks if a table slot is available for a potential new ID + * This is a helper function intended to be used with + * CFE_ES_FindNextAvailableID() for allocating new IDs + * + * As this dereferences fields within the record, global data must be + * locked prior to invoking this function. + * + * @param[in] CheckId pending/candidate Block ID to check + * @returns true if the table slot for the ID is occupied, false if available + */ +bool CFE_ES_CheckCDSBlockIdSlotUsed(CFE_ES_ResourceID_t CheckId); /*****************************************************************************/ /** diff --git a/fsw/cfe-core/src/es/cfe_es_mempool.c b/fsw/cfe-core/src/es/cfe_es_mempool.c index 1f32588dd..6e994aabc 100644 --- a/fsw/cfe-core/src/es/cfe_es_mempool.c +++ b/fsw/cfe-core/src/es/cfe_es_mempool.c @@ -108,12 +108,24 @@ int32 CFE_ES_MemPoolDirectCommit(CFE_ES_GenPoolRecord_t *PoolRecPtr, size_t Offs int32 CFE_ES_MemPoolID_ToIndex(CFE_ES_MemHandle_t PoolID, uint32 *Idx) { - return CFE_ES_ResourceID_ToIndex_Internal( + return CFE_ES_ResourceID_ToIndex( CFE_ES_ResourceID_ToInteger(PoolID) - CFE_ES_POOLID_BASE, CFE_PLATFORM_ES_MAX_MEMORY_POOLS, Idx); } +/*--------------------------------------------------------------------------------------- + * Function: CFE_ES_CheckMemPoolSlotUsed + * + * Purpose: Helper function, Aids in allocating a new ID by checking if + * a given table slot is available. Must be called while locked. + *--------------------------------------------------------------------------------------- + */ +bool CFE_ES_CheckMemPoolSlotUsed(CFE_ES_ResourceID_t CheckId) +{ + return CFE_ES_MemPoolRecordIsUsed(CFE_ES_LocateMemPoolRecordByID(CheckId)); +} + CFE_ES_MemPoolRecord_t* CFE_ES_LocateMemPoolRecordByID(CFE_ES_MemHandle_t PoolID) { CFE_ES_MemPoolRecord_t *MemPoolRecPtr; @@ -211,7 +223,7 @@ int32 CFE_ES_PoolCreateEx(CFE_ES_MemHandle_t *PoolID, CFE_ES_LockSharedData(__func__,__LINE__); /* scan for a free slot */ - PendingID = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastMemPoolId, CFE_PLATFORM_ES_MAX_MEMORY_POOLS); + PendingID = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastMemPoolId, CFE_PLATFORM_ES_MAX_MEMORY_POOLS, CFE_ES_CheckMemPoolSlotUsed); PoolRecPtr = CFE_ES_LocateMemPoolRecordByID(PendingID); if (PoolRecPtr == NULL) diff --git a/fsw/cfe-core/src/es/cfe_es_mempool.h b/fsw/cfe-core/src/es/cfe_es_mempool.h index cd4347488..247d65110 100644 --- a/fsw/cfe-core/src/es/cfe_es_mempool.h +++ b/fsw/cfe-core/src/es/cfe_es_mempool.h @@ -164,12 +164,38 @@ static inline void CFE_ES_MemPoolRecordSetFree(CFE_ES_MemPoolRecord_t *PoolRecPt PoolRecPtr->PoolID = CFE_ES_RESOURCEID_UNDEFINED; } - +/** + * @brief Check if an Mem Pool record is a match for the given Pool ID + * + * This routine confirms that the previously-located record is valid + * and matches the expected Pool ID. + * + * As this dereferences fields within the record, global data must be + * locked prior to invoking this function. + * + * @param[in] PoolRecPtr pointer to Pool table entry + * @param[in] PoolID expected Pool ID + * @returns true if the entry matches the given pool ID + */ static inline bool CFE_ES_MemPoolRecordIsMatch(const CFE_ES_MemPoolRecord_t *PoolRecPtr, CFE_ES_MemHandle_t PoolID) { return (PoolRecPtr != NULL && CFE_ES_ResourceID_Equal(PoolRecPtr->PoolID, PoolID)); } +/** + * @brief Check if a Pool ID table slot is used + * + * Checks if a table slot is available for a potential new ID + * This is a helper function intended to be used with + * CFE_ES_FindNextAvailableID() for allocating new IDs + * + * As this dereferences fields within the record, global data must be + * locked prior to invoking this function. + * + * @param[in] CheckId pending/candidate Pool ID to check + * @returns true if the table slot for the ID is occupied, false if available + */ +bool CFE_ES_CheckMemPoolSlotUsed(CFE_ES_ResourceID_t CheckId); #endif /* _CFE_ES_MEMPOOL_H_ */ diff --git a/fsw/cfe-core/src/es/cfe_es_resource.c b/fsw/cfe-core/src/es/cfe_es_resource.c index e51867277..4035697dd 100644 --- a/fsw/cfe-core/src/es/cfe_es_resource.c +++ b/fsw/cfe-core/src/es/cfe_es_resource.c @@ -43,11 +43,11 @@ /*********************************************************************/ /* - * CFE_ES_ResourceID_ToIndex_Internal + * CFE_ES_ResourceID_ToIndex * * For complete API information, see prototype in header */ -int32 CFE_ES_ResourceID_ToIndex_Internal(uint32 Serial, uint32 TableSize, uint32 *Idx) +int32 CFE_ES_ResourceID_ToIndex(uint32 Serial, uint32 TableSize, uint32 *Idx) { if (Idx == NULL) { @@ -94,7 +94,7 @@ CFE_ES_ResourceID_t CFE_ES_ResourceID_FromOSAL(osal_id_t id) * * For complete API information, see prototype in header */ -CFE_ES_ResourceID_t CFE_ES_FindNextAvailableId(CFE_ES_ResourceID_t StartId, uint32 TableSize) +CFE_ES_ResourceID_t CFE_ES_FindNextAvailableId(CFE_ES_ResourceID_t StartId, uint32 TableSize, bool (*CheckFunc)(CFE_ES_ResourceID_t)) { uint32 Serial; uint32 Count; @@ -124,27 +124,7 @@ CFE_ES_ResourceID_t CFE_ES_FindNextAvailableId(CFE_ES_ResourceID_t StartId, uint } CheckId = CFE_ES_ResourceID_FromInteger(ResourceType + Serial); - switch (ResourceType) - { - case CFE_ES_APPID_BASE: - IsTaken = CFE_ES_AppRecordIsUsed(CFE_ES_LocateAppRecordByID(CheckId)); - break; - case CFE_ES_LIBID_BASE: - IsTaken = CFE_ES_LibRecordIsUsed(CFE_ES_LocateLibRecordByID(CheckId)); - break; - case CFE_ES_COUNTID_BASE: - IsTaken = CFE_ES_CounterRecordIsUsed(CFE_ES_LocateCounterRecordByID(CheckId)); - break; - case CFE_ES_POOLID_BASE: - IsTaken = CFE_ES_MemPoolRecordIsUsed(CFE_ES_LocateMemPoolRecordByID(CheckId)); - break; - case CFE_ES_CDSBLOCKID_BASE: - IsTaken = CFE_ES_CDSBlockRecordIsUsed(CFE_ES_LocateCDSBlockRecordByID(CheckId)); - break; - default: - /* do nothing, should never happen */ - break; - } + IsTaken = CheckFunc(CheckId); } while (IsTaken); @@ -430,4 +410,43 @@ CFE_ES_AppRecord_t *CFE_ES_GetAppRecordByContext(void) return AppRecPtr; } +/* + * --------------------------------------------------------------------------------------- + * Function: CFE_ES_CheckCounterIdSlotUsed + * + * Purpose: Helper function, Aids in allocating a new ID by checking if + * a given ID is available. Must be called while locked. + * --------------------------------------------------------------------------------------- + */ +bool CFE_ES_CheckCounterIdSlotUsed(CFE_ES_ResourceID_t CheckId) +{ + return CFE_ES_CounterRecordIsUsed(CFE_ES_LocateCounterRecordByID(CheckId)); +} + +/* + *--------------------------------------------------------------------------------------- + * Function: CFE_ES_CheckAppIdSlotUsed + * + * Purpose: Helper function, Aids in allocating a new ID by checking if + * a given ID is available. Must be called while locked. + *--------------------------------------------------------------------------------------- + */ +bool CFE_ES_CheckAppIdSlotUsed(CFE_ES_ResourceID_t CheckId) +{ + return CFE_ES_AppRecordIsUsed(CFE_ES_LocateAppRecordByID(CheckId)); +} + +/* + * --------------------------------------------------------------------------------------- + * Function: CFE_ES_CheckLibIdSlotUsed + * + * Purpose: Helper function, Aids in allocating a new ID by checking if + * a given ID is available. Must be called while locked. + * --------------------------------------------------------------------------------------- + */ +bool CFE_ES_CheckLibIdSlotUsed(CFE_ES_ResourceID_t CheckId) +{ + return CFE_ES_LibRecordIsUsed(CFE_ES_LocateLibRecordByID(CheckId)); +} + diff --git a/fsw/cfe-core/src/es/cfe_es_resource.h b/fsw/cfe-core/src/es/cfe_es_resource.h index 07af0c0cc..91f2ddeca 100644 --- a/fsw/cfe-core/src/es/cfe_es_resource.h +++ b/fsw/cfe-core/src/es/cfe_es_resource.h @@ -34,73 +34,10 @@ /* ** Include Files */ +#include "cfe_resourceid.h" +#include "private/cfe_resourceid_internal.h" #include "cfe_es_global.h" -/* -** Defines -*/ - -/* - * Limits/definitions related to CFE_ES_ResourceID_t values. - * - * Defining based on OSAL ID values makes this object a superset of - * the OSAL ID type, such that OSAL IDs can be represented as ES resource IDs - * and not conflict with/alias each other. - * - * NOTE: This reflects a bit if "inside knowledge" about how OSAL IDs are - * constructed. The overlap between OSAL IDs and ES IDs may not always be - * consistent, and they can diverge in a future version. - */ -#define CFE_ES_RESOURCEID_SHIFT OS_OBJECT_TYPE_SHIFT -#define CFE_ES_RESOURCEID_MAX ((1 << CFE_ES_RESOURCEID_SHIFT)-1) -#define CFE_ES_RESOURCEID_MARK (0x02000000) - -/** - * @defgroup CFEESResourceIDBase ES Resource ID base values - * @{ - */ -#define CFE_ES_APPID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+1) << CFE_ES_RESOURCEID_SHIFT)) -#define CFE_ES_LIBID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+2) << CFE_ES_RESOURCEID_SHIFT)) -#define CFE_ES_COUNTID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+3) << CFE_ES_RESOURCEID_SHIFT)) -#define CFE_ES_POOLID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+4) << CFE_ES_RESOURCEID_SHIFT)) -#define CFE_ES_CDSBLOCKID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+5) << CFE_ES_RESOURCEID_SHIFT)) -/** @} */ - -/** - * @brief Get the Base value (type/category) from a resource ID value - * - * This masks out the ID serial number to obtain the base value, which is different - * for each resource type. - * - * @note The value is NOT shifted or otherwise adjusted. It should match one of the - * defined base values in @ref CFEESResourceIDBase. - * - * @param[in] ResourceId the resource ID to decode - * @returns The base value associated with that ID - */ -static inline uint32 CFE_ES_ResourceID_GetBase(CFE_ES_ResourceID_t ResourceId) -{ - uint32 ResourceType = CFE_ES_ResourceID_ToInteger(ResourceId); - return (ResourceType - (ResourceType & CFE_ES_RESOURCEID_MAX)); -} - -/** - * @brief Locate the next resource ID which does not map to an in-use table entry - * - * This begins searching from StartId which should be the most recently issued ID - * for the resource category. This will then search for the next ID which does - * _not_ map to a table entry that is in use. That is, it does not alias any - * valid ID when converted to an array index. - * - * returns an undefined ID value if no open slots are available - * - * @param[in] StartId the last issued ID for the resource category (app, lib, etc). - * @returns Next ID value which does not map to a valid entry - * @retval #CFE_ES_RESOURCEID_UNDEFINED if no open slots. - * - */ -CFE_ES_ResourceID_t CFE_ES_FindNextAvailableId(CFE_ES_ResourceID_t StartId, uint32 TableSize); - /** * @brief Locate the app table entry correlating with a given app ID. @@ -550,56 +487,6 @@ extern CFE_ES_AppRecord_t* CFE_ES_GetAppRecordByContext(void); */ extern CFE_ES_TaskRecord_t* CFE_ES_GetTaskRecordByContext(void); -/** - * @brief Convert an ES Task ID to an OSAL task ID - * - * Task IDs created via CFE ES are also OSAL task IDs, but technically - * do refer to a different scope and therefore have a different type - * to represent them. - * - * This function facilitates converting between the types. - * - * @note Currently the numeric values are the same and can be interchanged - * for backward compatibility, however they may diverge in a future version. - * New code should not assume equivalence between OSAL and ES task IDs. - * - * @sa CFE_ES_ResourceID_FromOSAL - * - * @param[in] id The ES task ID - * @returns The OSAL task ID - */ -osal_id_t CFE_ES_ResourceID_ToOSAL(CFE_ES_ResourceID_t id); - -/** - * @brief Convert an ES Task ID to an OSAL task ID - * - * Task IDs created via CFE ES are also OSAL task IDs, but technically - * do refer to a different scope and therefore have a different type - * to represent them. - * - * This function facilitates converting between the types. - * - * @note Currently the numeric values are the same and can be interchanged - * for backward compatibility, however they may diverge in a future version. - * New code should not assume equivalence between OSAL and ES task IDs. - * - * @sa CFE_ES_ResourceID_ToOSAL - * - * @param[in] id The OSAL task ID - * @returns The ES task ID - */ -CFE_ES_ResourceID_t CFE_ES_ResourceID_FromOSAL(osal_id_t id); - -/** - * @brief Internal routine to aid in converting an ES resource ID to an array index - - * @param[in] Serial The resource serial number (type info masked out) - * @param[in] TableSize The size of the internal table (MAX value) - * @param[out] Idx The output index - * @returns Status code, CFE_SUCCESS if successful. - */ -int32 CFE_ES_ResourceID_ToIndex_Internal(uint32 Serial, uint32 TableSize, uint32 *Idx); - /* * Internal functions to perform name based resource lookups * @@ -611,5 +498,10 @@ CFE_ES_LibRecord_t *CFE_ES_LocateLibRecordByName(const char *Name); CFE_ES_TaskRecord_t *CFE_ES_LocateTaskRecordByName(const char *Name); CFE_ES_GenCounterRecord_t *CFE_ES_LocateCounterRecordByName(const char *Name); +/* Availability check functions used in conjunction with CFE_ES_FindNextAvailableId() */ +bool CFE_ES_CheckAppIdSlotUsed(CFE_ES_ResourceID_t CheckId); +bool CFE_ES_CheckLibIdSlotUsed(CFE_ES_ResourceID_t CheckId); +bool CFE_ES_CheckCounterIdSlotUsed(CFE_ES_ResourceID_t CheckId); + #endif /* CFE_ES_RESOURCE_H */ diff --git a/fsw/cfe-core/src/es/cfe_es_start.c b/fsw/cfe-core/src/es/cfe_es_start.c index 560fc259d..43689cb6a 100644 --- a/fsw/cfe-core/src/es/cfe_es_start.c +++ b/fsw/cfe-core/src/es/cfe_es_start.c @@ -759,7 +759,7 @@ void CFE_ES_CreateObjects(void) */ CFE_ES_LockSharedData(__func__,__LINE__); - PendingAppId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastAppId, CFE_PLATFORM_ES_MAX_APPLICATIONS); + PendingAppId = CFE_ES_FindNextAvailableId(CFE_ES_Global.LastAppId, CFE_PLATFORM_ES_MAX_APPLICATIONS, CFE_ES_CheckAppIdSlotUsed); AppRecPtr = CFE_ES_LocateAppRecordByID(PendingAppId); if (AppRecPtr != NULL) { diff --git a/fsw/cfe-core/src/inc/cfe_es.h b/fsw/cfe-core/src/inc/cfe_es.h index 244a76510..b42457ac6 100644 --- a/fsw/cfe-core/src/inc/cfe_es.h +++ b/fsw/cfe-core/src/inc/cfe_es.h @@ -43,6 +43,7 @@ #include "cfe_mission_cfg.h" #include "cfe_perfids.h" #include "cfe_error.h" +#include "cfe_resourceid.h" /*****************************************************************************/ @@ -64,32 +65,6 @@ #define CFE_ES_TEST_LONG_MASK(m,s) (CFE_ES_DTEST(m[(s)/32],(s)%32)) /* Test a bit within an array of 32-bit integers. */ -/** \name Resource ID predefined values */ -/** \{ */ - -/** - * @brief A resource ID value that represents an undefined/unused resource - * - * This constant may be used to initialize local variables of the - * CFE_ES_ResourceID_t type to a safe value that will not alias a valid ID. - * - * By design, this value is also the result of zeroing a CFE_ES_ResourceID_t - * type via standard functions like memset(), such that objects initialized - * using this method will also be set to safe values. - */ -#define CFE_ES_RESOURCEID_UNDEFINED ((CFE_ES_ResourceID_t)0) - -/** - * @brief A resource ID value that represents a reserved entry - * - * This is not a valid value for any resource type, but is used to mark - * table entries that are not available for use. For instance, this may - * be used while setting up an entry initially. - */ -#define CFE_ES_RESOURCEID_RESERVED ((CFE_ES_ResourceID_t)0xFFFFFFFF) - -/** \} */ - /* ** Note about reset type and subtypes: ** @@ -214,82 +189,6 @@ typedef void* CFE_ES_MemPoolBuf_t; * @{ */ -/** - * @brief Convert a resource ID to an integer. - * - * This is primarily intended for logging purposes, such was writing - * to debug console, event messages, or log files, using printf-like APIs. - * - * For compatibility with C library APIs, this returns an "unsigned long" - * type and should be used with the "%lx" format specifier in a printf - * format string. - * - * @note No assumptions should be made about the actual integer value, - * such as its base/range. It may be printed, but should not be modified - * or tested/compared using other arithmetic ops, and should never be used - * as the index to an array or table. See the related function - * CFE_ES_ResourceID_ToIndex() for cases where a zero-based array/table index - * is needed. - * - * @sa CFE_ES_ResourceID_FromInteger() - * - * @param[in] id Resource ID to convert - * @returns Integer value corresponding to ID - */ -static inline unsigned long CFE_ES_ResourceID_ToInteger(CFE_ES_ResourceID_t id) -{ - return ((unsigned long)id); -} - -/** - * @brief Convert an integer to a resource ID. - * - * This is the inverse of CFE_ES_ResourceID_ToInteger(), and reconstitutes - * the original CFE_ES_ResourceID_t value from the integer representation. - * - * This may be used, for instance, where an ID value is parsed from a text - * file or message using C library APIs such as scanf() or strtoul(). - * - * @sa CFE_ES_ResourceID_ToInteger() - * - * @param[in] Value Integer value to convert - * @returns ID value corresponding to integer - */ -static inline CFE_ES_ResourceID_t CFE_ES_ResourceID_FromInteger(unsigned long Value) -{ - return ((CFE_ES_ResourceID_t)Value); -} - -/** - * @brief Compare two Resource ID values for equality - * - * @param[in] id1 Resource ID to check - * @param[in] id2 Resource ID to check - * @returns true if id1 and id2 are equal, false otherwise. - */ -static inline bool CFE_ES_ResourceID_Equal(CFE_ES_ResourceID_t id1, CFE_ES_ResourceID_t id2) -{ - return (id1 == id2); -} - -/** - * @brief Check if a resource ID value is defined - * - * The constant #CFE_ES_RESOURCEID_UNDEFINED represents an undefined ID value, - * such that the expression: - * - * CFE_ES_ResourceID_IsDefined(CFE_ES_RESOURCEID_UNDEFINED) - * - * Always returns false. - * - * @param[in] id Resource ID to check - * @returns True if the ID may refer to a defined entity, false if invalid/undefined. - */ -static inline bool CFE_ES_ResourceID_IsDefined(CFE_ES_ResourceID_t id) -{ - return (id != 0); -} - /** * @brief Obtain an index value correlating to an ES Application ID * diff --git a/fsw/cfe-core/src/inc/cfe_resourceid.h b/fsw/cfe-core/src/inc/cfe_resourceid.h new file mode 100644 index 000000000..199554539 --- /dev/null +++ b/fsw/cfe-core/src/inc/cfe_resourceid.h @@ -0,0 +1,150 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/** + * \file cfe_resourceid.h + * + * Contains global prototypes and definitions related to resource + * management and related CFE resource IDs. + * + * A CFE ES Resource ID is a common way to identify CFE-managed resources such + * as apps, tasks, counters, memory pools, CDS blocks, and other entities. + */ + +#ifndef CFE_RESOURCEID_H +#define CFE_RESOURCEID_H + +/* +** Include Files +** +** The actual CFE_ES_ResourceID_t type is part of the ES global/extern typedefs, +** as the concept originated in ES and has been extended across all of CFE. +*/ +#include "cfe_es_extern_typedefs.h" + +/* +** Defines +*/ + +/** \name Resource ID predefined values */ +/** \{ */ + +/** + * @brief A resource ID value that represents an undefined/unused resource + * + * This constant may be used to initialize local variables of the + * CFE_ES_ResourceID_t type to a safe value that will not alias a valid ID. + * + * By design, this value is also the result of zeroing a CFE_ES_ResourceID_t + * type via standard functions like memset(), such that objects initialized + * using this method will also be set to safe values. + */ +#define CFE_ES_RESOURCEID_UNDEFINED ((CFE_ES_ResourceID_t){0}) + +/** + * @brief A resource ID value that represents a reserved entry + * + * This is not a valid value for any resource type, but is used to mark + * table entries that are not available for use. For instance, this may + * be used while setting up an entry initially. + */ +#define CFE_ES_RESOURCEID_RESERVED ((CFE_ES_ResourceID_t){0xFFFFFFFF}) + +/** \} */ + + +/** + * @brief Convert a resource ID to an integer. + * + * This is primarily intended for logging purposes, such was writing + * to debug console, event messages, or log files, using printf-like APIs. + * + * For compatibility with C library APIs, this returns an "unsigned long" + * type and should be used with the "%lx" format specifier in a printf + * format string. + * + * @note No assumptions should be made about the actual integer value, + * such as its base/range. It may be printed, but should not be modified + * or tested/compared using other arithmetic ops, and should never be used + * as the index to an array or table. See the related function + * CFE_ES_ResourceID_ToIndex() for cases where a zero-based array/table index + * is needed. + * + * @sa CFE_ES_ResourceID_FromInteger() + * + * @param[in] id Resource ID to convert + * @returns Integer value corresponding to ID + */ +static inline unsigned long CFE_ES_ResourceID_ToInteger(CFE_ES_ResourceID_t id) +{ + return ((unsigned long)id); +} + +/** + * @brief Convert an integer to a resource ID. + * + * This is the inverse of CFE_ES_ResourceID_ToInteger(), and reconstitutes + * the original CFE_ES_ResourceID_t value from the integer representation. + * + * This may be used, for instance, where an ID value is parsed from a text + * file or message using C library APIs such as scanf() or strtoul(). + * + * @sa CFE_ES_ResourceID_ToInteger() + * + * @param[in] Value Integer value to convert + * @returns ID value corresponding to integer + */ +static inline CFE_ES_ResourceID_t CFE_ES_ResourceID_FromInteger(unsigned long Value) +{ + return ((CFE_ES_ResourceID_t)Value); +} + +/** + * @brief Compare two Resource ID values for equality + * + * @param[in] id1 Resource ID to check + * @param[in] id2 Resource ID to check + * @returns true if id1 and id2 are equal, false otherwise. + */ +static inline bool CFE_ES_ResourceID_Equal(CFE_ES_ResourceID_t id1, CFE_ES_ResourceID_t id2) +{ + return (id1 == id2); +} + +/** + * @brief Check if a resource ID value is defined + * + * The constant #CFE_ES_RESOURCEID_UNDEFINED represents an undefined ID value, + * such that the expression: + * + * CFE_ES_ResourceID_IsDefined(CFE_ES_RESOURCEID_UNDEFINED) + * + * Always returns false. + * + * @param[in] id Resource ID to check + * @returns True if the ID may refer to a defined entity, false if invalid/undefined. + */ +static inline bool CFE_ES_ResourceID_IsDefined(CFE_ES_ResourceID_t id) +{ + return (id != 0); +} + + +#endif /* CFE_RESOURCEID_H */ diff --git a/fsw/cfe-core/src/inc/cfe_sb.h b/fsw/cfe-core/src/inc/cfe_sb.h index 2d01e1ef3..e5073b506 100644 --- a/fsw/cfe-core/src/inc/cfe_sb.h +++ b/fsw/cfe-core/src/inc/cfe_sb.h @@ -43,6 +43,7 @@ #include "cfe_mission_cfg.h" #include "ccsds.h" #include "cfe_time.h" +#include "cfe_resourceid.h" /* @@ -122,6 +123,13 @@ #define CFE_CLR(i,x) ((i) &= ~CFE_BIT(x)) /**< \brief Clears bit x of i */ #define CFE_TST(i,x) (((i) & CFE_BIT(x)) != 0)/**< \brief true(non zero) if bit x of i is set */ +/** + * \brief A CFE_SB_PipeId_t value which is always invalid + * + * This may be used as a safe initializer for CFE_SB_PipeId_t values + */ +#define CFE_SB_INVALID_PIPE CFE_ES_RESOURCEID_UNDEFINED + /* ** Pipe option bit fields. */ @@ -156,7 +164,7 @@ typedef CFE_MSG_TelemetryHeader_t CFE_SB_TlmHdr_t; ** ** Software Bus pipe identifier used in many SB APIs */ -typedef uint8 CFE_SB_PipeId_t; +typedef CFE_ES_ResourceID_t CFE_SB_PipeId_t; #ifndef CFE_OMIT_DEPRECATED_6_8 /** \brief Pointer to an SB Message */ @@ -256,6 +264,32 @@ CFE_Status_t CFE_SB_CreatePipe(CFE_SB_PipeId_t *PipeIdPtr, uint16 Depth, const **/ CFE_Status_t CFE_SB_DeletePipe(CFE_SB_PipeId_t PipeId); +/** + * @brief Obtain an index value correlating to an SB Pipe ID + * + * This calculates a zero based integer value that may be used for indexing + * into a local resource table/array. + * + * Index values are only guaranteed to be unique for resources of the same + * type. For instance, the indices corresponding to two [valid] application + * IDs will never overlap, but the index of a pipe ID and an app ID + * may be the same. Furthermore, indices may be reused if a resource is + * deleted and re-created. + * + * @note There is no inverse of this function - indices cannot be converted + * back to the original PipeID value. The caller should retain the original ID + * for future use. + * + * @param[in] PipeID Pipe ID to convert + * @param[out] Idx Buffer where the calculated index will be stored + * + * @return Execution status, see @ref CFEReturnCodes + * @retval #CFE_SUCCESS @copybrief CFE_SUCCESS + * @retval #CFE_ES_ERR_RESOURCEID_NOT_VALID @copybrief CFE_ES_ERR_RESOURCEID_NOT_VALID + */ +CFE_Status_t CFE_SB_PipeId_ToIndex(CFE_SB_PipeId_t PipeID, uint32 *Idx); + + /*****************************************************************************/ /** ** \brief Set options on a pipe. diff --git a/fsw/cfe-core/src/inc/cfe_sb_msg.h b/fsw/cfe-core/src/inc/cfe_sb_msg.h index cdf37ccef..40623ad8d 100644 --- a/fsw/cfe-core/src/inc/cfe_sb_msg.h +++ b/fsw/cfe-core/src/inc/cfe_sb_msg.h @@ -604,14 +604,14 @@ typedef struct CFE_SB_PipeDepthStats { CFE_SB_PipeId_t PipeId;/**< \cfetlmmnemonic \SB_PDPIPEID \brief Pipe Id associated with the stats below */ - uint8 Spare;/**< \cfetlmmnemonic \SB_PDSPARE - \brief Spare byte to ensure alignment */ uint16 Depth;/**< \cfetlmmnemonic \SB_PDDEPTH \brief Number of messages the pipe can hold */ uint16 InUse;/**< \cfetlmmnemonic \SB_PDINUSE \brief Number of messages currently on the pipe */ uint16 PeakInUse;/**< \cfetlmmnemonic \SB_PDPKINUSE \brief Peak number of messages that have been on the pipe */ + uint16 Spare;/**< \cfetlmmnemonic \SB_PDSPARE + \brief Spare word to ensure alignment */ }CFE_SB_PipeDepthStats_t; diff --git a/fsw/cfe-core/src/inc/private/cfe_resourceid_internal.h b/fsw/cfe-core/src/inc/private/cfe_resourceid_internal.h new file mode 100644 index 000000000..cf9969fa7 --- /dev/null +++ b/fsw/cfe-core/src/inc/private/cfe_resourceid_internal.h @@ -0,0 +1,165 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/** + * \file cfe_resourceid_internal.h + * + * Contains CFE internal prototypes and definitions related to resource + * management and related CFE resource IDs. + * + * A CFE ES Resource ID is a common way to identify CFE-managed resources such + * as apps, tasks, counters, memory pools, CDS blocks, and other entities. + */ + +#ifndef CFE_RESOURCEID_INTERNAL_H +#define CFE_RESOURCEID_INTERNAL_H + +/* +** Include Files +*/ +#include "cfe_resourceid.h" +#include "osapi-idmap.h" + +/* +** Defines +*/ + +/* + * Limits/definitions related to CFE_ES_ResourceID_t values. + * + * Defining based on OSAL ID values makes this object a superset of + * the OSAL ID type, such that OSAL IDs can be represented as ES resource IDs + * and not conflict with/alias each other. + * + * NOTE: This reflects a bit if "inside knowledge" about how OSAL IDs are + * constructed. The overlap between OSAL IDs and ES IDs may not always be + * consistent, and they can diverge in a future version. + */ +#define CFE_ES_RESOURCEID_SHIFT OS_OBJECT_TYPE_SHIFT +#define CFE_ES_RESOURCEID_MAX ((1 << CFE_ES_RESOURCEID_SHIFT)-1) +#define CFE_ES_RESOURCEID_MARK (0x02000000) + +/** + * @defgroup CFEResourceIDBase Resource ID base values + * @{ + */ + +/* ES managed resources */ +#define CFE_ES_APPID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+1) << CFE_ES_RESOURCEID_SHIFT)) +#define CFE_ES_LIBID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+2) << CFE_ES_RESOURCEID_SHIFT)) +#define CFE_ES_COUNTID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+3) << CFE_ES_RESOURCEID_SHIFT)) +#define CFE_ES_POOLID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+4) << CFE_ES_RESOURCEID_SHIFT)) +#define CFE_ES_CDSBLOCKID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+5) << CFE_ES_RESOURCEID_SHIFT)) + +/* SB managed resources */ +#define CFE_SB_PIPEID_BASE (CFE_ES_RESOURCEID_MARK | ((OS_OBJECT_TYPE_USER+6) << CFE_ES_RESOURCEID_SHIFT)) + +/** @} */ + + +/** + * @brief Get the Base value (type/category) from a resource ID value + * + * This masks out the ID serial number to obtain the base value, which is different + * for each resource type. + * + * @note The value is NOT shifted or otherwise adjusted. It should match one of the + * defined base values in @ref CFEESResourceIDBase. + * + * @param[in] ResourceId the resource ID to decode + * @returns The base value associated with that ID + */ +static inline uint32 CFE_ES_ResourceID_GetBase(CFE_ES_ResourceID_t ResourceId) +{ + uint32 ResourceType = CFE_ES_ResourceID_ToInteger(ResourceId); + return (ResourceType - (ResourceType & CFE_ES_RESOURCEID_MAX)); +} + +/** + * @brief Locate the next resource ID which does not map to an in-use table entry + * + * This begins searching from StartId which should be the most recently issued ID + * for the resource category. This will then search for the next ID which does + * _not_ map to a table entry that is in use. That is, it does not alias any + * valid ID when converted to an array index. + * + * returns an undefined ID value if no open slots are available + * + * @param[in] StartId the last issued ID for the resource category (app, lib, etc). + * @param[in] TableSize the maximum size of the target table + * @param[in] CheckFunc a function to check if the given ID is available + * @returns Next ID value which does not map to a valid entry + * @retval #CFE_ES_RESOURCEID_UNDEFINED if no open slots. + * + */ +CFE_ES_ResourceID_t CFE_ES_FindNextAvailableId(CFE_ES_ResourceID_t StartId, uint32 TableSize, bool (*CheckFunc)(CFE_ES_ResourceID_t) ); + +/** + * @brief Convert an ES Task ID to an OSAL task ID + * + * Task IDs created via CFE ES are also OSAL task IDs, but technically + * do refer to a different scope and therefore have a different type + * to represent them. + * + * This function facilitates converting between the types. + * + * @note Currently the numeric values are the same and can be interchanged + * for backward compatibility, however they may diverge in a future version. + * New code should not assume equivalence between OSAL and ES task IDs. + * + * @sa CFE_ES_ResourceID_FromOSAL + * + * @param[in] id The ES task ID + * @returns The OSAL task ID + */ +osal_id_t CFE_ES_ResourceID_ToOSAL(CFE_ES_ResourceID_t id); + +/** + * @brief Convert an ES Task ID to an OSAL task ID + * + * Task IDs created via CFE ES are also OSAL task IDs, but technically + * do refer to a different scope and therefore have a different type + * to represent them. + * + * This function facilitates converting between the types. + * + * @note Currently the numeric values are the same and can be interchanged + * for backward compatibility, however they may diverge in a future version. + * New code should not assume equivalence between OSAL and ES task IDs. + * + * @sa CFE_ES_ResourceID_ToOSAL + * + * @param[in] id The OSAL task ID + * @returns The ES task ID + */ +CFE_ES_ResourceID_t CFE_ES_ResourceID_FromOSAL(osal_id_t id); + +/** + * @brief Internal routine to aid in converting an ES resource ID to an array index + + * @param[in] Serial The resource serial number (type info masked out) + * @param[in] TableSize The size of the internal table (MAX value) + * @param[out] Idx The output index + * @returns Status code, CFE_SUCCESS if successful. + */ +int32 CFE_ES_ResourceID_ToIndex(uint32 Serial, uint32 TableSize, uint32 *Idx); + + +#endif /* CFE_RESOURCEID_H */ diff --git a/fsw/cfe-core/src/sb/cfe_sb_api.c b/fsw/cfe-core/src/sb/cfe_sb_api.c index f05161ad1..f4a8cdcf8 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_api.c +++ b/fsw/cfe-core/src/sb/cfe_sb_api.c @@ -82,6 +82,18 @@ typedef struct CFE_SB_PipeId_t PipeId; /* Pipe id to remove */ } CFE_SB_RemovePipeCallback_t; + +/* + * Function: CFE_SB_PipeId_ToIndex - See API and header file for details + */ +CFE_Status_t CFE_SB_PipeId_ToIndex(CFE_SB_PipeId_t PipeID, uint32 *Idx) +{ + return CFE_ES_ResourceID_ToIndex( + CFE_ES_ResourceID_ToInteger(PipeID) - CFE_SB_PIPEID_BASE, + CFE_PLATFORM_SB_MAX_PIPES, + Idx); +} + /* * Function: CFE_SB_CreatePipe - See API and header file for details */ @@ -91,123 +103,185 @@ int32 CFE_SB_CreatePipe(CFE_SB_PipeId_t *PipeIdPtr, uint16 Depth, const char * CFE_ES_ResourceID_t TskId; osal_id_t SysQueueId; int32 Status; - CFE_SB_PipeId_t OriginalPipeIdParamValue = (PipeIdPtr == NULL) ? 0 : (*PipeIdPtr); - CFE_SB_PipeId_t PipeTblIdx; - char AppName[OS_MAX_API_NAME] = {'\0'}; + CFE_SB_PipeD_t *PipeDscPtr; + CFE_SB_PipeId_t PendingPipeId; + uint16 PendingEventId; char FullName[(OS_MAX_API_NAME * 2)]; - /* get callers AppId */ + Status = CFE_SUCCESS; + SysQueueId = OS_OBJECT_ID_UNDEFINED; + PendingEventId = 0; + PipeDscPtr = NULL; + + /* + * Get caller AppId. + * + * This is needed for both success and failure cases, + * as it is stored in the Pipe Descriptor on success, + * and used for events on failure, so get it now. + */ CFE_ES_GetAppID(&AppId); /* get callers TaskId */ CFE_ES_GetTaskID(&TskId); - /* get callers name */ - CFE_ES_GetAppName(AppName, AppId, sizeof(AppName)); + /* check input parameters */ + if((PipeIdPtr == NULL) || (Depth > CFE_PLATFORM_SB_MAX_PIPE_DEPTH) || (Depth == 0)) + { + PendingEventId = CFE_SB_CR_PIPE_BAD_ARG_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + /* Get an available Pipe Descriptor which must be done while locked */ + CFE_SB_LockSharedData(__func__,__LINE__); - /* Hardcode a NULL terminator, in case rcvd name was too long */ - AppName[OS_MAX_API_NAME-1]= '\0'; + /* get first available entry in pipe table */ + PendingPipeId = CFE_ES_FindNextAvailableId(CFE_SB.LastPipeId, CFE_PLATFORM_SB_MAX_PIPES, CFE_SB_CheckPipeDescSlotUsed); + PipeDscPtr = CFE_SB_LocatePipeDescByID(PendingPipeId); - /* take semaphore to prevent a task switch during this call */ - CFE_SB_LockSharedData(__func__,__LINE__); + /* if pipe table is full, send event and return error */ + if(PipeDscPtr == NULL) + { + PendingEventId = CFE_SB_MAX_PIPES_MET_EID; + Status = CFE_SB_MAX_PIPES_MET; + } + else + { + /* Fully clear the entry, just in case of stale data */ + memset(PipeDscPtr, 0, sizeof(*PipeDscPtr)); - /* set user's pipe id value to 'invalid' for error cases below */ - if(PipeIdPtr != NULL){ - *PipeIdPtr = CFE_SB_INVALID_PIPE; - }/* end if */ + CFE_SB_PipeDescSetUsed(PipeDscPtr, CFE_ES_RESOURCEID_RESERVED); + CFE_SB.LastPipeId = PendingPipeId; + } - /* check input parameters */ - if((PipeIdPtr == NULL)||(Depth > CFE_PLATFORM_SB_MAX_PIPE_DEPTH)||(Depth == 0)){ - CFE_SB.HKTlmMsg.Payload.CreatePipeErrorCounter++; CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_BAD_ARG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "CreatePipeErr:Bad Input Arg:app=%s,ptr=0x%lx,depth=%d,maxdepth=%d", - CFE_SB_GetAppTskName(TskId,FullName),(unsigned long)PipeIdPtr,(int)Depth,CFE_PLATFORM_SB_MAX_PIPE_DEPTH); - return CFE_SB_BAD_ARGUMENT; - }/*end if*/ + } - /* get first available entry in pipe table */ - PipeTblIdx = CFE_SB_GetAvailPipeIdx(); + if (Status == CFE_SUCCESS) + { + /* create the queue */ + Status = OS_QueueCreate(&SysQueueId,PipeName,Depth,sizeof(CFE_SB_BufferD_t *),0); + if (Status == OS_SUCCESS) + { + /* just translate the RC to CFE */ + Status = CFE_SUCCESS; + } + else + { + if (Status == OS_ERR_NAME_TAKEN) + { + PendingEventId = CFE_SB_CR_PIPE_NAME_TAKEN_EID; + } + else if (Status == OS_ERR_NO_FREE_IDS) + { + PendingEventId = CFE_SB_CR_PIPE_NO_FREE_EID; + } + else + { + /* some other unexpected error */ + PendingEventId = CFE_SB_CR_PIPE_ERR_EID; + } - /* if pipe table is full, send event and return error */ - if(PipeTblIdx == CFE_SB_INVALID_PIPE){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_MAX_PIPES_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "CreatePipeErr:Max Pipes(%d)In Use.app %s", - CFE_PLATFORM_SB_MAX_PIPES,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_MAX_PIPES_MET; - }/* end if */ + /* translate OSAL error to CFE error code */ + Status = CFE_SB_PIPE_CR_ERR; + } + } - /* create the queue */ - Status = OS_QueueCreate(&SysQueueId,PipeName,Depth,sizeof(CFE_SB_BufferD_t *),0); - if (Status != OS_SUCCESS) { - CFE_SB_UnlockSharedData(__func__,__LINE__); + CFE_SB_LockSharedData(__func__,__LINE__); - /* if OS_QueueCreate() failed because the pipe name passed in was already in use... */ - /* let's make sure we don't alter the user's pipe ID data */ - switch(Status) { - case OS_ERR_NAME_TAKEN: - CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_NAME_TAKEN_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "CreatePipeErr:OS_QueueCreate failed, name taken (app=%s, name=%s)", - CFE_SB_GetAppTskName(TskId,FullName), PipeName); + if (Status == CFE_SUCCESS) + { + /* fill in the pipe table fields */ + PipeDscPtr->SysQueueId = SysQueueId; + PipeDscPtr->QueueDepth = Depth; + PipeDscPtr->AppId = AppId; - *PipeIdPtr = OriginalPipeIdParamValue; + CFE_SB_PipeDescSetUsed(PipeDscPtr, PendingPipeId); - break; - case OS_ERR_NO_FREE_IDS: - CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_NO_FREE_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "CreatePipeErr:OS_QueueCreate failed, no free id's (app=%s)", - CFE_SB_GetAppTskName(TskId,FullName)); + /* Increment the Pipes in use ctr and if it's > the high water mark,*/ + /* adjust the high water mark */ + CFE_SB.StatTlmMsg.Payload.PipesInUse++; + if (CFE_SB.StatTlmMsg.Payload.PipesInUse > CFE_SB.StatTlmMsg.Payload.PeakPipesInUse) + { + CFE_SB.StatTlmMsg.Payload.PeakPipesInUse = CFE_SB.StatTlmMsg.Payload.PipesInUse; + }/* end if */ + } + else + { + /* + * If a descriptor had been allocated, then free it. + */ + if (PipeDscPtr != NULL) + { + CFE_SB_PipeDescSetFree(PipeDscPtr); + PipeDscPtr = NULL; + } + PendingPipeId = CFE_ES_RESOURCEID_UNDEFINED; + /* + * If there is a relevant error counter, increment it now + * while the global data is locked. + */ + switch(PendingEventId) + { + case CFE_SB_CR_PIPE_BAD_ARG_EID: + ++CFE_SB.HKTlmMsg.Payload.CreatePipeErrorCounter; break; default: - CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "CreatePipeErr:OS_QueueCreate returned %d,app %s", - (int)Status,CFE_SB_GetAppTskName(TskId,FullName)); - }/* end switch(Status) */ - - return CFE_SB_PIPE_CR_ERR; - }/* end if */ + /* no counter */ + break; + } + } - /* fill in the pipe table fields */ - CFE_SB.PipeTbl[PipeTblIdx].InUse = CFE_SB_IN_USE; - CFE_SB.PipeTbl[PipeTblIdx].SysQueueId = SysQueueId; - CFE_SB.PipeTbl[PipeTblIdx].PipeId = PipeTblIdx; - CFE_SB.PipeTbl[PipeTblIdx].QueueDepth = Depth; - CFE_SB.PipeTbl[PipeTblIdx].AppId = AppId; - CFE_SB.PipeTbl[PipeTblIdx].SendErrors = 0; - CFE_SB.PipeTbl[PipeTblIdx].CurrentBuff = NULL; - CFE_SB.PipeTbl[PipeTblIdx].ToTrashBuff = NULL; - strcpy(&CFE_SB.PipeTbl[PipeTblIdx].AppName[0],&AppName[0]); - - /* Increment the Pipes in use ctr and if it's > the high water mark,*/ - /* adjust the high water mark */ - CFE_SB.StatTlmMsg.Payload.PipesInUse++; - if(CFE_SB.StatTlmMsg.Payload.PipesInUse > CFE_SB.StatTlmMsg.Payload.PeakPipesInUse){ - CFE_SB.StatTlmMsg.Payload.PeakPipesInUse = CFE_SB.StatTlmMsg.Payload.PipesInUse; - }/* end if */ + CFE_SB_UnlockSharedData(__func__,__LINE__); - /* Reset the pipe depth parameters in the statistics pkt */ - if (PipeTblIdx < CFE_SB_TLM_PIPEDEPTHSTATS_SIZE) + /* Send any pending events now, after final unlock */ + if (Status == CFE_SUCCESS) { - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].PipeId = PipeTblIdx; - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].Depth = Depth; - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].InUse = 0; - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].PeakInUse = 0; - } - - /* give the pipe handle to the caller */ - *PipeIdPtr = PipeTblIdx; + /* send debug event */ + CFE_EVS_SendEventWithAppID(CFE_SB_PIPE_ADDED_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "Pipe Created:name %s,id %d,app %s", + PipeName, (int)CFE_ES_ResourceID_ToInteger(PendingPipeId), + CFE_SB_GetAppTskName(TskId,FullName)); - CFE_SB_UnlockSharedData(__func__,__LINE__); + /* give the pipe handle to the caller */ + *PipeIdPtr = PendingPipeId; + } + else + { + switch(PendingEventId) + { + case CFE_SB_CR_PIPE_BAD_ARG_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_BAD_ARG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "CreatePipeErr:Bad Input Arg:app=%s,ptr=0x%lx,depth=%d,maxdepth=%d", + CFE_SB_GetAppTskName(TskId,FullName),(unsigned long)PipeIdPtr,(int)Depth,CFE_PLATFORM_SB_MAX_PIPE_DEPTH); + break; - /* send debug event */ - CFE_EVS_SendEventWithAppID(CFE_SB_PIPE_ADDED_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Pipe Created:name %s,id %d,app %s", - PipeName, (int)CFE_SB.PipeTbl[PipeTblIdx].PipeId, - CFE_SB_GetAppTskName(TskId,FullName)); + case CFE_SB_MAX_PIPES_MET_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_MAX_PIPES_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "CreatePipeErr:Max Pipes(%d)In Use.app %s", + CFE_PLATFORM_SB_MAX_PIPES,CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_CR_PIPE_NAME_TAKEN_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_NAME_TAKEN_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "CreatePipeErr:OS_QueueCreate failed, name taken (app=%s, name=%s)", + CFE_SB_GetAppTskName(TskId,FullName), PipeName); + break; + case CFE_SB_CR_PIPE_NO_FREE_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_NO_FREE_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "CreatePipeErr:OS_QueueCreate failed, no free id's (app=%s)", + CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_CR_PIPE_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_CR_PIPE_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "CreatePipeErr:OS_QueueCreate returned %d,app %s", + (int)Status,CFE_SB_GetAppTskName(TskId,FullName)); + break; + } + } - return CFE_SUCCESS; + return Status; }/* end CFE_SB_CreatePipe */ @@ -288,102 +362,143 @@ void CFE_SB_RemovePipeFromRoute(CFE_SBR_RouteId_t RouteId, void *ArgPtr) */ int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId) { - uint8 PipeTblIdx; - int32 RtnFromVal; - int32 Stat; - CFE_ES_ResourceID_t Owner; + CFE_SB_PipeD_t *PipeDscPtr; + int32 Status; CFE_ES_ResourceID_t TskId; - CFE_SB_Buffer_t *BufPtr; + CFE_SB_BufferD_t *BufDscPtr; + osal_id_t SysQueueId; char FullName[(OS_MAX_API_NAME * 2)]; + size_t BufDscSize; CFE_SB_RemovePipeCallback_t Args; + uint16 PendingEventID; - /* get TaskId and name of caller for events */ - CFE_ES_GetTaskID(&TskId); - CFE_SB_GetAppTskName(TskId, FullName); + Status = CFE_SUCCESS; + PendingEventID = 0; + SysQueueId = OS_OBJECT_ID_UNDEFINED; + BufDscPtr = NULL; /* take semaphore to prevent a task switch during this call */ CFE_SB_LockSharedData(__func__,__LINE__); - /* check input parameter */ - PipeTblIdx = CFE_SB_GetPipeIdx(PipeId); - RtnFromVal = CFE_SB_ValidatePipeId(PipeId); - if((RtnFromVal != CFE_SUCCESS)||(PipeTblIdx == CFE_SB_INVALID_PIPE)) - { - CFE_SB.HKTlmMsg.Payload.CreatePipeErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_DEL_PIPE_ERR1_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Pipe Delete Error:Bad Argument,PipedId %d,Requestor %s,Idx %d,Stat %d", - (int)PipeId,FullName,(int)PipeTblIdx,(int)RtnFromVal); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - Owner = CFE_SB.PipeTbl[PipeTblIdx].AppId; - + /* check input parameter */ + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + PendingEventID = CFE_SB_DEL_PIPE_ERR1_EID; + Status = CFE_SB_BAD_ARGUMENT; + } /* check that the given AppId is the owner of the pipe */ - if( !CFE_ES_ResourceID_Equal(AppId, Owner) ) + else if (!CFE_ES_ResourceID_Equal(AppId, PipeDscPtr->AppId)) { - CFE_SB.HKTlmMsg.Payload.CreatePipeErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_DEL_PIPE_ERR2_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Pipe Delete Error:Caller(%s) is not the owner of pipe %d", FullName, (int)PipeId); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - /* Remove the pipe from all routes */ - Args.PipeId = PipeId; - Args.FullName = FullName; - CFE_SBR_ForEachRouteId(CFE_SB_RemovePipeFromRoute, &Args, NULL); - - if (CFE_SB.PipeTbl[PipeTblIdx].ToTrashBuff != NULL) { - - /* Decrement the Buffer Use Count and Free buffer if cnt=0) */ - CFE_SB_DecrBufUseCnt(CFE_SB.PipeTbl[PipeTblIdx].ToTrashBuff); - CFE_SB.PipeTbl[PipeTblIdx].ToTrashBuff = NULL; + PendingEventID = CFE_SB_DEL_PIPE_ERR2_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + /* Remove the pipe from all routes */ + Args.PipeId = PipeId; + Args.FullName = FullName; + CFE_SBR_ForEachRouteId(CFE_SB_RemovePipeFromRoute, &Args, NULL); + + /* + * With the route removed there should be no new messages written to this pipe, + * + * but the pipe ID itself also needs to be invalidated now (before releasing lock) to make + * sure that no no subscriptions/routes can be added either. + * + * However we must first save certain state data for later deletion. + */ + SysQueueId = PipeDscPtr->SysQueueId; + BufDscPtr = PipeDscPtr->LastBuffer; + + /* + * Mark entry as "reserved" so other resources can be deleted + * while the SB global is unlocked. This prevents other tasks + * from trying to use this Pipe Desc slot, and also should prevents + * any task from re-subscribing to this pipe. + */ + CFE_SB_PipeDescSetUsed(PipeDscPtr, CFE_ES_RESOURCEID_RESERVED); + } - }/* end if */ + CFE_SB_UnlockSharedData(__func__,__LINE__); /* remove any messages that might be on the pipe */ - /* this step will free the memory used to store the message */ - do{ - CFE_SB_UnlockSharedData(__func__,__LINE__); - Stat = CFE_SB_ReceiveBuffer(&BufPtr,PipeId,CFE_SB_POLL); - CFE_SB_LockSharedData(__func__,__LINE__); - }while(Stat == CFE_SUCCESS); + if (Status == CFE_SUCCESS) + { + while(true) + { + /* decrement refcount of any previous buffer */ + if (BufDscPtr != NULL) + { + CFE_SB_LockSharedData(__func__,__LINE__); + CFE_SB_DecrBufUseCnt(BufDscPtr); + CFE_SB_UnlockSharedData(__func__,__LINE__); + BufDscPtr = NULL; + } - /* Delete the underlying OS queue */ - OS_QueueDelete(CFE_SB.PipeTbl[PipeTblIdx].SysQueueId); + if (OS_QueueGet(SysQueueId, &BufDscPtr, sizeof(BufDscPtr), &BufDscSize, OS_CHECK) != OS_SUCCESS) + { + /* no more messages */ + break; + } + } - /* remove the pipe from the pipe table */ - CFE_SB.PipeTbl[PipeTblIdx].InUse = CFE_SB_NOT_IN_USE; - CFE_SB.PipeTbl[PipeTblIdx].SysQueueId = CFE_SB_UNUSED_QUEUE; - CFE_SB.PipeTbl[PipeTblIdx].PipeId = CFE_SB_INVALID_PIPE; - CFE_SB.PipeTbl[PipeTblIdx].CurrentBuff = NULL; + /* Delete the underlying OS queue */ + OS_QueueDelete(SysQueueId); + } - /* zero out the pipe depth stats */ - if (PipeTblIdx < CFE_SB_TLM_PIPEDEPTHSTATS_SIZE) + /* + * Final cleanup with global data locked + */ + CFE_SB_LockSharedData(__func__,__LINE__); + + if (Status == CFE_SUCCESS) { - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].PipeId = 0; - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].Depth = 0; - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].InUse = 0; - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeTblIdx].PeakInUse = 0; + CFE_SB_PipeDescSetFree(PipeDscPtr); + --CFE_SB.StatTlmMsg.Payload.PipesInUse; + } + else if (PendingEventID != 0) + { + CFE_SB.HKTlmMsg.Payload.CreatePipeErrorCounter++; } - - CFE_SB.StatTlmMsg.Payload.PipesInUse--; CFE_SB_UnlockSharedData(__func__,__LINE__); - /* - * Get the app name of the actual pipe owner for the event string - * as this may be different than the task doing the deletion. - * - * Note: If this fails (e.g. bad AppID, it returns an empty string - */ - CFE_ES_GetAppName(FullName, Owner, sizeof(FullName)); + if (Status == CFE_SUCCESS) + { + /* + * Get the app name of the actual pipe owner for the event string + * as this may be different than the task doing the deletion. + * + * Note: If this fails (e.g. bad AppID, it returns an empty string + */ + CFE_ES_GetAppName(FullName, AppId, sizeof(FullName)); + + CFE_EVS_SendEventWithAppID(CFE_SB_PIPE_DELETED_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "Pipe Deleted:id %d,owner %s",(int)CFE_ES_ResourceID_ToInteger(PipeId), FullName); + } + else + { + /* get TaskId and name of caller for events */ + CFE_ES_GetTaskID(&TskId); + CFE_SB_GetAppTskName(TskId, FullName); - CFE_EVS_SendEventWithAppID(CFE_SB_PIPE_DELETED_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Pipe Deleted:id %d,owner %s",(int)PipeId, FullName); + switch (PendingEventID) + { + case CFE_SB_DEL_PIPE_ERR1_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_DEL_PIPE_ERR1_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Pipe Delete Error:Bad Argument,PipedId %ld,Requestor %s", + CFE_ES_ResourceID_ToInteger(PipeId),FullName); + break; + case CFE_SB_DEL_PIPE_ERR2_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_DEL_PIPE_ERR2_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Pipe Delete Error:Caller(%s) is not the owner of pipe %ld", + FullName, CFE_ES_ResourceID_ToInteger(PipeId)); + break; + } + } - return CFE_SUCCESS; + return Status; }/* end CFE_SB_DeletePipeFull */ @@ -393,23 +508,16 @@ int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId) */ int32 CFE_SB_SetPipeOpts(CFE_SB_PipeId_t PipeId, uint8 Opts) { - uint8 PipeTblIdx = 0; - int32 RtnFromVal = 0; - CFE_ES_ResourceID_t Owner; + CFE_SB_PipeD_t *PipeDscPtr; CFE_ES_ResourceID_t AppID; CFE_ES_ResourceID_t TskId; + uint16 PendingEventID; int32 Status; char FullName[(OS_MAX_API_NAME * 2)]; - Status = CFE_ES_GetAppID(&AppID); - if(Status != CFE_SUCCESS) - { - /* shouldn't happen... */ - return Status; - } + PendingEventID = 0; - /* get TaskId of caller for events */ - Status = CFE_ES_GetTaskID(&TskId); + Status = CFE_ES_GetAppID(&AppID); if(Status != CFE_SUCCESS) { /* shouldn't happen... */ @@ -420,47 +528,61 @@ int32 CFE_SB_SetPipeOpts(CFE_SB_PipeId_t PipeId, uint8 Opts) CFE_SB_LockSharedData(__func__,__LINE__); /* check input parameter */ - PipeTblIdx = CFE_SB_GetPipeIdx(PipeId); - RtnFromVal = CFE_SB_ValidatePipeId(PipeId); - - if((RtnFromVal != CFE_SUCCESS)||(PipeTblIdx == CFE_SB_INVALID_PIPE)) + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + if(!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) { - CFE_SB.HKTlmMsg.Payload.PipeOptsErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_SETPIPEOPTS_ID_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Pipe Opts Error:Bad Argument,PipedId %d,Requestor %s,Idx %d,Stat %d", - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName),(int)PipeTblIdx,(int)RtnFromVal); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ + PendingEventID = CFE_SB_SETPIPEOPTS_ID_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + /* check that the caller AppId is the owner of the pipe */ + else if( !CFE_ES_ResourceID_Equal(AppID, PipeDscPtr->AppId) ) + { + PendingEventID = CFE_SB_SETPIPEOPTS_OWNER_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + PipeDscPtr->Opts = Opts; + } - /* check that the given AppId is the owner of the pipe */ - Owner = CFE_SB.PipeTbl[PipeTblIdx].AppId; - if( !CFE_ES_ResourceID_Equal(AppID, Owner) ) + /* If anything went wrong, increment the error counter before unlock */ + if (Status != CFE_SUCCESS) { CFE_SB.HKTlmMsg.Payload.PipeOptsErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_SETPIPEOPTS_OWNER_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Pipe Opts Set Error: Caller(%s) is not the owner of pipe %d", - CFE_SB_GetAppTskName(TskId,FullName),(int)PipeId); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - CFE_SB.PipeTbl[PipeTblIdx].Opts = Opts; + } CFE_SB_UnlockSharedData(__func__,__LINE__); - /* - * Get the app name of the actual pipe owner for the event string - * as this may be different than the task doing the deletion. - * - * Note: If this fails (e.g. bad AppID, it returns an empty string - */ - CFE_ES_GetAppName(FullName, Owner, sizeof(FullName)); + /* Send events after unlocking SB */ + if (Status == CFE_SUCCESS) + { + /* get AppID of caller for events */ + CFE_ES_GetAppName(FullName, AppID, sizeof(FullName)); - CFE_EVS_SendEventWithAppID(CFE_SB_SETPIPEOPTS_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Pipe opts set:id %d,owner %s, opts=0x%02x",(int)PipeId, FullName, (unsigned int)Opts); + CFE_EVS_SendEventWithAppID(CFE_SB_SETPIPEOPTS_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "Pipe opts set:id %lu,owner %s, opts=0x%02x",CFE_ES_ResourceID_ToInteger(PipeId), FullName, (unsigned int)Opts); + } + else + { + /* get TaskId of caller for events */ + CFE_ES_GetTaskID(&TskId); - return CFE_SUCCESS; + switch (PendingEventID) + { + case CFE_SB_SETPIPEOPTS_ID_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SETPIPEOPTS_ID_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Pipe Opts Error:Bad Argument,PipedId %lu,Requestor %s", + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_SETPIPEOPTS_OWNER_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SETPIPEOPTS_OWNER_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Pipe Opts Set Error: Caller(%s) is not the owner of pipe %lu", + CFE_SB_GetAppTskName(TskId,FullName),CFE_ES_ResourceID_ToInteger(PipeId)); + break; + } + } + + return Status; }/* end CFE_SB_SetPipeOpts */ /* @@ -468,97 +590,162 @@ int32 CFE_SB_SetPipeOpts(CFE_SB_PipeId_t PipeId, uint8 Opts) */ int32 CFE_SB_GetPipeOpts(CFE_SB_PipeId_t PipeId, uint8 *OptsPtr) { - uint8 PipeTblIdx = 0; - int32 RtnFromVal = 0; + int32 Status; CFE_ES_ResourceID_t TskId; char FullName[(OS_MAX_API_NAME * 2)]; + uint16 PendingEventID; + CFE_SB_PipeD_t *PipeDscPtr; - /* get TaskId of caller for events */ - CFE_ES_GetTaskID(&TskId); - - if(OptsPtr == NULL) - { - CFE_SB.HKTlmMsg.Payload.PipeOptsErrorCounter++; - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEOPTS_PTR_ERR_EID, CFE_EVS_EventType_ERROR, CFE_SB.AppId, - "Pipe Opts Error:Bad Argument,Requestor %s", - CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - } + PendingEventID = 0; + Status = CFE_SUCCESS; /* take semaphore to prevent a task switch during this call */ CFE_SB_LockSharedData(__func__,__LINE__); /* check input parameter */ - PipeTblIdx = CFE_SB_GetPipeIdx(PipeId); - RtnFromVal = CFE_SB_ValidatePipeId(PipeId); + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + PendingEventID = CFE_SB_GETPIPEOPTS_ID_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else if (OptsPtr == NULL) + { + PendingEventID = CFE_SB_GETPIPEOPTS_PTR_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + *OptsPtr = PipeDscPtr->Opts; + } - if((RtnFromVal != CFE_SUCCESS)||(PipeTblIdx == CFE_SB_INVALID_PIPE)) + /* If anything went wrong, increment the error counter before unlock */ + if (Status != CFE_SUCCESS) { CFE_SB.HKTlmMsg.Payload.PipeOptsErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEOPTS_ID_ERR_EID, CFE_EVS_EventType_ERROR, CFE_SB.AppId, - "Pipe Opts Error:Bad Argument,PipedId %d,Requestor %s,Idx %d,Stat %d", - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName),(int)PipeTblIdx,(int)RtnFromVal); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - *OptsPtr = CFE_SB.PipeTbl[PipeTblIdx].Opts; + } CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEOPTS_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Pipe opts set:id %d, opts=0x%02x",(int)PipeId, (unsigned int)*OptsPtr); - return CFE_SUCCESS; + + /* Send events after unlocking SB */ + if (Status == CFE_SUCCESS) + { + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEOPTS_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "Pipe opts get:id %lu, opts=0x%02x",CFE_ES_ResourceID_ToInteger(PipeId), (unsigned int)*OptsPtr); + } + else + { + /* get TaskId of caller for events */ + CFE_ES_GetTaskID(&TskId); + + switch(PendingEventID) + { + case CFE_SB_GETPIPEOPTS_PTR_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEOPTS_PTR_ERR_EID, CFE_EVS_EventType_ERROR, CFE_SB.AppId, + "Pipe Opts Error:Bad Argument,Requestor %s", + CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_GETPIPEOPTS_ID_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEOPTS_ID_ERR_EID, CFE_EVS_EventType_ERROR, CFE_SB.AppId, + "Pipe Opts Error:Bad Argument,PipedId %lu,Requestor %s", + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); + break; + } + } + + return Status; }/* end CFE_SB_GetPipeOpts */ /* * Function: CFE_SB_GetPipeName - See API and header file for details */ -int32 CFE_SB_GetPipeName(char *PipeNameBuf, size_t PipeNameSize, CFE_SB_PipeId_t PipeId){ - OS_queue_prop_t queue_prop; - int32 Status = CFE_SUCCESS; - CFE_ES_ResourceID_t TskId; - char FullName[(OS_MAX_API_NAME * 2)]; +int32 CFE_SB_GetPipeName(char *PipeNameBuf, size_t PipeNameSize, CFE_SB_PipeId_t PipeId) +{ + int32 Status; + CFE_ES_ResourceID_t TskId; + char FullName[(OS_MAX_API_NAME * 2)]; + uint16 PendingEventID; + CFE_SB_PipeD_t *PipeDscPtr; + osal_id_t SysQueueId; - if(PipeNameBuf == NULL || PipeNameSize == 0) { - CFE_ES_GetTaskID(&TskId); - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_NULL_PTR_EID, CFE_EVS_EventType_ERROR, - CFE_SB.AppId, "Pipe Name Error:NullPtr,Requestor %s", - CFE_SB_GetAppTskName(TskId,FullName)); + PendingEventID = 0; + Status = CFE_SUCCESS; + SysQueueId = OS_OBJECT_ID_UNDEFINED; + + /* take semaphore to prevent a task switch during this call */ + CFE_SB_LockSharedData(__func__,__LINE__); + /* check input parameter */ + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + PendingEventID = CFE_SB_GETPIPENAME_ID_ERR_EID; Status = CFE_SB_BAD_ARGUMENT; - } else if(PipeId >= CFE_PLATFORM_SB_MAX_PIPES){ - CFE_ES_GetTaskID(&TskId); - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_ID_ERR_EID, CFE_EVS_EventType_ERROR, - CFE_SB.AppId, "Pipe Id Error:Bad Argument,Id=%d,Requestor %s", - PipeId,CFE_SB_GetAppTskName(TskId,FullName)); + } + else + { + SysQueueId = PipeDscPtr->SysQueueId; + } - memset(PipeNameBuf, 0, PipeNameSize); + CFE_SB_UnlockSharedData(__func__,__LINE__); - Status = CFE_SB_BAD_ARGUMENT; - }else{ - if (OS_QueueGetInfo(CFE_SB.PipeTbl[PipeId].SysQueueId, &queue_prop) - == OS_SUCCESS){ - strncpy(PipeNameBuf, queue_prop.name, PipeNameSize-1); + if (Status == CFE_SUCCESS) + { + if (PipeNameBuf == NULL || PipeNameSize == 0) + { + PendingEventID = CFE_SB_GETPIPENAME_NULL_PTR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + Status = OS_GetResourceName(SysQueueId, PipeNameBuf, PipeNameSize); - PipeNameBuf[PipeNameSize-1] = '\0'; + if (Status == OS_SUCCESS) + { + Status = CFE_SUCCESS; + } + else + { + PendingEventID = CFE_SB_GETPIPENAME_ID_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + } + } - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_EID, + /* Send Events */ + if (Status == CFE_SUCCESS) + { + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_EID, CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "GetPipeName name=%s id=%d", - PipeNameBuf, PipeId); - } else{ - CFE_ES_GetTaskID(&TskId); - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_ID_ERR_EID, CFE_EVS_EventType_ERROR, - CFE_SB.AppId, "Pipe Id Error:Bad Argument,Id=%d,Requestor %s", - PipeId,CFE_SB_GetAppTskName(TskId,FullName)); + "GetPipeName name=%s id=%lu", + PipeNameBuf, CFE_ES_ResourceID_ToInteger(PipeId)); + } + else + { + CFE_ES_GetTaskID(&TskId); - memset(PipeNameBuf, 0, PipeNameSize); + switch(PendingEventID) + { + case CFE_SB_GETPIPENAME_NULL_PTR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_NULL_PTR_EID, CFE_EVS_EventType_ERROR, + CFE_SB.AppId, "Pipe Name Error:NullPtr,Requestor %s", + CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_GETPIPENAME_ID_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPENAME_ID_ERR_EID, CFE_EVS_EventType_ERROR, + CFE_SB.AppId, "Pipe Id Error:Bad Argument,Id=%lu,Requestor %s", + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); + break; + } - Status = CFE_SB_BAD_ARGUMENT; - }/* end if */ - }/* end if */ + if (PipeNameBuf != NULL && PipeNameSize > 0) + { + memset(PipeNameBuf, 0, PipeNameSize); + } + } return Status; + }/* end CFE_SB_GetPipeName */ /* @@ -566,89 +753,103 @@ int32 CFE_SB_GetPipeName(char *PipeNameBuf, size_t PipeNameSize, CFE_SB_PipeId_t */ int32 CFE_SB_GetPipeIdByName(CFE_SB_PipeId_t *PipeIdPtr, const char *PipeName) { - uint8 PipeTblIdx = 0; - int32 Status = CFE_SUCCESS; - int32 RtnFromVal = 0; + int32 Status; CFE_ES_ResourceID_t TskId; - osal_id_t QueueId; + uint32 Idx; char FullName[(OS_MAX_API_NAME * 2)]; + uint16 PendingEventID; + CFE_SB_PipeD_t *PipeDscPtr; + osal_id_t SysQueueId; - /* get TaskId of caller for events */ - CFE_ES_GetTaskID(&TskId); + PendingEventID = 0; + Status = CFE_SUCCESS; + SysQueueId = OS_OBJECT_ID_UNDEFINED; if(PipeName == NULL || PipeIdPtr == NULL) { - CFE_SB.HKTlmMsg.Payload.GetPipeIdByNameErrorCounter++; - - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEIDBYNAME_NULL_ERR_EID, CFE_EVS_EventType_ERROR, CFE_SB.AppId, - "Pipe ID By Name Error:Bad Argument,Requestor %s", - CFE_SB_GetAppTskName(TskId,FullName)); - + PendingEventID = CFE_SB_GETPIPEIDBYNAME_NULL_ERR_EID; Status = CFE_SB_BAD_ARGUMENT; } else { - RtnFromVal = OS_QueueGetIdByName(&QueueId, PipeName); - - if(RtnFromVal == OS_SUCCESS) + /* Get QueueID from OSAL */ + Status = OS_QueueGetIdByName(&SysQueueId, PipeName); + if (Status == OS_SUCCESS) { - /* take semaphore to prevent a task switch while iterating - * through the PipeTbl. - */ - CFE_SB_LockSharedData(__func__,__LINE__); + Status = CFE_SUCCESS; + } + else + { + PendingEventID = CFE_SB_GETPIPEIDBYNAME_NAME_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + } + + CFE_SB_LockSharedData(__func__,__LINE__); - for(PipeTblIdx = 0; - PipeTblIdx < CFE_PLATFORM_SB_MAX_PIPES; - PipeTblIdx++) + if (Status == CFE_SUCCESS) + { + Idx = CFE_PLATFORM_SB_MAX_PIPES; + PipeDscPtr = CFE_SB.PipeTbl; + while(true) + { + if (Idx == 0) { - if(CFE_SB.PipeTbl[PipeTblIdx].InUse != 0 - && OS_ObjectIdEqual(CFE_SB.PipeTbl[PipeTblIdx].SysQueueId, QueueId)) - { - /* grab the ID before we release the lock */ - *PipeIdPtr = CFE_SB.PipeTbl[PipeTblIdx].PipeId; + PendingEventID = CFE_SB_GETPIPEIDBYNAME_NAME_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + break; + } - break; - }/* end if */ + if (OS_ObjectIdEqual(PipeDscPtr->SysQueueId, SysQueueId)) + { + /* grab the ID before we release the lock */ + *PipeIdPtr = CFE_SB_PipeDescGetID(PipeDscPtr); + break; + }/* end if */ - }/* end for */ + --Idx; + ++PipeDscPtr; + } + } + + if (Status != CFE_SUCCESS) + { + ++CFE_SB.HKTlmMsg.Payload.GetPipeIdByNameErrorCounter; + } - CFE_SB_UnlockSharedData(__func__,__LINE__); + CFE_SB_UnlockSharedData(__func__,__LINE__); - if(PipeTblIdx == CFE_PLATFORM_SB_MAX_PIPES) - { - /* should never get here! */ - CFE_SB.HKTlmMsg.Payload.GetPipeIdByNameErrorCounter++; + /* Send Events */ + if (Status == CFE_SUCCESS) + { + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEIDBYNAME_EID, + CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "PipeIdByName name=%s id=%lu", + PipeName, CFE_ES_ResourceID_ToInteger(*PipeIdPtr)); + } + else + { + /* get TaskId of caller for events */ + CFE_ES_GetTaskID(&TskId); + + switch(PendingEventID) + { + case CFE_SB_GETPIPEIDBYNAME_NULL_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEIDBYNAME_NULL_ERR_EID, + CFE_EVS_EventType_ERROR, CFE_SB.AppId, + "Pipe ID By Name Error:Bad Argument,Requestor %s", + CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_GETPIPEIDBYNAME_NAME_ERR_EID: CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEIDBYNAME_NAME_ERR_EID, CFE_EVS_EventType_ERROR, CFE_SB.AppId, "Pipe ID By Name Error:Bad Argument,Requestor %s", CFE_SB_GetAppTskName(TskId,FullName)); + break; - Status = CFE_SB_BAD_ARGUMENT; - } - else - { - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEIDBYNAME_EID, - CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "PipeIdByName name=%s id=%d", - PipeName, *PipeIdPtr); - - Status = CFE_SUCCESS; - } } - else - { - CFE_SB.HKTlmMsg.Payload.GetPipeIdByNameErrorCounter++; - - CFE_EVS_SendEventWithAppID(CFE_SB_GETPIPEIDBYNAME_NAME_ERR_EID, - CFE_EVS_EventType_ERROR, CFE_SB.AppId, - "Pipe ID By Name Error:Bad Argument,Requestor %s", - CFE_SB_GetAppTskName(TskId,FullName)); - - Status = CFE_SB_BAD_ARGUMENT; - }/* end if */ - - }/* end if */ + } return Status; @@ -731,17 +932,21 @@ int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, uint8 Scope) { CFE_SBR_RouteId_t RouteId; - int32 Stat; - CFE_ES_ResourceID_t TskId; + CFE_SB_PipeD_t *PipeDscPtr; + int32 Status; + CFE_ES_ResourceID_t TskId; CFE_ES_ResourceID_t AppId; - uint8 PipeIdx; - CFE_SB_DestinationD_t *DestPtr = NULL; - uint32 DestCount = 0; + CFE_SB_DestinationD_t *DestPtr; + uint32 DestCount; char FullName[(OS_MAX_API_NAME * 2)]; - char PipeName[OS_MAX_API_NAME] = {'\0'}; - uint32 Collisions = 0; + char PipeName[OS_MAX_API_NAME]; + uint32 Collisions; + uint16 PendingEventID; - CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); + PendingEventID = 0; + Status = CFE_SUCCESS; + DestPtr = NULL; + Collisions = 0; /* get the callers Application Id */ CFE_ES_GetAppID(&AppId); @@ -753,153 +958,208 @@ int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, CFE_SB_LockSharedData(__func__,__LINE__); /* check that the pipe has been created */ - PipeIdx = CFE_SB_GetPipeIdx(PipeId); - if(PipeIdx==CFE_SB_INVALID_PIPE){ - CFE_SB.HKTlmMsg.Payload.SubscribeErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_SUB_INV_PIPE_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Invalid Pipe Id,Msg=0x%x,PipeId=%d,App %s",(unsigned int)CFE_SB_MsgIdToValue(MsgId), - (int)PipeId, CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - /* check that the requestor is the owner of the pipe */ - if( !CFE_ES_ResourceID_Equal(CFE_SB.PipeTbl[PipeIdx].AppId, AppId)){ - CFE_SB.HKTlmMsg.Payload.SubscribeErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_SUB_INV_CALLER_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Caller(%s) is not the owner of pipe %d,Msg=0x%x", - CFE_SB_GetAppTskName(TskId,FullName),(int)PipeId,(unsigned int)CFE_SB_MsgIdToValue(MsgId)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + PendingEventID = CFE_SB_SUB_INV_PIPE_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else if (!CFE_ES_ResourceID_Equal(PipeDscPtr->AppId, AppId)) + { + PendingEventID = CFE_SB_SUB_INV_CALLER_EID; + Status = CFE_SB_BAD_ARGUMENT; + } /* check message id key and scope */ - if(!CFE_SB_IsValidMsgId(MsgId) || (Scope > 1)) + else if (!CFE_SB_IsValidMsgId(MsgId) || (Scope > 1)) { - CFE_SB.HKTlmMsg.Payload.SubscribeErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_SUB_ARG_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Bad Arg,MsgId 0x%x,PipeId %d,app %s,scope %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName),Scope); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - RouteId = CFE_SBR_GetRouteId(MsgId); - if (CFE_SBR_IsValidRouteId(RouteId)) + PendingEventID = CFE_SB_SUB_ARG_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else { - /* check for duplicate subscription */ - if(CFE_SB_GetDestPtr(RouteId, PipeId) != NULL) + /* Get the route, adding one if it does not exist already */ + RouteId = CFE_SBR_GetRouteId(MsgId); + + if (!CFE_SBR_IsValidRouteId(RouteId)) { - CFE_SB.HKTlmMsg.Payload.DuplicateSubscriptionsCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_DUP_SUBSCRIP_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, - "Duplicate Subscription,MsgId 0x%x on %s pipe,app %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SUCCESS; + /* Add the route */ + RouteId = CFE_SBR_AddRoute(MsgId, &Collisions); + + /* if all routing table elements are used, send event */ + if (!CFE_SBR_IsValidRouteId(RouteId)) + { + PendingEventID = CFE_SB_MAX_MSGS_MET_EID; + Status = CFE_SB_MAX_MSGS_MET; + } + else + { + /* Increment the MsgIds in use ctr and if it's > the high water mark,*/ + /* adjust the high water mark */ + CFE_SB.StatTlmMsg.Payload.MsgIdsInUse++; + if(CFE_SB.StatTlmMsg.Payload.MsgIdsInUse > CFE_SB.StatTlmMsg.Payload.PeakMsgIdsInUse) + { + CFE_SB.StatTlmMsg.Payload.PeakMsgIdsInUse = CFE_SB.StatTlmMsg.Payload.MsgIdsInUse; + }/* end if */ + } } + } - /* Check for destination limit */ - for (DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); DestPtr != NULL; DestPtr = DestPtr->Next) + /* If successful up to this point, check if new dest should be added to this route */ + if (Status == CFE_SUCCESS) + { + DestCount = 0; + for (DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); + DestPtr != NULL; + DestPtr = DestPtr->Next) { - DestCount++; + ++DestCount; + + /* Check if duplicate (status stays as CFE_SUCCESS) */ + if (CFE_ES_ResourceID_Equal(DestPtr->PipeId, PipeId)) + { + PendingEventID = CFE_SB_DUP_SUBSCRIP_EID; + break; + } + + /* Check if limit reached */ + if (DestCount >= CFE_PLATFORM_SB_MAX_DEST_PER_PKT) + { + PendingEventID = CFE_SB_MAX_DESTS_MET_EID; + Status = CFE_SB_MAX_DESTS_MET; + break; + } + } - if(DestCount >= CFE_PLATFORM_SB_MAX_DEST_PER_PKT){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_MAX_DESTS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Max Dests(%d)In Use For Msg 0x%x,pipe %s,app %s", - CFE_PLATFORM_SB_MAX_DEST_PER_PKT, - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName, CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_MAX_DESTS_MET; + /* If no existing dest found, add one now */ + if (DestPtr == NULL) + { + DestPtr = CFE_SB_GetDestinationBlk(); + if(DestPtr == NULL) + { + PendingEventID = CFE_SB_DEST_BLK_ERR_EID; + Status = CFE_SB_BUF_ALOC_ERR; + } + else + { + /* initialize destination block */ + DestPtr->PipeId = PipeId; + DestPtr->MsgId2PipeLim = MsgLim; + DestPtr->Active = CFE_SB_ACTIVE; + DestPtr->BuffCount = 0; + DestPtr->DestCnt = 0; + DestPtr->Scope = Scope; + DestPtr->Prev = NULL; + DestPtr->Next = NULL; + + /* add destination node */ + CFE_SB_AddDestNode(RouteId, DestPtr); + + CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse++; + if(CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse > CFE_SB.StatTlmMsg.Payload.PeakSubscriptionsInUse) + { + CFE_SB.StatTlmMsg.Payload.PeakSubscriptionsInUse = CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse; + } + } } } - else + + /* Increment counter before unlock */ + switch(PendingEventID) { - /* Add the route */ - RouteId = CFE_SBR_AddRoute(MsgId, &Collisions); + case CFE_SB_SUB_INV_PIPE_EID: + case CFE_SB_SUB_INV_CALLER_EID: + case CFE_SB_SUB_ARG_ERR_EID: + case CFE_SB_MAX_MSGS_MET_EID: + case CFE_SB_DEST_BLK_ERR_EID: + case CFE_SB_MAX_DESTS_MET_EID: + CFE_SB.HKTlmMsg.Payload.SubscribeErrorCounter++; + break; + case CFE_SB_DUP_SUBSCRIP_EID: + CFE_SB.HKTlmMsg.Payload.DuplicateSubscriptionsCounter++; + break; + } - /* if all routing table elements are used, send event */ - if(!CFE_SBR_IsValidRouteId(RouteId)){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_MAX_MSGS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Max Msgs(%d)In Use,MsgId 0x%x,pipe %s,app %s", - CFE_PLATFORM_SB_MAX_MSG_IDS, - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_MAX_MSGS_MET; - }/* end if */ + CFE_SB_UnlockSharedData(__func__,__LINE__); - /* Increment the MsgIds in use ctr and if it's > the high water mark,*/ - /* adjust the high water mark */ - CFE_SB.StatTlmMsg.Payload.MsgIdsInUse++; - if(CFE_SB.StatTlmMsg.Payload.MsgIdsInUse > CFE_SB.StatTlmMsg.Payload.PeakMsgIdsInUse){ - CFE_SB.StatTlmMsg.Payload.PeakMsgIdsInUse = CFE_SB.StatTlmMsg.Payload.MsgIdsInUse; - }/* end if */ + /* Send events now */ + if (PendingEventID != 0) + { + CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); - }/* end if */ + switch(PendingEventID) + { + case CFE_SB_DUP_SUBSCRIP_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_DUP_SUBSCRIP_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, + "Duplicate Subscription,MsgId 0x%x on %s pipe,app %s", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + PipeName,CFE_SB_GetAppTskName(TskId,FullName)); + break; + + case CFE_SB_SUB_INV_CALLER_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SUB_INV_CALLER_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Caller(%s) is not the owner of pipe %lu,Msg=0x%x", + CFE_SB_GetAppTskName(TskId,FullName),CFE_ES_ResourceID_ToInteger(PipeId), + (unsigned int)CFE_SB_MsgIdToValue(MsgId)); + break; + + case CFE_SB_SUB_INV_PIPE_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SUB_INV_PIPE_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Invalid Pipe Id,Msg=0x%x,PipeId=%lu,App %s", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(PipeId), CFE_SB_GetAppTskName(TskId,FullName)); + break; - DestPtr = CFE_SB_GetDestinationBlk(); - if(DestPtr == NULL){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_DEST_BLK_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Request for Destination Blk failed for Msg 0x%x", - (unsigned int)CFE_SB_MsgIdToValue(MsgId)); - return CFE_SB_BUF_ALOC_ERR; - }/* end if */ + case CFE_SB_DEST_BLK_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_DEST_BLK_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Request for Destination Blk failed for Msg 0x%x", + (unsigned int)CFE_SB_MsgIdToValue(MsgId)); + break; - /* initialize destination block */ - DestPtr->PipeId = PipeId; - DestPtr->MsgId2PipeLim = (uint16)MsgLim; - DestPtr->Active = CFE_SB_ACTIVE; - DestPtr->BuffCount = 0; - DestPtr->DestCnt = 0; - DestPtr->Scope = Scope; - DestPtr->Prev = NULL; - DestPtr->Next = NULL; + case CFE_SB_MAX_DESTS_MET_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_MAX_DESTS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Max Dests(%d)In Use For Msg 0x%x,pipe %s,app %s", + CFE_PLATFORM_SB_MAX_DEST_PER_PKT, (unsigned int)CFE_SB_MsgIdToValue(MsgId), + PipeName, CFE_SB_GetAppTskName(TskId,FullName)); + break; - /* add destination node */ - CFE_SB_AddDestNode(RouteId, DestPtr); + case CFE_SB_MAX_MSGS_MET_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_MAX_MSGS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Max Msgs(%d)In Use,MsgId 0x%x,pipe %s,app %s", + CFE_PLATFORM_SB_MAX_MSG_IDS, (unsigned int)CFE_SB_MsgIdToValue(MsgId), + PipeName, CFE_SB_GetAppTskName(TskId,FullName)); + break; - CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse++; - if(CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse > CFE_SB.StatTlmMsg.Payload.PeakSubscriptionsInUse) + case CFE_SB_SUB_ARG_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SUB_ARG_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Bad Arg,MsgId 0x%x,PipeId %lu,app %s,scope %d", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName),Scope); + break; + } + } + else if (Status == CFE_SUCCESS) { - CFE_SB.StatTlmMsg.Payload.PeakSubscriptionsInUse = CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse; - }/* end if */ - - if((CFE_SB.SubscriptionReporting == CFE_SB_ENABLE)&&(Scope==CFE_SB_GLOBAL)){ - CFE_SB.SubRprtMsg.Payload.MsgId = MsgId; - CFE_SB.SubRprtMsg.Payload.Pipe = PipeId; - CFE_SB.SubRprtMsg.Payload.Qos.Priority = Quality.Priority; - CFE_SB.SubRprtMsg.Payload.Qos.Reliability = Quality.Reliability; - CFE_SB.SubRprtMsg.Payload.SubType = CFE_SB_SUBSCRIPTION; - CFE_SB_UnlockSharedData(__func__,__LINE__); - Stat = CFE_SB_TransmitMsg(&CFE_SB.SubRprtMsg.Hdr.Msg, true); - CFE_EVS_SendEventWithAppID(CFE_SB_SUBSCRIPTION_RPT_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Sending Subscription Report Msg=0x%x,Pipe=%d,Stat=0x%x", + /* If no other event pending, send a debug event indicating success */ + CFE_EVS_SendEventWithAppID(CFE_SB_SUBSCRIPTION_RCVD_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "Subscription Rcvd:MsgId 0x%x on %s(%lu),app %s", (unsigned int)CFE_SB_MsgIdToValue(MsgId), - (int)PipeId,(unsigned int)Stat); - CFE_SB_LockSharedData(__func__,__LINE__);/* to prevent back-to-back unlock */ - }/* end if */ - - /* release the semaphore */ - CFE_SB_UnlockSharedData(__func__,__LINE__); + PipeName,CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); + } - CFE_EVS_SendEventWithAppID(CFE_SB_SUBSCRIPTION_RCVD_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Subscription Rcvd:MsgId 0x%x on %s(%d),app %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName,(int)PipeId,CFE_SB_GetAppTskName(TskId,FullName)); + if (Status == CFE_SUCCESS && Scope == CFE_SB_GLOBAL) + { + CFE_SB_SendSubscriptionReport(MsgId, PipeId, Quality); + } if (Collisions != 0) { CFE_EVS_SendEventWithAppID(CFE_SB_HASHCOLLISION_EID, CFE_EVS_EventType_DEBUG, CFE_SB.AppId, - "Msg hash collision: MsgId = 0x%x, collisions = %u", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), (unsigned int)Collisions); + "Msg hash collision: MsgId = 0x%x, collisions = %u", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), (unsigned int)Collisions); } - return CFE_SUCCESS; + return Status; }/* end CFE_SB_SubscribeFull */ @@ -1006,12 +1266,18 @@ int32 CFE_SB_UnsubscribeWithAppId(CFE_SB_MsgId_t MsgId, int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId,CFE_SB_PipeId_t PipeId, uint8 Scope,CFE_ES_ResourceID_t AppId) { + int32 Status; CFE_SBR_RouteId_t RouteId; - uint32 PipeIdx; CFE_ES_ResourceID_t TskId; - CFE_SB_DestinationD_t *DestPtr = NULL; + CFE_SB_DestinationD_t *DestPtr; char FullName[(OS_MAX_API_NAME * 2)]; - char PipeName[OS_MAX_API_NAME] = {'\0'}; + char PipeName[OS_MAX_API_NAME]; + CFE_SB_PipeD_t *PipeDscPtr; + uint16 PendingEventID; + + PendingEventID = 0; + Status = CFE_SUCCESS; + DestPtr = NULL; /* get TaskId of caller for events */ CFE_ES_GetTaskID(&TskId); @@ -1020,83 +1286,98 @@ int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId,CFE_SB_PipeId_t PipeId, CFE_SB_LockSharedData(__func__,__LINE__); /* check that the pipe has been created */ - PipeIdx = CFE_SB_GetPipeIdx(PipeId); - if(PipeIdx==CFE_SB_INVALID_PIPE){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_INV_PIPE_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Unsubscribe Err:Invalid Pipe Id Msg=0x%x,Pipe=%d,app=%s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + PendingEventID = CFE_SB_UNSUB_INV_PIPE_EID; + Status = CFE_SB_BAD_ARGUMENT; + } /* if given 'AppId' is not the owner of the pipe, send error event and return */ - if( !CFE_ES_ResourceID_Equal(CFE_SB.PipeTbl[PipeIdx].AppId, AppId) ) - { - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_INV_CALLER_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Unsubscribe Err:Caller(%s) is not the owner of pipe %d,Msg=0x%x", - CFE_SB_GetAppTskName(TskId,FullName),(int)PipeId, - (unsigned int)CFE_SB_MsgIdToValue(MsgId)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - + else if (!CFE_ES_ResourceID_Equal(PipeDscPtr->AppId, AppId)) + { + PendingEventID = CFE_SB_UNSUB_INV_CALLER_EID; + Status = CFE_SB_BAD_ARGUMENT; + } /* check input parameters */ - if(!CFE_SB_IsValidMsgId(MsgId) || - (CFE_SB_ValidatePipeId(PipeId) != CFE_SUCCESS)|| - (Scope > 1)) + else if (!CFE_SB_IsValidMsgId(MsgId) || (Scope > 1)) { - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_ARG_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "UnSubscribe Err:Bad Arg,MsgId 0x%x,PipeId %d,app %s,scope %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName),(int)Scope); - return CFE_SB_BAD_ARGUMENT; + PendingEventID = CFE_SB_UNSUB_ARG_ERR_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + /* get routing id */ + RouteId = CFE_SBR_GetRouteId(MsgId); + + /* if there have never been subscriptions for this message id... */ + if(!CFE_SBR_IsValidRouteId(RouteId)) + { + PendingEventID = CFE_SB_UNSUB_NO_SUBS_EID; + /* Status stays CFE_SUCCESS here */ + } + else + { + /* Get the destination pointer */ + DestPtr = CFE_SB_GetDestPtr(RouteId, PipeId); + + if(DestPtr != NULL) + { + /* match found, remove destination */ + CFE_SB_RemoveDest(RouteId,DestPtr); + } + else + { + PendingEventID = CFE_SB_UNSUB_NO_SUBS_EID; + } + } }/* end if */ - /* get routing id */ - RouteId = CFE_SBR_GetRouteId(MsgId); + CFE_SB_UnlockSharedData(__func__,__LINE__); - /* if there have never been subscriptions for this message id... */ - if(!CFE_SBR_IsValidRouteId(RouteId)) + if (PendingEventID != 0) { - CFE_SB_UnlockSharedData(__func__,__LINE__); - - CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); + switch(PendingEventID) + { + case CFE_SB_UNSUB_NO_SUBS_EID: + CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); + CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_NO_SUBS_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, + "Unsubscribe Err:No subs for Msg 0x%x on %s,app %s", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + PipeName,CFE_SB_GetAppTskName(TskId,FullName)); + break; - CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_NO_SUBS_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, - "Unsubscribe Err:No subs for Msg 0x%x on %s,app %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SUCCESS; - }/* end if */ + case CFE_SB_UNSUB_INV_PIPE_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_INV_PIPE_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Unsubscribe Err:Invalid Pipe Id Msg=0x%x,Pipe=%lu,app=%s", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); + break; - /* Get the destination pointer */ - DestPtr = CFE_SB_GetDestPtr(RouteId, PipeId); + case CFE_SB_UNSUB_INV_CALLER_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_INV_CALLER_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Unsubscribe Err:Caller(%s) is not the owner of pipe %lu,Msg=0x%x", + CFE_SB_GetAppTskName(TskId,FullName),CFE_ES_ResourceID_ToInteger(PipeId), + (unsigned int)CFE_SB_MsgIdToValue(MsgId)); + break; - if(DestPtr != NULL) + case CFE_SB_UNSUB_ARG_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_ARG_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "UnSubscribe Err:Bad Arg,MsgId 0x%x,PipeId %lu,app %s,scope %d", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName),(int)Scope); + break; + } + } + else if (Status == CFE_SUCCESS) { - /* match found, remove destination */ - CFE_SB_RemoveDest(RouteId,DestPtr); - + /* if no other event pending, send a debug event for successful unsubscribe */ CFE_EVS_SendEventWithAppID(CFE_SB_SUBSCRIPTION_REMOVED_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, - "Subscription Removed:Msg 0x%x on pipe %d,app %s", + "Subscription Removed:Msg 0x%x on pipe %lu,app %s", (unsigned int)CFE_SB_MsgIdToValue(MsgId), - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName)); + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); } - else - { - CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); - - CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_NO_SUBS_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, - "Unsubscribe Err:No subs for Msg 0x%x on %s,app %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName,CFE_SB_GetAppTskName(TskId,FullName)); - }/* end if */ - CFE_SB_UnlockSharedData(__func__,__LINE__); - - return CFE_SUCCESS; + return Status; }/* end CFE_SB_UnsubscribeFull */ /* @@ -1112,31 +1393,22 @@ int32 CFE_SB_TransmitMsg(CFE_MSG_Message_t *MsgPtr, bool IncrementSequenceCount CFE_SB_BufferD_t *BufDscPtr; CFE_SBR_RouteId_t RouteId; CFE_MSG_Type_t MsgType; + uint16 PendingEventID; - /* Get task id for events and Sender Info*/ - CFE_ES_GetTaskID(&TskId); + PendingEventID = 0; + BufDscPtr = NULL; Status = CFE_SB_TransmitMsgValidate(MsgPtr, &MsgId, &Size, &RouteId); - /* Copy into buffer and send if route exists */ if (Status == CFE_SUCCESS && CFE_SBR_IsValidRouteId(RouteId)) { + CFE_SB_LockSharedData(__func__, __LINE__); + /* Get buffer */ BufDscPtr = CFE_SB_GetBufferFromPool(MsgId, Size); if (BufDscPtr == NULL) { - /* Determine if event can be sent without causing recursive event problem */ - if(CFE_SB_RequestToSendEvent(TskId,CFE_SB_GET_BUF_ERR_EID_BIT) == CFE_SB_GRANTED) - { - CFE_EVS_SendEventWithAppID(CFE_SB_GET_BUF_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Send Err:Request for Buffer Failed. MsgId 0x%x,app %s,size %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - CFE_SB_GetAppTskName(TskId,FullName),(int)Size); - - /* clear the bit so the task may send this event again */ - CFE_SB_FinishSendEvent(TskId,CFE_SB_GET_BUF_ERR_EID_BIT); - } - + PendingEventID = CFE_SB_GET_BUF_ERR_EID; Status = CFE_SB_BUF_ALOC_ERR; } else @@ -1148,21 +1420,43 @@ int32 CFE_SB_TransmitMsg(CFE_MSG_Message_t *MsgPtr, bool IncrementSequenceCount CFE_SBR_IncrementSequenceCounter(RouteId); CFE_MSG_SetSequenceCount(MsgPtr, CFE_SBR_GetSequenceCounter(RouteId)); } - - /* Copy data into buffer and transmit */ - memcpy(BufDscPtr->Buffer, MsgPtr, Size); - Status = CFE_SB_TransmitBufferFull(BufDscPtr, RouteId, MsgId); } + + CFE_SB_UnlockSharedData(__func__, __LINE__); + } + + if (Status == CFE_SUCCESS && BufDscPtr != NULL) + { + /* Copy data into buffer and transmit */ + memcpy(BufDscPtr->Buffer, MsgPtr, Size); + Status = CFE_SB_TransmitBufferFull(BufDscPtr, RouteId, MsgId); } if (Status != CFE_SUCCESS) { - /* Increment error counter (inside lock) if not success */ + /* Increment error counter (inside lock) if not success */ CFE_SB_LockSharedData(__func__, __LINE__); CFE_SB.HKTlmMsg.Payload.MsgSendErrorCounter++; CFE_SB_UnlockSharedData(__func__, __LINE__); } + if (PendingEventID == CFE_SB_GET_BUF_ERR_EID) + { + /* Get task id for events and Sender Info*/ + CFE_ES_GetTaskID(&TskId); + + if (CFE_SB_RequestToSendEvent(TskId,CFE_SB_GET_BUF_ERR_EID_BIT) == CFE_SB_GRANTED) + { + CFE_EVS_SendEventWithAppID(CFE_SB_GET_BUF_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Send Err:Request for Buffer Failed. MsgId 0x%x,app %s,size %d", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_SB_GetAppTskName(TskId,FullName),(int)Size); + + /* clear the bit so the task may send this event again */ + CFE_SB_FinishSendEvent(TskId,CFE_SB_GET_BUF_ERR_EID_BIT); + } + } + return Status; } @@ -1210,67 +1504,107 @@ int32 CFE_SB_TransmitMsgValidate(CFE_MSG_Message_t *MsgPtr, { CFE_ES_ResourceID_t TskId; char FullName[(OS_MAX_API_NAME * 2)]; + uint16 PendingEventID; + int32 Status; - /* get task id for events and Sender Info*/ - CFE_ES_GetTaskID(&TskId); + PendingEventID = 0; + Status = CFE_SUCCESS; /* check input parameter */ - if(MsgPtr == NULL) + if (MsgPtr == NULL) { - CFE_EVS_SendEventWithAppID(CFE_SB_SEND_BAD_ARG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Send Err:Bad input argument,Arg 0x%lx,App %s", - (unsigned long)MsgPtr,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - CFE_MSG_GetMsgId(MsgPtr, MsgIdPtr); + PendingEventID = CFE_SB_SEND_BAD_ARG_EID; + Status = CFE_SB_BAD_ARGUMENT; + } - /* validate the msgid in the message */ - if(!CFE_SB_IsValidMsgId(*MsgIdPtr)) + if (Status == CFE_SUCCESS) { - CFE_EVS_SendEventWithAppID(CFE_SB_SEND_INV_MSGID_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Send Err:Invalid MsgId(0x%x)in msg,App %s", - (unsigned int)CFE_SB_MsgIdToValue(*MsgIdPtr), - CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ + CFE_MSG_GetMsgId(MsgPtr, MsgIdPtr); - CFE_MSG_GetSize(MsgPtr, SizePtr); + /* validate the msgid in the message */ + if(!CFE_SB_IsValidMsgId(*MsgIdPtr)) + { + PendingEventID = CFE_SB_SEND_INV_MSGID_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + } - /* Verify the size of the pkt is < or = the mission defined max */ - if(*SizePtr > CFE_MISSION_SB_MAX_SB_MSG_SIZE) + if (Status == CFE_SUCCESS) { - CFE_EVS_SendEventWithAppID(CFE_SB_MSG_TOO_BIG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Send Err:Msg Too Big MsgId=0x%x,app=%s,size=%d,MaxSz=%d", - (unsigned int)CFE_SB_MsgIdToValue(*MsgIdPtr), - CFE_SB_GetAppTskName(TskId,FullName),(int)*SizePtr,CFE_MISSION_SB_MAX_SB_MSG_SIZE); - return CFE_SB_MSG_TOO_BIG; - }/* end if */ + CFE_MSG_GetSize(MsgPtr, SizePtr); + + /* Verify the size of the pkt is < or = the mission defined max */ + if(*SizePtr > CFE_MISSION_SB_MAX_SB_MSG_SIZE) + { + PendingEventID = CFE_SB_MSG_TOO_BIG_EID; + Status = CFE_SB_MSG_TOO_BIG; + }/* end if */ + } + + if (Status == CFE_SUCCESS) + { + /* check the route, which should be done while locked */ + CFE_SB_LockSharedData(__func__, __LINE__); + + /* Get the routing id */ + *RouteIdPtr = CFE_SBR_GetRouteId(*MsgIdPtr); - /* Get the routing id */ - *RouteIdPtr = CFE_SBR_GetRouteId(*MsgIdPtr); + /* if there have been no subscriptions for this pkt, */ + /* increment the dropped pkt cnt, send event and return success */ + if(!CFE_SBR_IsValidRouteId(*RouteIdPtr)) + { + CFE_SB.HKTlmMsg.Payload.NoSubscribersCounter++; + PendingEventID = CFE_SB_SEND_NO_SUBS_EID; + } + + CFE_SB_UnlockSharedData(__func__, __LINE__); + } + + if (PendingEventID != 0) + { + /* get task id for events */ + CFE_ES_GetTaskID(&TskId); - /* if there have been no subscriptions for this pkt, */ - /* increment the dropped pkt cnt, send event and return success */ - if(!CFE_SBR_IsValidRouteId(*RouteIdPtr)){ + switch (PendingEventID) + { + case CFE_SB_SEND_BAD_ARG_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SEND_BAD_ARG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Send Err:Bad input argument,Arg 0x%lx,App %s", + (unsigned long)MsgPtr,CFE_SB_GetAppTskName(TskId,FullName)); + break; - CFE_SB.HKTlmMsg.Payload.NoSubscribersCounter++; + case CFE_SB_SEND_INV_MSGID_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_SEND_INV_MSGID_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Send Err:Invalid MsgId(0x%x)in msg,App %s", + (unsigned int)CFE_SB_MsgIdToValue(*MsgIdPtr), + CFE_SB_GetAppTskName(TskId,FullName)); + break; - /* Determine if event can be sent without causing recursive event problem */ - if(CFE_SB_RequestToSendEvent(TskId,CFE_SB_SEND_NO_SUBS_EID_BIT) == CFE_SB_GRANTED){ + case CFE_SB_MSG_TOO_BIG_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_MSG_TOO_BIG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Send Err:Msg Too Big MsgId=0x%x,app=%s,size=%d,MaxSz=%d", + (unsigned int)CFE_SB_MsgIdToValue(*MsgIdPtr), + CFE_SB_GetAppTskName(TskId,FullName),(int)*SizePtr,CFE_MISSION_SB_MAX_SB_MSG_SIZE); + break; - CFE_EVS_SendEventWithAppID(CFE_SB_SEND_NO_SUBS_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, - "No subscribers for MsgId 0x%x,sender %s", - (unsigned int)CFE_SB_MsgIdToValue(*MsgIdPtr), - CFE_SB_GetAppTskName(TskId,FullName)); + case CFE_SB_SEND_NO_SUBS_EID: + /* Determine if event can be sent without causing recursive event problem */ + if (CFE_SB_RequestToSendEvent(TskId,CFE_SB_SEND_NO_SUBS_EID_BIT) == CFE_SB_GRANTED) + { + CFE_EVS_SendEventWithAppID(CFE_SB_SEND_NO_SUBS_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, + "No subscribers for MsgId 0x%x,sender %s", + (unsigned int)CFE_SB_MsgIdToValue(*MsgIdPtr), + CFE_SB_GetAppTskName(TskId,FullName)); - /* clear the bit so the task may send this event again */ - CFE_SB_FinishSendEvent(TskId,CFE_SB_SEND_NO_SUBS_EID_BIT); - }/* end if */ + /* clear the bit so the task may send this event again */ + CFE_SB_FinishSendEvent(TskId,CFE_SB_SEND_NO_SUBS_EID_BIT); + }/* end if */ + break; + } }/* end if */ - return CFE_SUCCESS; + return Status; } /*****************************************************************************/ @@ -1290,12 +1624,14 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, CFE_ES_ResourceID_t TskId; CFE_SB_DestinationD_t *DestPtr; CFE_SB_PipeD_t *PipeDscPtr; - CFE_SB_EventBuf_t SBSndErr = {0}; - char PipeName[OS_MAX_API_NAME] = {'\0'}; - CFE_SB_PipeDepthStats_t *StatObj; + CFE_SB_EventBuf_t SBSndErr; int32 Status; uint32 i; char FullName[(OS_MAX_API_NAME * 2)]; + char PipeName[OS_MAX_API_NAME]; + + Status = CFE_SUCCESS; + SBSndErr.EvtsToSnd = 0; /* get app id for loopback testing */ CFE_ES_GetAppID(&AppId); @@ -1309,23 +1645,30 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, /* Send the packet to all destinations */ for(DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); DestPtr != NULL; DestPtr = DestPtr->Next) { - if (DestPtr->Active == CFE_SB_INACTIVE) /* destination is active */ + if (DestPtr->Active == CFE_SB_ACTIVE) /* destination is active */ { - continue; - }/*end if */ + PipeDscPtr = CFE_SB_LocatePipeDescByID(DestPtr->PipeId); + } + else + { + PipeDscPtr = NULL; + } - PipeDscPtr = &CFE_SB.PipeTbl[DestPtr->PipeId]; + if (!CFE_SB_PipeDescIsMatch(PipeDscPtr, DestPtr->PipeId)) + { + continue; + } if((PipeDscPtr->Opts & CFE_SB_PIPEOPTS_IGNOREMINE) != 0 && - CFE_ES_ResourceID_Equal(PipeDscPtr->AppId, AppId)) + CFE_ES_ResourceID_Equal(PipeDscPtr->AppId, AppId)) { continue; }/* end if */ /* if Msg limit exceeded, log event, increment counter */ /* and go to next destination */ - if(DestPtr->BuffCount >= DestPtr->MsgId2PipeLim){ - + if(DestPtr->BuffCount >= DestPtr->MsgId2PipeLim) + { SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_MSGID_LIM_ERR_EID; SBSndErr.EvtsToSnd++; @@ -1343,38 +1686,42 @@ int32 CFE_SB_TransmitBufferFull(CFE_SB_BufferD_t *BufDscPtr, if (Status == OS_SUCCESS) { - BufDscPtr->UseCount++; /* used for releasing buffer */ + /* The queue now holds a ref to the buffer, so increment its ref count. */ + CFE_SB_IncrBufUseCnt(BufDscPtr); + DestPtr->BuffCount++; /* used for checking MsgId2PipeLimit */ DestPtr->DestCnt++; /* used for statistics */ - if (DestPtr->PipeId < CFE_SB_TLM_PIPEDEPTHSTATS_SIZE) + ++PipeDscPtr->QueueDepth; + if (PipeDscPtr->QueueDepth >= PipeDscPtr->PeakDepth) { - StatObj = &CFE_SB.StatTlmMsg.Payload.PipeDepthStats[DestPtr->PipeId]; - StatObj->InUse++; - if(StatObj->InUse > StatObj->PeakInUse) - { - StatObj->PeakInUse = StatObj->InUse; - }/* end if */ + PipeDscPtr->PeakDepth = PipeDscPtr->QueueDepth; } + + Status = CFE_SUCCESS; } - else if(Status == OS_QUEUE_FULL) + else { - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_FULL_ERR_EID; - SBSndErr.EvtsToSnd++; - CFE_SB.HKTlmMsg.Payload.PipeOverflowErrorCounter++; - PipeDscPtr->SendErrors++; + if (Status == OS_QUEUE_FULL) + { + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_FULL_ERR_EID; + SBSndErr.EvtsToSnd++; + CFE_SB.HKTlmMsg.Payload.PipeOverflowErrorCounter++; + PipeDscPtr->SendErrors++; + } + else + { + /* Unexpected error while writing to queue. */ + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_WR_ERR_EID; + SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].ErrStat = Status; + SBSndErr.EvtsToSnd++; + CFE_SB.HKTlmMsg.Payload.InternalErrorCounter++; + PipeDscPtr->SendErrors++; + }/*end if */ + + Status = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; } - else - { - /* Unexpected error while writing to queue. */ - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_WR_ERR_EID; - SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].ErrStat = Status; - SBSndErr.EvtsToSnd++; - CFE_SB.HKTlmMsg.Payload.InternalErrorCounter++; - PipeDscPtr->SendErrors++; - }/*end if */ - } /* end loop over destinations */ /* @@ -1472,120 +1819,252 @@ int32 CFE_SB_ReceiveBuffer(CFE_SB_Buffer_t **BufPtr, int32 TimeOut) { int32 Status; - CFE_SB_BufferD_t *Message; + int32 RcvStatus; + CFE_SB_BufferD_t *BufDscPtr; + size_t BufDscSize; CFE_SB_PipeD_t *PipeDscPtr; - CFE_SB_DestinationD_t *DestPtr = NULL; + CFE_SB_DestinationD_t *DestPtr; CFE_SBR_RouteId_t RouteId; CFE_ES_ResourceID_t TskId; + uint16 PendingEventID; + osal_id_t SysQueueId; + int32 SysTimeout; char FullName[(OS_MAX_API_NAME * 2)]; - /* get task id for events */ - CFE_ES_GetTaskID(&TskId); - - /* Check input parameters */ - if((BufPtr == NULL)||(TimeOut < (-1))){ - CFE_SB_LockSharedData(__func__,__LINE__); - CFE_SB.HKTlmMsg.Payload.MsgReceiveErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_RCV_BAD_ARG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Rcv Err:Bad Input Arg:BufPtr 0x%lx,pipe %d,t/o %d,app %s", - (unsigned long)BufPtr,(int)PipeId,(int)TimeOut,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - PipeDscPtr = CFE_SB_GetPipePtr(PipeId); - /* If the pipe does not exist or PipeId is out of range... */ - if (PipeDscPtr == NULL) { - CFE_SB_LockSharedData(__func__,__LINE__); - CFE_SB.HKTlmMsg.Payload.MsgReceiveErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_BAD_PIPEID_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Rcv Err:PipeId %d does not exist,app %s", - (int)PipeId,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SB_BAD_ARGUMENT; - }/* end if */ - - /* - ** Save off any currently in use buffer to free later; this allows - ** one fewer shared data locks - */ - - PipeDscPtr->ToTrashBuff = PipeDscPtr->CurrentBuff; - PipeDscPtr->CurrentBuff = NULL; - + PendingEventID = 0; + Status = CFE_SUCCESS; + SysTimeout = OS_PEND; + SysQueueId = OS_OBJECT_ID_UNDEFINED; + PipeDscPtr = NULL; + BufDscPtr = NULL; + DestPtr = NULL; + BufDscSize = 0; + /* - ** Read a new buffer from the queue of the pipe, using the - ** specified timeout option. If a buffer was obtained, return the - ** packet to the task according to mode. Otherwise, return a status - ** code indicating that no buffer was read. - */ - Status = CFE_SB_ReadQueue(PipeDscPtr, TskId, TimeOut, &Message); - - /* take semaphore again to protect the remaining code in this call */ - CFE_SB_LockSharedData(__func__,__LINE__); - - /* free any pending trash buffer */ - if (PipeDscPtr->ToTrashBuff != NULL) { - - /* Decrement the Buffer Use Count and Free buffer if cnt=0) */ - CFE_SB_DecrBufUseCnt(PipeDscPtr->ToTrashBuff); + * Check input args and see if any are bad, which require + * a "BAD_ARG_EID" to be generated. + * + * Also translate the timeout here. Timeouts greater than 0 + * may be passed to OSAL directly, but the two fixed constants + * CFE_SB_PEND_FOREVER and CFE_SB_POLL are checked explicitly, + * to maintain API independence - even though the values are + * currently defined the same. + */ - PipeDscPtr->ToTrashBuff = NULL; + if (BufPtr == NULL) + { + PendingEventID = CFE_SB_RCV_BAD_ARG_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else if (TimeOut > 0) + { + /* time outs greater than 0 can be passed to OSAL directly */ + SysTimeout = TimeOut; + } + else if (TimeOut == CFE_SB_POLL) + { + SysTimeout = OS_CHECK; + } + else if (TimeOut != CFE_SB_PEND_FOREVER) + { + /* any other timeout value is invalid */ + PendingEventID = CFE_SB_RCV_BAD_ARG_EID; + Status = CFE_SB_BAD_ARGUMENT; + } - }/* end if */ + /* If OK, then lock and pull relevent info from Pipe Descriptor */ + if (Status == CFE_SUCCESS) + { + CFE_SB_LockSharedData(__func__,__LINE__); - if (Status == CFE_SUCCESS) { + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); - /* - ** Load the pipe tables 'CurrentBuff' with the buffer descriptor - ** ptr corresponding to the message just read. This is done so that - ** the buffer can be released on the next receive call for this pipe. - */ - PipeDscPtr->CurrentBuff = Message; + /* If the pipe does not exist or PipeId is out of range... */ + if(!CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + PendingEventID = CFE_SB_BAD_PIPEID_EID; + Status = CFE_SB_BAD_ARGUMENT; + } + else + { + /* Grab the queue ID */ + SysQueueId = PipeDscPtr->SysQueueId; + + /* + * Un-reference any previous buffer from the last call. + * + * NOTE: This is historical behavior where apps call CFE_SB_ReceiveBuffer() + * in the loop within the app's main task. There is currently no separate + * API to "free" or unreference a buffer that was returned from SB. + * + * Instead, each time this function is invoked, it is implicitly interpreted + * as an indication that the caller is done with the previous buffer. + * + * Unfortunately this prevents pipe IDs from being serviced/shared across + * multiple child tasks in a worker pattern design. This may be changed + * in a future version of CFE to decouple these actions, to allow for + * multiple workers to service the same pipe. + */ + if (PipeDscPtr->LastBuffer != NULL) + { + /* Decrement the Buffer Use Count, which will Free buffer if it becomes 0 */ + CFE_SB_DecrBufUseCnt(PipeDscPtr->LastBuffer); + PipeDscPtr->LastBuffer = NULL; + } + } - /* Set the Receivers pointer to the address of the actual message */ - *BufPtr = (CFE_SB_Buffer_t *) Message->Buffer; + CFE_SB_UnlockSharedData(__func__,__LINE__); + } - /* get pointer to destination to be used in decrementing msg limit cnt*/ - RouteId = CFE_SBR_GetRouteId(PipeDscPtr->CurrentBuff->MsgId); - DestPtr = CFE_SB_GetDestPtr(RouteId, PipeDscPtr->PipeId); + /* + * If everything validated, then proceed to get a buffer from the queue. + * This must be done OUTSIDE the SB lock, as this call likely blocks. + */ + if (Status == CFE_SUCCESS) + { + /* Read the buffer descriptor address from the queue. */ + RcvStatus = OS_QueueGet(SysQueueId, + &BufDscPtr, + sizeof(BufDscPtr), + &BufDscSize, + SysTimeout); + + /* + * translate the return value - + * + * CFE functions have their own set of RC values should not directly return OSAL codes + * The size should always match. If it does not, then generate CFE_SB_Q_RD_ERR_EID. + */ + if(RcvStatus == OS_SUCCESS && BufDscPtr != NULL && BufDscSize == sizeof(BufDscPtr)) + { + /* Pass through */ + } + else if (RcvStatus == OS_QUEUE_EMPTY) + { + /* normal if using CFE_SB_POLL */ + Status = CFE_SB_NO_MESSAGE; + } + else if (RcvStatus == OS_QUEUE_TIMEOUT) + { + /* normal if using a nonzero timeout */ + Status = CFE_SB_TIME_OUT; + } + else + { + /* off-nominal condition, report an error event */ + PendingEventID = CFE_SB_Q_RD_ERR_EID; + Status = CFE_SB_PIPE_RD_ERR; + } + } - /* - ** DestPtr would be NULL if the msg is unsubscribed to while it is on - ** the pipe. The BuffCount may be zero if the msg is unsubscribed to and - ** then resubscribed to while it is on the pipe. Both of these cases are - ** considered nominal and are handled by the code below. - */ - if(DestPtr != NULL){ + /* Now re-lock to store the buffer in the pipe descriptor */ + CFE_SB_LockSharedData(__func__,__LINE__); - if (DestPtr->BuffCount > 0){ + if (Status == CFE_SUCCESS) + { + /* + * NOTE: This uses the same PipeDscPtr that was found earlier. + * Technically it is possible that the pipe was changed between now and then, + * but the current PipeID definition doesn't really allow this to be detected. + */ + if (CFE_SB_PipeDescIsMatch(PipeDscPtr, PipeId)) + { + /* + ** Load the pipe tables 'CurrentBuff' with the buffer descriptor + ** ptr corresponding to the message just read. This is done so that + ** the buffer can be released on the next receive call for this pipe. + ** + ** This counts as a new reference as it is being stored in the PipeDsc + */ + CFE_SB_IncrBufUseCnt(BufDscPtr); + PipeDscPtr->LastBuffer = BufDscPtr; + + /* + * Also set the Receivers pointer to the address of the actual message + * (currently this is "borrowing" the ref above, not its own ref) + */ + *BufPtr = BufDscPtr->Buffer; + + /* get pointer to destination to be used in decrementing msg limit cnt*/ + RouteId = CFE_SBR_GetRouteId(BufDscPtr->MsgId); + DestPtr = CFE_SB_GetDestPtr(RouteId, PipeId); + + /* + ** DestPtr would be NULL if the msg is unsubscribed to while it is on + ** the pipe. The BuffCount may be zero if the msg is unsubscribed to and + ** then resubscribed to while it is on the pipe. Both of these cases are + ** considered nominal and are handled by the code below. + */ + if (DestPtr != NULL && DestPtr->BuffCount > 0) + { DestPtr->BuffCount--; } - }/* end if DestPtr != NULL */ + if (PipeDscPtr->CurrentDepth > 0) + { + --PipeDscPtr->CurrentDepth; + } + } + else + { + /* should send the bad pipe ID event here too */ + PendingEventID = CFE_SB_BAD_PIPEID_EID; + Status = CFE_SB_PIPE_RD_ERR; + } + + /* Always decrement the use count, for the ref that was in the queue */ + CFE_SB_DecrBufUseCnt(BufDscPtr); + } - if (PipeDscPtr->PipeId < CFE_SB_TLM_PIPEDEPTHSTATS_SIZE) + /* Before unlocking, check the PendingEventID and increment relevant error counter */ + if (Status != CFE_SUCCESS) + { + if (PendingEventID == CFE_SB_RCV_BAD_ARG_EID || PendingEventID == CFE_SB_BAD_PIPEID_EID) + { + ++CFE_SB.HKTlmMsg.Payload.MsgReceiveErrorCounter; + } + else { - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeDscPtr->PipeId].InUse--; + /* For any other unexpected error (e.g. CFE_SB_Q_RD_ERR_EID) */ + ++CFE_SB.HKTlmMsg.Payload.InternalErrorCounter; } + } - }else{ + CFE_SB_UnlockSharedData(__func__,__LINE__); - /* Set the users pointer to NULL indicating the CFE_SB_ReadQueue failed */ - *BufPtr = NULL; + /* Now actually send the event, after unlocking (do not call EVS with SB locked) */ + if (PendingEventID != 0) + { + /* get task id for events */ + CFE_ES_GetTaskID(&TskId); - }/* end if */ + switch(PendingEventID) + { + case CFE_SB_Q_RD_ERR_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_Q_RD_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Pipe Read Err,pipe %lu,app %s,stat 0x%x", + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName),(unsigned int)RcvStatus); + break; + case CFE_SB_RCV_BAD_ARG_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_RCV_BAD_ARG_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Rcv Err:Bad Input Arg:BufPtr 0x%lx,pipe %lu,t/o %d,app %s", + (unsigned long)BufPtr,CFE_ES_ResourceID_ToInteger(PipeId),(int)TimeOut,CFE_SB_GetAppTskName(TskId,FullName)); + break; + case CFE_SB_BAD_PIPEID_EID: + CFE_EVS_SendEventWithAppID(CFE_SB_BAD_PIPEID_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Rcv Err:PipeId %lu does not exist,app %s", + CFE_ES_ResourceID_ToInteger(PipeId),CFE_SB_GetAppTskName(TskId,FullName)); + break; + } + } - /* release the semaphore */ - CFE_SB_UnlockSharedData(__func__,__LINE__); + /* If not successful, set the output pointer to NULL */ + if (Status != CFE_SUCCESS && BufPtr != NULL) + { + *BufPtr = NULL; + } - /* - ** If status is not CFE_SUCCESS, then no packet was received. If this was - ** caused by an unexpected error, then CFE_SB_ReadQueue() will report the - ** error. - */ return Status; - } @@ -1672,7 +2151,7 @@ CFE_SB_Buffer_t *CFE_SB_ZeroCopyGetPtr(size_t MsgSize, /* Initialize the buffer descriptor structure. */ bd->UseCount = 1; bd->Size = MsgSize; - bd->Buffer = (void *)address; + bd->Buffer = (CFE_SB_Buffer_t *)address; return (CFE_SB_Buffer_t *)address; @@ -1862,99 +2341,3 @@ int32 CFE_SB_ZeroCopyPass(CFE_SB_Buffer_t *BufPtr, }/* end CFE_SB_ZeroCopyPass */ #endif - -/****************************************************************************** -** Function: CFE_SB_ReadQueue() -** -** Purpose: -** Read an SB message from the system queue. The message is represented -** by a pointer to the buffer descriptor of the message. Several options -** are available for the timeout, as described below. -** -** Arguments: -** PipeDscPtr: Pointer to pipe descriptor. -** AppId : Application ID of the receiving task (used for error messages). -** Time_Out : Timeout option; one of the following: -** CFE_SB_PEND_FOREVER = wait forever until a packet arrives -** CFE_SB_POLL = check the pipe for packets but don't wait -** value in milliseconds = wait up to a specified time -** Message : Pointer to a variable that will receive the buffer -** descriptor of the message. -** -** Return: -** CFE_SB status code indicating the result of the operation: -** CFE_SUCCESS = message was successfully read -** CFE_SB_NO_MESSAGE = no message is present (for CFE_SB_POLL option) -** CFE_SB_TIME_OUT = timeout expired (for timeout option) -** CFE_SB_PIPE_RD_ERR = an unexpected queue read error occurred -*/ - -int32 CFE_SB_ReadQueue (CFE_SB_PipeD_t *PipeDscPtr, - CFE_ES_ResourceID_t TskId, - uint32 Time_Out, - CFE_SB_BufferD_t **Message) -{ - int32 Status,TimeOut; - size_t Nbytes; - char FullName[(OS_MAX_API_NAME * 2)]; - char PipeName[OS_MAX_API_NAME] = {'\0'}; - - /* translate the given Time_Out value */ - switch(Time_Out){ - - case CFE_SB_PEND_FOREVER: - TimeOut = OS_PEND; - break; - - case CFE_SB_POLL: - TimeOut = OS_CHECK; - break; - - default: - TimeOut = Time_Out; - break; - - }/* end switch */ - - /* Read the buffer descriptor address from the queue. */ - Status = OS_QueueGet(PipeDscPtr->SysQueueId, - (void *)Message, - sizeof(CFE_SB_BufferD_t *), - &Nbytes, - TimeOut); - - /* translate the return value */ - switch(Status){ - - case OS_SUCCESS: - Status = CFE_SUCCESS; - break; - - case OS_QUEUE_EMPTY: - Status = CFE_SB_NO_MESSAGE; - break; - - case OS_QUEUE_TIMEOUT: - Status = CFE_SB_TIME_OUT; - break; - - default: - CFE_SB_LockSharedData(__func__,__LINE__); - CFE_SB.HKTlmMsg.Payload.InternalErrorCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - /* Unexpected error while reading the queue. */ - CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeDscPtr->PipeId); - CFE_EVS_SendEventWithAppID(CFE_SB_Q_RD_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Pipe Read Err,pipe %s,app %s,stat 0x%x", - PipeName,CFE_SB_GetAppTskName(TskId,FullName),(unsigned int)Status); - - Status = CFE_SB_PIPE_RD_ERR; - break; - - }/* end switch */ - - return (Status); -}/* end CFE_SB_ReadQueue */ - -/*****************************************************************************/ - diff --git a/fsw/cfe-core/src/sb/cfe_sb_buf.c b/fsw/cfe-core/src/sb/cfe_sb_buf.c index e213a12e6..8bb1b7a83 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_buf.c +++ b/fsw/cfe-core/src/sb/cfe_sb_buf.c @@ -91,7 +91,7 @@ CFE_SB_BufferD_t * CFE_SB_GetBufferFromPool(CFE_SB_MsgId_t MsgId, size_t Size) { bd->MsgId = MsgId; bd->UseCount = 1; bd->Size = Size; - bd->Buffer = (void *)address; + bd->Buffer = (CFE_SB_Buffer_t *)address; return bd; @@ -156,6 +156,32 @@ int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd){ }/* end CFE_SB_ReturnBufferToPool */ +/****************************************************************************** +** Function: CFE_SB_IncrBufUseCnt() +** +** Purpose: +** This function will increment the UseCount of a particular buffer. +** +** Note: +** UseCount is a variable in the CFE_SB_BufferD_t and is used only to +** determine when a buffer may be returned to the memory pool. +** +** Arguments: +** bd : Pointer to the buffer descriptor. +** +** Return: +** CFE_SUCCESS for normal operation. +*/ +void CFE_SB_IncrBufUseCnt(CFE_SB_BufferD_t *bd) +{ + /* range check the UseCount variable */ + if(bd->UseCount < 0x7FFF) + { + ++bd->UseCount; + } + +}/* end CFE_SB_DecrBufUseCnt */ + /****************************************************************************** ** Function: CFE_SB_DecrBufUseCnt() @@ -175,21 +201,19 @@ int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd){ ** Return: ** CFE_SUCCESS for normal operation. */ -int32 CFE_SB_DecrBufUseCnt(CFE_SB_BufferD_t *bd){ - +void CFE_SB_DecrBufUseCnt(CFE_SB_BufferD_t *bd) +{ /* range check the UseCount variable */ - if(bd->UseCount > 0){ - - bd->UseCount--; + if(bd->UseCount > 0) + { + --bd->UseCount; - if (bd->UseCount == 0) { + if (bd->UseCount == 0) + { CFE_SB_ReturnBufferToPool(bd); - }/* end if */ - + } } - return CFE_SUCCESS; - }/* end CFE_SB_DecrBufUseCnt */ diff --git a/fsw/cfe-core/src/sb/cfe_sb_init.c b/fsw/cfe-core/src/sb/cfe_sb_init.c index e9a35cfb4..b5b2c1a4a 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_init.c +++ b/fsw/cfe-core/src/sb/cfe_sb_init.c @@ -87,6 +87,9 @@ int32 CFE_SB_EarlyInit (void) { int32 Stat; + /* ensure entire CFE_SB global data structure is purged first */ + memset(&CFE_SB, 0, sizeof(CFE_SB)); + CFE_SB_Default_Qos.Priority = CFE_SB_QOS_LOW_PRIORITY; CFE_SB_Default_Qos.Reliability = CFE_SB_QOS_LOW_RELIABILITY; @@ -178,16 +181,9 @@ int32 CFE_SB_InitBuffers(void) { ** Return: ** none */ -void CFE_SB_InitPipeTbl(void){ - - uint8 i; - - for(i=0;i /****************************************************************************** @@ -97,88 +98,43 @@ ** Return: ** None */ -int32 CFE_SB_CleanUpApp(CFE_ES_ResourceID_t AppId){ - - uint32 i; - - /* loop through the pipe table looking for pipes owned by AppId */ - for(i=0;iAppId, AppId)) + { + DelList[DelCount] = CFE_SB_PipeDescGetID(PipeDscPtr); + ++DelCount; + } + ++PipeDscPtr; + } - /* search the pipe table for the for the given pipe id */ - for(i=0;iPipeId == PipeId) + if( CFE_ES_ResourceID_Equal(destptr->PipeId, PipeId) ) { break; } @@ -348,31 +274,39 @@ int32 CFE_SB_ValidateMsgId(CFE_SB_MsgId_t MsgId){ }/* end CFE_SB_ValidateMsgId */ +/*********************************************************************/ +/* + * CFE_SB_LocatePipeDescByID + * + * For complete API information, see prototype in header + */ +CFE_SB_PipeD_t *CFE_SB_LocatePipeDescByID(CFE_SB_PipeId_t PipeId) +{ + CFE_SB_PipeD_t *PipeDscPtr; + uint32 Idx; -/****************************************************************************** -** Function: CFE_SB_ValidatePipeId() -** -** Purpose: -** This function checks that the pipe id does not have an index larger than the -** array and that the pipe is in use. -** -** Arguments: -** -** Return: -** None -*/ -int32 CFE_SB_ValidatePipeId(CFE_SB_PipeId_t PipeId){ - - if((PipeId >= CFE_PLATFORM_SB_MAX_PIPES)|| - (CFE_SB.PipeTbl[PipeId].InUse == CFE_SB_NOT_IN_USE)) + if (CFE_SB_PipeId_ToIndex(PipeId, &Idx) == CFE_SUCCESS) { - return CFE_SB_FAILED; - }else{ - return CFE_SUCCESS; - }/* end if */ + PipeDscPtr = &CFE_SB.PipeTbl[Idx]; + } + else + { + PipeDscPtr = NULL; + } -}/* end CFE_SB_ValidatePipeId */ + return PipeDscPtr; +} +/*********************************************************************/ +/* + * CFE_SB_CheckPipeDescSlotUsed + * + * Checks if a table slot is used or not (helper for allocating IDs) + */ +bool CFE_SB_CheckPipeDescSlotUsed(CFE_SB_PipeId_t CheckId) +{ + return CFE_SB_PipeDescIsUsed(CFE_SB_LocatePipeDescByID(CheckId)); +} /****************************************************************************** ** Function: CFE_SB_GetAppTskName() @@ -618,4 +552,3 @@ int32 CFE_SB_ZeroCopyReleaseAppId(CFE_ES_ResourceID_t AppId) }/* end CFE_SB_ZeroCopyReleasePtr */ /*****************************************************************************/ - diff --git a/fsw/cfe-core/src/sb/cfe_sb_priv.h b/fsw/cfe-core/src/sb/cfe_sb_priv.h index f8a0ff05a..4888434f1 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_priv.h +++ b/fsw/cfe-core/src/sb/cfe_sb_priv.h @@ -43,13 +43,13 @@ #include "cfe_time.h" #include "cfe_es.h" #include "private/cfe_sbr.h" +#include "private/cfe_resourceid_internal.h" /* ** Macro Definitions */ #define CFE_SB_UNUSED_QUEUE OS_OBJECT_ID_UNDEFINED -#define CFE_SB_INVALID_PIPE 0xFF #define CFE_SB_NO_DESTINATION 0xFF #define CFE_SB_FAILED 1 #define SB_DONT_CARE 0 @@ -117,7 +117,7 @@ typedef struct { CFE_SB_MsgId_t MsgId; uint16 UseCount; size_t Size; - void *Buffer; + CFE_SB_Buffer_t *Buffer; } CFE_SB_BufferD_t; /****************************************************************************** @@ -148,18 +148,16 @@ typedef struct { */ typedef struct { - uint8 InUse; - CFE_SB_PipeId_t PipeId; - char AppName[OS_MAX_API_NAME]; - uint8 Opts; - uint8 Spare; + CFE_SB_PipeId_t PipeId; + uint8 Opts; + uint8 Spare; CFE_ES_ResourceID_t AppId; - osal_id_t SysQueueId; - uint32 LastSender; - uint16 QueueDepth; - uint16 SendErrors; - CFE_SB_BufferD_t *CurrentBuff; - CFE_SB_BufferD_t *ToTrashBuff; + osal_id_t SysQueueId; + uint16 QueueDepth; + uint16 SendErrors; + uint16 CurrentDepth; + uint16 PeakDepth; + CFE_SB_BufferD_t *LastBuffer; } CFE_SB_PipeD_t; /****************************************************************************** @@ -196,8 +194,8 @@ typedef struct CFE_SB_PipeId_t CmdPipe; CFE_SB_MemParams_t Mem; CFE_SB_AllSubscriptionsTlm_t PrevSubMsg; - CFE_SB_SingleSubscriptionTlm_t SubRprtMsg; CFE_EVS_BinFilter_t EventFilters[CFE_SB_MAX_CFG_FILE_EVENTS_TO_FILTER]; + CFE_SB_PipeId_t LastPipeId; } cfe_sb_t; @@ -238,11 +236,8 @@ void CFE_SB_ResetCounts(void); void CFE_SB_LockSharedData(const char *FuncName, int32 LineNumber); void CFE_SB_UnlockSharedData(const char *FuncName, int32 LineNumber); void CFE_SB_ReleaseBuffer (CFE_SB_BufferD_t *bd, CFE_SB_DestinationD_t *dest); -int32 CFE_SB_ReadQueue(CFE_SB_PipeD_t *PipeDscPtr,CFE_ES_ResourceID_t TskId, - uint32 Time_Out,CFE_SB_BufferD_t **Message ); int32 CFE_SB_WriteQueue(CFE_SB_PipeD_t *pd,uint32 TskId, const CFE_SB_BufferD_t *bd,CFE_SB_MsgId_t MsgId ); -uint8 CFE_SB_GetPipeIdx(CFE_SB_PipeId_t PipeId); int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd); void CFE_SB_ProcessCmdPipePkt(CFE_SB_Buffer_t *SBBufPtr); void CFE_SB_ResetCounters(void); @@ -250,8 +245,6 @@ void CFE_SB_SetMsgSeqCnt(CFE_MSG_Message_t *MsgPtr,uint32 Count); char *CFE_SB_GetAppTskName(CFE_ES_ResourceID_t TaskId, char* FullName); CFE_SB_BufferD_t *CFE_SB_GetBufferFromPool(CFE_SB_MsgId_t MsgId, size_t Size); CFE_SB_BufferD_t *CFE_SB_GetBufferFromCaller(CFE_SB_MsgId_t MsgId, void *Address); -CFE_SB_PipeD_t *CFE_SB_GetPipePtr(CFE_SB_PipeId_t PipeId); -CFE_SB_PipeId_t CFE_SB_GetAvailPipeIdx(void); int32 CFE_SB_DeletePipeWithAppId(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId); int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId); int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, @@ -277,12 +270,14 @@ int32 CFE_SB_SendPipeInfo(const char *Filename); int32 CFE_SB_SendMapInfo(const char *Filename); int32 CFE_SB_ZeroCopyReleaseDesc(CFE_SB_Buffer_t *Ptr2Release, CFE_SB_ZeroCopyHandle_t BufferHandle); int32 CFE_SB_ZeroCopyReleaseAppId(CFE_ES_ResourceID_t AppId); -int32 CFE_SB_DecrBufUseCnt(CFE_SB_BufferD_t *bd); +void CFE_SB_IncrBufUseCnt(CFE_SB_BufferD_t *bd); +void CFE_SB_DecrBufUseCnt(CFE_SB_BufferD_t *bd); int32 CFE_SB_ValidateMsgId(CFE_SB_MsgId_t MsgId); int32 CFE_SB_ValidatePipeId(CFE_SB_PipeId_t PipeId); void CFE_SB_IncrCmdCtr(int32 status); void CFE_SB_FileWriteByteCntErr(const char *Filename,uint32 Requested,uint32 Actual); void CFE_SB_SetSubscriptionReporting(uint32 state); +int32 CFE_SB_SendSubscriptionReport(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId, CFE_SB_Qos_t Quality); uint32 CFE_SB_RequestToSendEvent(CFE_ES_ResourceID_t TaskId, uint32 Bit); void CFE_SB_FinishSendEvent(CFE_ES_ResourceID_t TaskId, uint32 Bit); CFE_SB_DestinationD_t *CFE_SB_GetDestinationBlk(void); @@ -381,6 +376,104 @@ int32 CFE_SB_SendMapInfoCmd(const CFE_SB_SendMapInfoCmd_t *data); int32 CFE_SB_SendPrevSubsCmd(const CFE_SB_SendPrevSubsCmd_t *data); + +/** + * @brief Locate the Pipe table entry correlating with a given Pipe ID. + * + * This only returns a pointer to the table entry and does _not_ + * otherwise check/validate the entry. + * + * @param[in] PipeId the Pipe ID to locate + * @return pointer to Pipe Table entry for the given Pipe ID + */ +extern CFE_SB_PipeD_t* CFE_SB_LocatePipeDescByID(CFE_SB_PipeId_t PipeId); + + + +/** + * @brief Check if an Pipe descriptor is in use or free/empty + * + * This routine checks if the Pipe table entry is in use or if it is free + * + * As this dereferences fields within the descriptor, global data must be + * locked prior to invoking this function. + * + * @param[in] PipeDscPtr pointer to Pipe table entry + * @returns true if the entry is in use/configured, or false if it is free/empty + */ +static inline bool CFE_SB_PipeDescIsUsed(const CFE_SB_PipeD_t *PipeDscPtr) +{ + return CFE_ES_ResourceID_IsDefined(PipeDscPtr->PipeId); +} + +/** + * @brief Get the ID value from an Pipe table entry + * + * This routine converts the table entry back to an abstract ID. + * + * @param[in] PipeDscPtr pointer to Pipe table entry + * @returns PipeID of entry + */ +static inline CFE_SB_PipeId_t CFE_SB_PipeDescGetID(const CFE_SB_PipeD_t *PipeDscPtr) +{ + return PipeDscPtr->PipeId; +} + +/** + * @brief Marks an Pipe table entry as used (not free) + * + * This sets the internal field(s) within this entry, and marks + * it as being associated with the given Pipe ID. + * + * As this dereferences fields within the descriptor, global data must be + * locked prior to invoking this function. + * + * @param[in] PipeDscPtr pointer to Pipe table entry + * @param[in] PipeID the Pipe ID of this entry + */ +static inline void CFE_SB_PipeDescSetUsed(CFE_SB_PipeD_t *PipeDscPtr, CFE_SB_PipeId_t PipeID) +{ + PipeDscPtr->PipeId = PipeID; +} + +/** + * @brief Set an Pipe descriptor table entry free (not used) + * + * This clears the internal field(s) within this entry, and allows the + * memory to be re-used in the future. + * + * As this dereferences fields within the descriptor, global data must be + * locked prior to invoking this function. + * + * @param[in] PipeDscPtr pointer to Pipe table entry + */ +static inline void CFE_SB_PipeDescSetFree(CFE_SB_PipeD_t *PipeDscPtr) +{ + PipeDscPtr->PipeId = CFE_SB_INVALID_PIPE; +} + +/** + * @brief Check if an Pipe descriptor is a match for the given PipeID + * + * This routine confirms that the previously-located descriptor is valid + * and matches the expected Pipe ID. + * + * As this dereferences fields within the descriptor, global data must be + * locked prior to invoking this function. + * + * @param[in] PipeDscPtr pointer to Pipe table entry + * @param[in] PipeID expected Pipe ID + * @returns true if the entry matches the given Pipe ID + */ +static inline bool CFE_SB_PipeDescIsMatch(const CFE_SB_PipeD_t *PipeDscPtr, CFE_SB_PipeId_t PipeID) +{ + return (PipeDscPtr != NULL && CFE_ES_ResourceID_Equal(PipeDscPtr->PipeId, PipeID)); +} + +/* Availability check functions used in conjunction with CFE_ES_FindNextAvailableId() */ +bool CFE_SB_CheckPipeDescSlotUsed(CFE_SB_PipeId_t CheckId); + + /* * External variables private to the software bus module */ diff --git a/fsw/cfe-core/src/sb/cfe_sb_task.c b/fsw/cfe-core/src/sb/cfe_sb_task.c index 003f3c0f5..dc2cd0db9 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_task.c +++ b/fsw/cfe-core/src/sb/cfe_sb_task.c @@ -233,10 +233,6 @@ int32 CFE_SB_AppInit(void){ CFE_SB_ValueToMsgId(CFE_SB_ALLSUBS_TLM_MID), sizeof(CFE_SB.PrevSubMsg)); - CFE_MSG_Init(&CFE_SB.SubRprtMsg.Hdr.Msg, - CFE_SB_ValueToMsgId(CFE_SB_ONESUB_TLM_MID), - sizeof(CFE_SB.SubRprtMsg)); - /* Populate the fixed fields in the HK Tlm Msg */ CFE_SB.HKTlmMsg.Payload.MemPoolHandle = CFE_SB.Mem.PoolHdl; @@ -569,9 +565,13 @@ int32 CFE_SB_DisableSubReportingCmd(const CFE_SB_DisableSubReportingCmd_t *data) */ int32 CFE_SB_SendHKTlmCmd(const CFE_MSG_CommandHeader_t *data) { + CFE_SB_LockSharedData(__FILE__, __LINE__); + CFE_SB.HKTlmMsg.Payload.MemInUse = CFE_SB.StatTlmMsg.Payload.MemInUse; CFE_SB.HKTlmMsg.Payload.UnmarkedMem = CFE_PLATFORM_SB_BUF_MEMORY_BYTES - CFE_SB.StatTlmMsg.Payload.PeakMemInUse; - + + CFE_SB_UnlockSharedData(__FILE__, __LINE__); + CFE_SB_TimeStampMsg(&CFE_SB.HKTlmMsg.Hdr.Msg); CFE_SB_TransmitMsg(&CFE_SB.HKTlmMsg.Hdr.Msg, true); @@ -627,49 +627,66 @@ void CFE_SB_ResetCounters(void){ int32 CFE_SB_EnableRouteCmd(const CFE_SB_EnableRouteCmd_t *data) { CFE_SB_MsgId_t MsgId; - CFE_SB_PipeId_t PipeId; + CFE_SB_PipeD_t *PipeDscPtr; CFE_SB_DestinationD_t *DestPtr; const CFE_SB_RouteCmd_Payload_t *CmdPtr; + uint16 PendingEventID; + PendingEventID = 0; CmdPtr = &data->Payload; MsgId = CmdPtr->MsgId; - PipeId = CmdPtr->Pipe; + + CFE_SB_LockSharedData(__func__,__LINE__); /* check cmd parameters */ + PipeDscPtr = CFE_SB_LocatePipeDescByID(CmdPtr->Pipe); if(!CFE_SB_IsValidMsgId(MsgId) || - (CFE_SB_ValidatePipeId(PipeId) != CFE_SUCCESS)) + !CFE_SB_PipeDescIsMatch(PipeDscPtr,CmdPtr->Pipe)) { - CFE_EVS_SendEvent(CFE_SB_ENBL_RTE3_EID,CFE_EVS_EventType_ERROR, - "Enbl Route Cmd:Invalid Param.Msg 0x%x,Pipe %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId),(int)PipeId); + PendingEventID = CFE_SB_ENBL_RTE3_EID; CFE_SB.HKTlmMsg.Payload.CommandErrorCounter++; - /* - * returning "success" here as there is no other recourse; - * the full extent of the error recovery has been done - */ - return CFE_SUCCESS; - }/* end if */ + } + else + { + DestPtr = CFE_SB_GetDestPtr(CFE_SBR_GetRouteId(MsgId), CmdPtr->Pipe); + if(DestPtr == NULL) + { + PendingEventID = CFE_SB_ENBL_RTE1_EID; + CFE_SB.HKTlmMsg.Payload.CommandErrorCounter++; + } + else + { + DestPtr->Active = CFE_SB_ACTIVE; + PendingEventID = CFE_SB_ENBL_RTE2_EID; + CFE_SB.HKTlmMsg.Payload.CommandCounter++; + } - DestPtr = CFE_SB_GetDestPtr(CFE_SBR_GetRouteId(MsgId), PipeId); - if(DestPtr == NULL){ - CFE_EVS_SendEvent(CFE_SB_ENBL_RTE1_EID,CFE_EVS_EventType_ERROR, - "Enbl Route Cmd:Route does not exist.Msg 0x%x,Pipe %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId),(int)PipeId); - CFE_SB.HKTlmMsg.Payload.CommandErrorCounter++; - /* - * returning "success" here as there is no other recourse; - * the full extent of the error recovery has been done - */ - return CFE_SUCCESS; - }/* end if */ + }/* end if */ - DestPtr->Active = CFE_SB_ACTIVE; - CFE_EVS_SendEvent(CFE_SB_ENBL_RTE2_EID,CFE_EVS_EventType_DEBUG, - "Enabling Route,Msg 0x%x,Pipe %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId),(int)PipeId); + CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_SB.HKTlmMsg.Payload.CommandCounter++; + switch(PendingEventID) + { + case CFE_SB_ENBL_RTE1_EID: + CFE_EVS_SendEvent(CFE_SB_ENBL_RTE1_EID,CFE_EVS_EventType_ERROR, + "Enbl Route Cmd:Route does not exist.Msg 0x%x,Pipe %lu", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(CmdPtr->Pipe)); + break; + case CFE_SB_ENBL_RTE3_EID: + CFE_EVS_SendEvent(CFE_SB_ENBL_RTE3_EID,CFE_EVS_EventType_ERROR, + "Enbl Route Cmd:Invalid Param.Msg 0x%x,Pipe %lu", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(CmdPtr->Pipe)); + break; + case CFE_SB_ENBL_RTE2_EID: + CFE_EVS_SendEvent(CFE_SB_ENBL_RTE2_EID,CFE_EVS_EventType_DEBUG, + "Enabling Route,Msg 0x%x,Pipe %lu", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(CmdPtr->Pipe)); + break; + } return CFE_SUCCESS; }/* end CFE_SB_EnableRouteCmd */ @@ -692,48 +709,67 @@ int32 CFE_SB_EnableRouteCmd(const CFE_SB_EnableRouteCmd_t *data) int32 CFE_SB_DisableRouteCmd(const CFE_SB_DisableRouteCmd_t *data) { CFE_SB_MsgId_t MsgId; - CFE_SB_PipeId_t PipeId; + CFE_SB_PipeD_t *PipeDscPtr; CFE_SB_DestinationD_t *DestPtr; const CFE_SB_RouteCmd_Payload_t *CmdPtr; + uint16 PendingEventID; + PendingEventID = 0; CmdPtr = &data->Payload; MsgId = CmdPtr->MsgId; - PipeId = CmdPtr->Pipe; + + CFE_SB_LockSharedData(__func__,__LINE__); /* check cmd parameters */ + PipeDscPtr = CFE_SB_LocatePipeDescByID(CmdPtr->Pipe); if(!CFE_SB_IsValidMsgId(MsgId) || - (CFE_SB_ValidatePipeId(PipeId) != CFE_SUCCESS)){ - CFE_EVS_SendEvent(CFE_SB_DSBL_RTE3_EID,CFE_EVS_EventType_ERROR, - "Disable Route Cmd:Invalid Param.Msg 0x%x,Pipe %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId),(int)PipeId); + !CFE_SB_PipeDescIsMatch(PipeDscPtr,CmdPtr->Pipe)) + { + PendingEventID = CFE_SB_DSBL_RTE3_EID; CFE_SB.HKTlmMsg.Payload.CommandErrorCounter++; - /* - * returning "success" here as there is no other recourse; - * the full extent of the error recovery has been done - */ - return CFE_SUCCESS; - }/* end if */ + } + else + { + DestPtr = CFE_SB_GetDestPtr(CFE_SBR_GetRouteId(MsgId), CmdPtr->Pipe); + if(DestPtr == NULL) + { + PendingEventID = CFE_SB_DSBL_RTE1_EID; + CFE_SB.HKTlmMsg.Payload.CommandErrorCounter++; + } + else + { + DestPtr->Active = CFE_SB_INACTIVE; + PendingEventID = CFE_SB_DSBL_RTE2_EID; + CFE_SB.HKTlmMsg.Payload.CommandCounter++; + } - DestPtr = CFE_SB_GetDestPtr(CFE_SBR_GetRouteId(MsgId), PipeId); - if(DestPtr == NULL){ - CFE_EVS_SendEvent(CFE_SB_DSBL_RTE1_EID,CFE_EVS_EventType_ERROR, - "Disable Route Cmd:Route does not exist,Msg 0x%x,Pipe %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId),(int)PipeId); - CFE_SB.HKTlmMsg.Payload.CommandErrorCounter++; - /* - * returning "success" here as there is no other recourse; - * the full extent of the error recovery has been done - */ - return CFE_SUCCESS; - }/* end if */ + }/* end if */ - DestPtr->Active = CFE_SB_INACTIVE; + CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEvent(CFE_SB_DSBL_RTE2_EID,CFE_EVS_EventType_DEBUG, - "Route Disabled,Msg 0x%x,Pipe %d", - (unsigned int)CFE_SB_MsgIdToValue(MsgId),(int)PipeId); - CFE_SB.HKTlmMsg.Payload.CommandCounter++; + + switch(PendingEventID) + { + case CFE_SB_DSBL_RTE1_EID: + CFE_EVS_SendEvent(CFE_SB_DSBL_RTE1_EID,CFE_EVS_EventType_ERROR, + "Disable Route Cmd:Route does not exist,Msg 0x%x,Pipe %lu", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(CmdPtr->Pipe)); + break; + case CFE_SB_DSBL_RTE3_EID: + CFE_EVS_SendEvent(CFE_SB_DSBL_RTE3_EID,CFE_EVS_EventType_ERROR, + "Disable Route Cmd:Invalid Param.Msg 0x%x,Pipe %lu", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(CmdPtr->Pipe)); + break; + case CFE_SB_DSBL_RTE2_EID: + CFE_EVS_SendEvent(CFE_SB_DSBL_RTE2_EID,CFE_EVS_EventType_DEBUG, + "Route Disabled,Msg 0x%x,Pipe %lu", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(CmdPtr->Pipe)); + break; + } return CFE_SUCCESS; }/* end CFE_SB_DisableRouteCmd */ @@ -753,6 +789,45 @@ int32 CFE_SB_DisableRouteCmd(const CFE_SB_DisableRouteCmd_t *data) */ int32 CFE_SB_SendStatsCmd(const CFE_SB_SendSbStatsCmd_t *data) { + uint32 PipeDscCount; + uint32 PipeStatCount; + CFE_SB_PipeD_t *PipeDscPtr; + CFE_SB_PipeDepthStats_t *PipeStatPtr; + + CFE_SB_LockSharedData(__FILE__, __LINE__); + + /* Collect data on pipes */ + PipeDscCount = CFE_PLATFORM_SB_MAX_PIPES; + PipeStatCount = CFE_MISSION_SB_MAX_PIPES; + PipeDscPtr = CFE_SB.PipeTbl; + PipeStatPtr = CFE_SB.StatTlmMsg.Payload.PipeDepthStats; + + while (PipeDscCount > 0 && PipeStatCount > 0) + { + if (CFE_SB_PipeDescIsUsed(PipeDscPtr)) + { + PipeStatPtr->PipeId = PipeDscPtr->PipeId; + PipeStatPtr->InUse = PipeDscPtr->CurrentDepth; + PipeStatPtr->PeakInUse = PipeDscPtr->PeakDepth; + PipeStatPtr->Depth = PipeDscPtr->QueueDepth; + + ++PipeStatPtr; + --PipeStatCount; + } + + --PipeDscCount; + ++PipeDscPtr; + } + + CFE_SB_UnlockSharedData(__FILE__, __LINE__); + + while (PipeStatCount > 0) + { + memset(PipeStatPtr, 0, sizeof(*PipeStatPtr)); + + ++PipeStatPtr; + --PipeStatCount; + } CFE_SB_TimeStampMsg(&CFE_SB.StatTlmMsg.Hdr.Msg); CFE_SB_TransmitMsg(&CFE_SB.StatTlmMsg.Hdr.Msg, true); @@ -861,57 +936,129 @@ int32 CFE_SB_SendMapInfoCmd(const CFE_SB_SendMapInfoCmd_t *data) */ void CFE_SB_WriteRouteToFile(CFE_SBR_RouteId_t RouteId, void *ArgPtr) { + struct RouteInfo + { + CFE_SB_PipeId_t PipeId; + uint8 Active; + uint16 DestCnt; + }; + CFE_SB_FileWriteCallback_t *args; CFE_SB_DestinationD_t *destptr; CFE_SB_PipeD_t *pipedptr; int32 status; CFE_SB_RoutingFileEntry_t entry; + struct RouteInfo RouteInfo[CFE_PLATFORM_SB_MAX_DEST_PER_PKT]; + struct RouteInfo *RouteInfoPtr; + uint32 NumDest; /* Cast arguments for local use */ args = (CFE_SB_FileWriteCallback_t *)ArgPtr; + NumDest = 0; + + /* Data must be locked to snapshot the route info */ + CFE_SB_LockSharedData(__FILE__, __LINE__); + destptr = CFE_SBR_GetDestListHeadPtr(RouteId); + entry.MsgId = CFE_SBR_GetMsgId(RouteId); + RouteInfoPtr = RouteInfo; - while((destptr != NULL) && (args->Status != CFE_SB_FILE_IO_ERR)) + while((destptr != NULL) && NumDest < CFE_PLATFORM_SB_MAX_DEST_PER_PKT) { - - pipedptr = CFE_SB_GetPipePtr(destptr->PipeId); + pipedptr = CFE_SB_LocatePipeDescByID(destptr->PipeId); /* If invalid id, continue on to next entry */ - if (pipedptr != NULL) + if (CFE_SB_PipeDescIsMatch(pipedptr,destptr->PipeId)) { + RouteInfoPtr->PipeId = destptr->PipeId; + RouteInfoPtr->Active = destptr->Active; + RouteInfoPtr->DestCnt = destptr->DestCnt; + ++RouteInfoPtr; + ++NumDest; + } - entry.MsgId = CFE_SBR_GetMsgId(RouteId); - entry.PipeId = destptr->PipeId; - entry.State = destptr->Active; - entry.MsgCnt = destptr->DestCnt; + destptr = destptr->Next; + } - entry.AppName[0] = 0; - /* - * NOTE: as long as CFE_ES_GetAppName() returns success, then it - * guarantees null termination of the output. Return code is not - * checked here (bad) but in case of error it does not seem to touch - * the buffer, therefore the initialization above will protect for now - */ - CFE_ES_GetAppName(entry.AppName, pipedptr->AppId, sizeof(entry.AppName)); - CFE_SB_GetPipeName(entry.PipeName, sizeof(entry.PipeName), entry.PipeId); + CFE_SB_UnlockSharedData(__FILE__, __LINE__); - status = OS_write (args->Fd, &entry, sizeof(CFE_SB_RoutingFileEntry_t)); - if(status != sizeof(CFE_SB_RoutingFileEntry_t)) - { - CFE_SB_FileWriteByteCntErr(args->Filename, sizeof(CFE_SB_RoutingFileEntry_t), status); - OS_close(args->Fd); - args->Status = CFE_SB_FILE_IO_ERR; - } + RouteInfoPtr = RouteInfo; + while (NumDest > 0) + { + entry.PipeId = RouteInfoPtr->PipeId; + entry.State = RouteInfoPtr->Active; + entry.MsgCnt = RouteInfoPtr->DestCnt; + + entry.AppName[0] = 0; - args->FileSize += status; - args->EntryCount++; + /* + * NOTE: as long as CFE_ES_GetAppName() returns success, then it + * guarantees null termination of the output. Return code is not + * checked here (bad) but in case of error it does not seem to touch + * the buffer, therefore the initialization above will protect for now + */ + CFE_ES_GetAppName(entry.AppName, pipedptr->AppId, sizeof(entry.AppName)); + CFE_SB_GetPipeName(entry.PipeName, sizeof(entry.PipeName), entry.PipeId); + + status = OS_write (args->Fd, &entry, sizeof(CFE_SB_RoutingFileEntry_t)); + if(status != sizeof(CFE_SB_RoutingFileEntry_t)) + { + CFE_SB_FileWriteByteCntErr(args->Filename, sizeof(CFE_SB_RoutingFileEntry_t), status); + OS_close(args->Fd); + args->Status = CFE_SB_FILE_IO_ERR; } - destptr = destptr->Next; + args->FileSize += status; + args->EntryCount++; + + ++RouteInfoPtr; + --NumDest; } } +/****************************************************************************** +** Function: CFE_SB_SendSubscriptionReport() +** +** Purpose: +** SB internal function to generate the "ONESUB_TLM" message after a subscription. +** No-op when subscription reporting is disabled. +** +** Arguments: +** Payload of notification message - MsgId, PipeId, QOS +** +** Return: +** CFE_SUCCESS or error code +*/ +int32 CFE_SB_SendSubscriptionReport(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId, CFE_SB_Qos_t Quality) +{ + CFE_SB_SingleSubscriptionTlm_t SubRptMsg; + int32 Status; + + Status = CFE_SUCCESS; + + if (CFE_SB.SubscriptionReporting == CFE_SB_ENABLE) + { + CFE_MSG_Init(&SubRptMsg.Hdr.Msg, + CFE_SB_ValueToMsgId(CFE_SB_ONESUB_TLM_MID), + sizeof(SubRptMsg)); + + SubRptMsg.Payload.MsgId = MsgId; + SubRptMsg.Payload.Pipe = PipeId; + SubRptMsg.Payload.Qos = Quality; + SubRptMsg.Payload.SubType = CFE_SB_SUBSCRIPTION; + + Status = CFE_SB_TransmitMsg(&SubRptMsg.Hdr.Msg, true); + CFE_EVS_SendEventWithAppID(CFE_SB_SUBSCRIPTION_RPT_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, + "Sending Subscription Report Msg=0x%x,Pipe=%lu,Stat=0x%x", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + CFE_ES_ResourceID_ToInteger(PipeId),(unsigned int)Status); + } + + return Status; +} + + /****************************************************************************** ** Function: CFE_SB_SendRoutingInfo() ** @@ -993,6 +1140,8 @@ int32 CFE_SB_SendPipeInfo(const char *Filename) uint32 FileSize = 0; uint32 EntryCount = 0; CFE_FS_Header_t FileHdr; + CFE_SB_PipeD_t *PipeDscPtr; + CFE_SB_PipeD_t entry; /* NOTE: Should be separate/dedicated type */ Status = OS_OpenCreate(&fd, Filename, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); @@ -1015,13 +1164,21 @@ int32 CFE_SB_SendPipeInfo(const char *Filename) FileSize = Status; - /* loop through the pipe table */ - for(i=0;iStatus != CFE_SB_FILE_IO_ERR) { + CFE_SB_LockSharedData(__FILE__,__LINE__); entry.MsgId = CFE_SBR_GetMsgId(RouteId); entry.Index = CFE_SBR_RouteIdToValue(RouteId); + CFE_SB_UnlockSharedData(__FILE__,__LINE__); status = OS_write (args->Fd, &entry, sizeof(CFE_SB_MsgMapFileEntry_t)); if(status != sizeof(CFE_SB_MsgMapFileEntry_t)) @@ -1295,8 +1460,3 @@ void CFE_SB_SetSubscriptionReporting(uint32 state){ CFE_SB.SubscriptionReporting = state; }/* end CFE_SB_SetSubscriptionReporting */ - - - - - diff --git a/fsw/cfe-core/src/time/cfe_time_tone.c b/fsw/cfe-core/src/time/cfe_time_tone.c index 40b86f1b9..0cc067723 100644 --- a/fsw/cfe-core/src/time/cfe_time_tone.c +++ b/fsw/cfe-core/src/time/cfe_time_tone.c @@ -1459,7 +1459,7 @@ void CFE_TIME_Local1HzTask(void) /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -void CFE_TIME_NotifyTimeSynchApps(void) +void CFE_TIME_NotifyTimeSynchApps(void) { uint32 i = 0; CFE_TIME_SynchCallbackPtr_t Func; diff --git a/fsw/cfe-core/unit-test/es_UT.c b/fsw/cfe-core/unit-test/es_UT.c index bff84dc8b..cda38c3f2 100644 --- a/fsw/cfe-core/unit-test/es_UT.c +++ b/fsw/cfe-core/unit-test/es_UT.c @@ -2139,6 +2139,12 @@ void TestApps(void) } +static bool ES_UT_CheckIdSlotUsed(CFE_ES_ResourceID_t Id) +{ + return UT_DEFAULT_IMPL(ES_UT_CheckIdSlotUsed) != 0; +} + + void TestResourceID(void) { /* @@ -2151,15 +2157,17 @@ void TestResourceID(void) /* Call CFE_ES_FindNextAvailableId() using an invalid resource type */ ES_ResetUnitTest(); - Id = CFE_ES_FindNextAvailableId(CFE_ES_RESOURCEID_UNDEFINED, 5); + UT_SetDefaultReturnValue(UT_KEY(ES_UT_CheckIdSlotUsed), 1); + Id = CFE_ES_FindNextAvailableId(CFE_ES_RESOURCEID_UNDEFINED, 5, ES_UT_CheckIdSlotUsed); UtAssert_True(!CFE_ES_ResourceID_IsDefined(Id), "CFE_ES_FindNextAvailableId() on undefined resource type"); /* Verify that CFE_ES_FindNextAvailableId() does not repeat until CFE_ES_RESOURCEID_MAX is reached */ + UT_SetDefaultReturnValue(UT_KEY(ES_UT_CheckIdSlotUsed), 0); LastId = CFE_ES_Global.LastAppId; Count = CFE_ES_RESOURCEID_MAX-1; while (Count > 0) { - Id = CFE_ES_FindNextAvailableId(LastId, CFE_PLATFORM_ES_MAX_APPLICATIONS); + Id = CFE_ES_FindNextAvailableId(LastId, CFE_PLATFORM_ES_MAX_APPLICATIONS, ES_UT_CheckIdSlotUsed); if (CFE_ES_ResourceID_ToInteger(Id) - CFE_ES_ResourceID_ToInteger(LastId) != 1) { /* Numbers should be incrementing by 1 each time, never decreasing */ @@ -2172,7 +2180,7 @@ void TestResourceID(void) UtAssert_True(Count == 0, "CFE_ES_FindNextAvailableId() allocate all resource ID space"); /* Now verify that CFE_ES_FindNextAvailableId() recycles the first item again */ - Id = CFE_ES_FindNextAvailableId(LastId, CFE_PLATFORM_ES_MAX_APPLICATIONS); + Id = CFE_ES_FindNextAvailableId(LastId, CFE_PLATFORM_ES_MAX_APPLICATIONS, ES_UT_CheckIdSlotUsed); UtAssert_True(CFE_ES_ResourceID_IsDefined(Id), "CFE_ES_FindNextAvailableId() after wrap"); UtAssert_True(CFE_ES_ResourceID_ToInteger(Id) < (CFE_ES_APPID_BASE + CFE_PLATFORM_ES_MAX_APPLICATIONS), "CFE_ES_FindNextAvailableId() wrap ID"); } diff --git a/fsw/cfe-core/unit-test/sb_UT.c b/fsw/cfe-core/unit-test/sb_UT.c index e7522dd6d..06624f099 100644 --- a/fsw/cfe-core/unit-test/sb_UT.c +++ b/fsw/cfe-core/unit-test/sb_UT.c @@ -112,6 +112,12 @@ const CFE_SB_MsgId_t SB_UT_ALTERNATE_INVALID_MID = CFE_SB_MSGID_WRAP_VALUE(CFE_P const CFE_SB_MsgId_t SB_UT_BARE_CMD_MID3 = CFE_SB_MSGID_WRAP_VALUE(0x1003); const CFE_SB_MsgId_t SB_UT_BARE_TLM_MID3 = CFE_SB_MSGID_WRAP_VALUE(0x0003); +const CFE_SB_PipeId_t SB_UT_PIPEID_0 = { CFE_SB_PIPEID_BASE + 0 }; +const CFE_SB_PipeId_t SB_UT_PIPEID_1 = { CFE_SB_PIPEID_BASE + 1 }; +const CFE_SB_PipeId_t SB_UT_PIPEID_2 = { CFE_SB_PIPEID_BASE + 2 }; +const CFE_SB_PipeId_t SB_UT_PIPEID_3 = { CFE_SB_PIPEID_BASE + 3 }; +const CFE_SB_PipeId_t SB_UT_ALTERNATE_INVALID_PIPEID = { 0xDEADBEEF }; + /* * Helper function to "corrupt" a resource ID value in a consistent/predicatble way, * which can also be un-done easily. @@ -227,7 +233,7 @@ void Test_SB_AppInit_EVSSendEvtFail(void) UT_SetDeferredRetcode(UT_KEY(CFE_EVS_SendEvent), 1, ForcedRtnVal); ASSERT_EQ(CFE_SB_AppInit(), ForcedRtnVal); - EVTCNT(7); + EVTCNT(4); TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); @@ -255,8 +261,6 @@ void Test_SB_AppInit_CrPipeFail(void) */ void Test_SB_AppInit_Sub1Fail(void) { - CFE_SB_PipeId_t PipeId = 0; - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 1, -1); ASSERT_EQ(CFE_SB_AppInit(), CFE_SB_BUF_ALOC_ERR); @@ -264,7 +268,7 @@ void Test_SB_AppInit_Sub1Fail(void) EVTSENT(CFE_SB_DEST_BLK_ERR_EID); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_AppInit_Sub1Fail */ @@ -273,16 +277,14 @@ void Test_SB_AppInit_Sub1Fail(void) */ void Test_SB_AppInit_Sub2Fail(void) { - CFE_SB_PipeId_t PipeId = 0; - UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 2, -1); ASSERT_EQ(CFE_SB_AppInit(), CFE_SB_BUF_ALOC_ERR); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_DEST_BLK_ERR_EID); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_AppInit_Sub2Fail */ @@ -291,16 +293,15 @@ void Test_SB_AppInit_Sub2Fail(void) */ void Test_SB_AppInit_GetPoolFail(void) { - CFE_SB_PipeId_t PipeId = 0; int32 ForcedRtnVal = -1; UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 4, ForcedRtnVal); ASSERT_EQ(CFE_SB_AppInit(), ForcedRtnVal); - EVTCNT(7); + EVTCNT(4); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_AppInit_GetPoolFail */ @@ -309,16 +310,15 @@ void Test_SB_AppInit_GetPoolFail(void) */ void Test_SB_AppInit_PutPoolFail(void) { - CFE_SB_PipeId_t PipeId = 0; int32 ForcedRtnVal = -1; UT_SetDeferredRetcode(UT_KEY(CFE_ES_PutPoolBuf), 1, ForcedRtnVal); ASSERT_EQ(CFE_SB_AppInit(), ForcedRtnVal); - EVTCNT(7); + EVTCNT(4); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_AppInit_PutPoolFail */ @@ -336,18 +336,16 @@ void Test_SB_MainRoutine(void) */ void Test_SB_Main_RcvErr(void) { - CFE_SB_PipeId_t PipeId = 0; - UT_SetDeferredRetcode(UT_KEY(OS_QueueGet), 1, -1); CFE_SB_TaskMain(); - EVTCNT(10); + EVTCNT(6); EVTSENT(CFE_SB_INIT_EID); EVTSENT(CFE_SB_Q_RD_ERR_EID); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_Main_RcvErr */ @@ -356,14 +354,12 @@ void Test_SB_Main_RcvErr(void) */ void Test_SB_Main_InitErr(void) { - CFE_SB_PipeId_t PipeId = 0; - UT_SetDeferredRetcode(UT_KEY(CFE_ES_PutPoolBuf), 1, -1); CFE_SB_TaskMain(); - EVTCNT(7); + EVTCNT(4); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_Main_InitErr */ @@ -507,7 +503,6 @@ void Test_SB_Cmds_RoutingInfoDef(void) CFE_SB_Buffer_t SBBuf; CFE_SB_SendRoutingInfoCmd_t Cmd; } SendRoutingInfo; - CFE_SB_PipeId_t PipeId = 0; CFE_MSG_FcnCode_t FcnCode = CFE_SB_SEND_ROUTING_INFO_CC; CFE_SB_MsgId_t MsgId = CFE_SB_ValueToMsgId(CFE_SB_CMD_MID); CFE_MSG_Size_t Size = sizeof(SendRoutingInfo.Cmd); @@ -522,7 +517,7 @@ void Test_SB_Cmds_RoutingInfoDef(void) CFE_SB_ProcessCmdPipePkt(&SendRoutingInfo.SBBuf); - EVTCNT(12); + EVTCNT(9); EVTSENT(CFE_SB_INIT_EID); @@ -532,7 +527,7 @@ void Test_SB_Cmds_RoutingInfoDef(void) EVTSENT(CFE_SB_SND_RTG_EID); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_Cmds_RoutingInfoDef */ @@ -616,8 +611,6 @@ void Test_SB_Cmds_RoutingInfoHdrFail(void) */ void Test_SB_Cmds_RoutingInfoWriteFail(void) { - CFE_SB_PipeId_t PipeId = 0; - /* Make some routing info by calling CFE_SB_AppInit */ SETUP(CFE_SB_AppInit()); @@ -625,7 +618,7 @@ void Test_SB_Cmds_RoutingInfoWriteFail(void) ASSERT_EQ(CFE_SB_SendRtgInfo("RoutingTstFile"), CFE_SB_FILE_IO_ERR); - EVTCNT(11); + EVTCNT(9); EVTSENT(CFE_SB_PIPE_ADDED_EID); @@ -635,7 +628,7 @@ void Test_SB_Cmds_RoutingInfoWriteFail(void) EVTSENT(CFE_SB_FILEWRITE_ERR_EID); - TEARDOWN(CFE_SB_DeletePipe(PipeId)); + TEARDOWN(CFE_SB_DeletePipe(CFE_SB.CmdPipe)); } /* end Test_SB_Cmds_RoutingInfoWriteFail */ @@ -808,7 +801,7 @@ void Test_SB_Cmds_MapInfoDef(void) CFE_SB_ProcessCmdPipePkt(&SendMapInfo.SBBuf); - EVTCNT(18); + EVTCNT(11); EVTSENT(CFE_SB_SND_RTG_EID); @@ -910,7 +903,7 @@ void Test_SB_Cmds_MapInfoWriteFail(void) ASSERT_EQ(CFE_SB_SendMapInfo("MapTstFile"), CFE_SB_FILE_IO_ERR); - EVTCNT(18); + EVTCNT(11); EVTSENT(CFE_SB_FILEWRITE_ERR_EID); @@ -953,7 +946,7 @@ void Test_SB_Cmds_EnRouteValParam(void) CFE_SB_ProcessCmdPipePkt(&EnableRoute.SBBuf); - EVTCNT(4); + EVTCNT(3); EVTSENT(CFE_SB_PIPE_ADDED_EID); @@ -995,7 +988,7 @@ void Test_SB_Cmds_EnRouteNonExist(void) CFE_SB_ProcessCmdPipePkt(&EnableRoute.SBBuf); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_PIPE_ADDED_EID); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -1025,7 +1018,7 @@ void Test_SB_Cmds_EnRouteInvParam(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); EnableRoute.Cmd.Payload.MsgId = SB_UT_LAST_VALID_MID; - EnableRoute.Cmd.Payload.Pipe = 3; + EnableRoute.Cmd.Payload.Pipe = SB_UT_PIPEID_3; CFE_SB_ProcessCmdPipePkt(&EnableRoute.SBBuf); @@ -1054,7 +1047,7 @@ void Test_SB_Cmds_EnRouteInvParam2(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); EnableRoute.Cmd.Payload.MsgId = CFE_SB_INVALID_MSG_ID; - EnableRoute.Cmd.Payload.Pipe = 3; + EnableRoute.Cmd.Payload.Pipe = SB_UT_PIPEID_3; CFE_SB_ProcessCmdPipePkt(&EnableRoute.SBBuf); @@ -1084,7 +1077,7 @@ void Test_SB_Cmds_EnRouteInvParam3(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); EnableRoute.Cmd.Payload.MsgId = SB_UT_ALTERNATE_INVALID_MID; - EnableRoute.Cmd.Payload.Pipe = 0; + EnableRoute.Cmd.Payload.Pipe = SB_UT_PIPEID_0; CFE_SB_ProcessCmdPipePkt(&EnableRoute.SBBuf); @@ -1122,7 +1115,7 @@ void Test_SB_Cmds_DisRouteValParam(void) CFE_SB_ProcessCmdPipePkt(&DisableRoute.SBBuf); - EVTCNT(4); + EVTCNT(3); EVTSENT(CFE_SB_PIPE_ADDED_EID); @@ -1163,7 +1156,7 @@ void Test_SB_Cmds_DisRouteNonExist(void) CFE_SB_ProcessCmdPipePkt(&DisableRoute.SBBuf); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_PIPE_ADDED_EID); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -1193,7 +1186,7 @@ void Test_SB_Cmds_DisRouteInvParam(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); DisableRoute.Cmd.Payload.MsgId = SB_UT_LAST_VALID_MID; - DisableRoute.Cmd.Payload.Pipe = 3; + DisableRoute.Cmd.Payload.Pipe = SB_UT_PIPEID_3; CFE_SB_ProcessCmdPipePkt(&DisableRoute.SBBuf); @@ -1222,7 +1215,7 @@ void Test_SB_Cmds_DisRouteInvParam2(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); DisableRoute.Cmd.Payload.MsgId = CFE_SB_INVALID_MSG_ID; - DisableRoute.Cmd.Payload.Pipe = 3; + DisableRoute.Cmd.Payload.Pipe = SB_UT_PIPEID_3; CFE_SB_ProcessCmdPipePkt(&DisableRoute.SBBuf); @@ -1252,7 +1245,7 @@ void Test_SB_Cmds_DisRouteInvParam3(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); DisableRoute.Cmd.Payload.MsgId = SB_UT_ALTERNATE_INVALID_MID; - DisableRoute.Cmd.Payload.Pipe = 0; + DisableRoute.Cmd.Payload.Pipe = SB_UT_PIPEID_0; CFE_SB_ProcessCmdPipePkt(&DisableRoute.SBBuf); @@ -1332,7 +1325,7 @@ void Test_SB_Cmds_SendPrevSubs(void) * */ if (i != CFE_SB_ALLSUBS_TLM_MID) { - NumEvts += 2; + NumEvts += 1; SETUP(CFE_SB_Subscribe(CFE_SB_ValueToMsgId(i), PipeId1)); } } @@ -1358,7 +1351,7 @@ void Test_SB_Cmds_SendPrevSubs(void) CFE_SB_ProcessCmdPipePkt(&SendPrevSubs.SBBuf); - NumEvts += 8; /* +2 for the subscribe, +6 for the SEND_PREV_SUBS_CC */ + NumEvts += 7; /* +1 for the subscribe, +6 for the SEND_PREV_SUBS_CC */ /* Event count is only exact if there were no collisions */ if (UT_EventIsInHistory(CFE_SB_HASHCOLLISION_EID)) @@ -1376,7 +1369,7 @@ void Test_SB_Cmds_SendPrevSubs(void) for (; i < CFE_SB_SUB_ENTRIES_PER_PKT * 3; i++) { SETUP(CFE_SB_Subscribe(CFE_SB_ValueToMsgId(i), PipeId1)); - NumEvts += 2; + NumEvts += 1; } SETUP(CFE_SB_SubscribeLocal(MsgId, PipeId2, MsgLim)); @@ -1685,6 +1678,7 @@ void Test_CreatePipe_MaxPipes(void) /* Create maximum number of pipes + 1. Only one 'create pipe' failure * expected */ + UT_SetDeferredRetcode(UT_KEY(CFE_ES_ResourceID_ToIndex), 1+CFE_PLATFORM_SB_MAX_PIPES, -1); for (i = 0; i < (CFE_PLATFORM_SB_MAX_PIPES + 1); i++) { snprintf(PipeName, OS_MAX_API_NAME, "TestPipe%ld", (long) i); @@ -1714,8 +1708,8 @@ void Test_CreatePipe_MaxPipes(void) */ void Test_CreatePipe_SamePipeName(void) { - CFE_SB_PipeId_t FirstPipeId = -1; - CFE_SB_PipeId_t PipeId = -1; + CFE_SB_PipeId_t FirstPipeId = CFE_SB_INVALID_PIPE; + CFE_SB_PipeId_t PipeId = CFE_SB_INVALID_PIPE; uint16 PipeDepth = 1; char PipeName[] = "Test_CFE_SB"; @@ -1731,7 +1725,7 @@ void Test_CreatePipe_SamePipeName(void) /* Second call to CFE_SB_CreatePipe with same PipeName should fail */ ASSERT_EQ(CFE_SB_CreatePipe(&PipeId, PipeDepth, PipeName), CFE_SB_PIPE_CR_ERR); - ASSERT_EQ(PipeId, FirstPipeId); + ASSERT_TRUE(CFE_ES_ResourceID_Equal(PipeId, FirstPipeId)); EVTCNT(2); @@ -1791,7 +1785,7 @@ void Test_DeletePipe_WithSubs(void) SETUP(CFE_SB_Subscribe(MsgId3, PipedId)); ASSERT(CFE_SB_DeletePipe(PipedId)); - EVTCNT(10); + EVTCNT(6); EVTSENT(CFE_SB_PIPE_ADDED_EID); EVTSENT(CFE_SB_PIPE_DELETED_EID); @@ -1803,7 +1797,7 @@ void Test_DeletePipe_WithSubs(void) */ void Test_DeletePipe_InvalidPipeId(void) { - CFE_SB_PipeId_t PipeId = 30; + CFE_SB_PipeId_t PipeId = SB_UT_ALTERNATE_INVALID_PIPEID; ASSERT_EQ(CFE_SB_DeletePipe(PipeId), CFE_SB_BAD_ARGUMENT); @@ -1819,16 +1813,18 @@ void Test_DeletePipe_InvalidPipeId(void) void Test_DeletePipe_InvalidPipeOwner(void) { CFE_SB_PipeId_t PipedId; + CFE_SB_PipeD_t *PipeDscPtr; CFE_ES_ResourceID_t RealOwner; uint16 PipeDepth = 10; SETUP(CFE_SB_CreatePipe(&PipedId, PipeDepth, "TestPipe")); /* Change owner of pipe through memory corruption */ - RealOwner = CFE_SB.PipeTbl[PipedId].AppId; + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipedId); + RealOwner = PipeDscPtr->AppId; /* Choose a value that is sure not to be owner */ - CFE_SB.PipeTbl[PipedId].AppId = UT_SB_ResourceID_Modify(RealOwner, 1); + PipeDscPtr->AppId = UT_SB_ResourceID_Modify(RealOwner, 1); ASSERT_EQ(CFE_SB_DeletePipe(PipedId), CFE_SB_BAD_ARGUMENT); EVTCNT(2); @@ -1836,7 +1832,7 @@ void Test_DeletePipe_InvalidPipeOwner(void) EVTSENT(CFE_SB_DEL_PIPE_ERR2_EID); /* Restore owner id and delete pipe since test is complete */ - CFE_SB.PipeTbl[PipedId].AppId = RealOwner; + PipeDscPtr->AppId = RealOwner; TEARDOWN(CFE_SB_DeletePipe(PipedId)); } /* end Test_DeletePipe_InvalidPipeId */ @@ -1859,7 +1855,7 @@ void Test_DeletePipe_WithAppid(void) ASSERT(CFE_SB_DeletePipeWithAppId(PipedId, AppId)); - EVTCNT(10); + EVTCNT(6); } /* end Test_DeletePipe_WithAppid */ @@ -1891,10 +1887,15 @@ void Test_GetPipeName_API(void) */ void Test_GetPipeName_NullPtr(void) { - ASSERT_EQ(CFE_SB_GetPipeName(NULL, OS_MAX_API_NAME, 0), CFE_SB_BAD_ARGUMENT); + CFE_SB_PipeId_t PipeId; + + SETUP(CFE_SB_CreatePipe(&PipeId, 4, "TestPipe")); + ASSERT_EQ(CFE_SB_GetPipeName(NULL, OS_MAX_API_NAME, PipeId), CFE_SB_BAD_ARGUMENT); EVTSENT(CFE_SB_GETPIPENAME_NULL_PTR_EID); + TEARDOWN(CFE_SB_DeletePipe(PipeId)); + } /* end Test_GetPipeName_NullPtr */ /* @@ -1903,13 +1904,17 @@ void Test_GetPipeName_NullPtr(void) void Test_GetPipeName_InvalidId(void) { char PipeName[OS_MAX_API_NAME]; + CFE_SB_PipeId_t PipeId; - UT_SetDeferredRetcode(UT_KEY(OS_QueueGetInfo), 1, OS_ERROR); + SETUP(CFE_SB_CreatePipe(&PipeId, 4, "TestPipe")); - ASSERT_EQ(CFE_SB_GetPipeName(PipeName, OS_MAX_API_NAME, 0), CFE_SB_BAD_ARGUMENT); + UT_SetDeferredRetcode(UT_KEY(OS_GetResourceName), 1, OS_ERROR); + ASSERT_EQ(CFE_SB_GetPipeName(PipeName, OS_MAX_API_NAME, PipeId), CFE_SB_BAD_ARGUMENT); EVTSENT(CFE_SB_GETPIPENAME_ID_ERR_EID); + TEARDOWN(CFE_SB_DeletePipe(PipeId)); + } /* end Test_GetPipeName_InvalidId */ /* @@ -1918,7 +1923,7 @@ void Test_GetPipeName_InvalidId(void) void Test_GetPipeName(void) { char PipeName[OS_MAX_API_NAME]; - CFE_SB_PipeId_t PipeId = 0; + CFE_SB_PipeId_t PipeId = SB_UT_PIPEID_0; OS_queue_prop_t queue_info = { "TestPipe1" @@ -1954,7 +1959,7 @@ void Test_GetPipeIdByName_API(void) */ void Test_GetPipeIdByName_NullPtrs(void) { - CFE_SB_PipeId_t PipeIDOut = 0; + CFE_SB_PipeId_t PipeIDOut; ASSERT_EQ(CFE_SB_GetPipeIdByName(&PipeIDOut, NULL), CFE_SB_BAD_ARGUMENT); @@ -1971,8 +1976,9 @@ void Test_GetPipeIdByName_NullPtrs(void) */ void Test_GetPipeIdByName_InvalidName(void) { - CFE_SB_PipeId_t PipeIdOut = 0; + CFE_SB_PipeId_t PipeIdOut; + UT_SetDeferredRetcode(UT_KEY(OS_QueueGetIdByName), 1, OS_ERR_NAME_NOT_FOUND); ASSERT_EQ(CFE_SB_GetPipeIdByName(&PipeIdOut, "invalid"), CFE_SB_BAD_ARGUMENT); EVTSENT(CFE_SB_GETPIPEIDBYNAME_NAME_ERR_EID); @@ -1984,7 +1990,8 @@ void Test_GetPipeIdByName_InvalidName(void) */ void Test_GetPipeIdByName(void) { - CFE_SB_PipeId_t PipeId = 0, PipeIdOut = 0; + CFE_SB_PipeId_t PipeId = SB_UT_PIPEID_0; + CFE_SB_PipeId_t PipeIdOut; SETUP(CFE_SB_CreatePipe(&PipeId, 4, "TestPipe1")); @@ -2007,7 +2014,7 @@ void Test_GetPipeIdByName(void) */ void Test_SetPipeOpts_BadID(void) { - ASSERT_EQ(CFE_SB_SetPipeOpts(CFE_PLATFORM_SB_MAX_PIPES, 0), CFE_SB_BAD_ARGUMENT); + ASSERT_EQ(CFE_SB_SetPipeOpts(SB_UT_ALTERNATE_INVALID_PIPEID, 0), CFE_SB_BAD_ARGUMENT); EVTSENT(CFE_SB_SETPIPEOPTS_ID_ERR_EID); @@ -2018,19 +2025,20 @@ void Test_SetPipeOpts_BadID(void) */ void Test_SetPipeOpts_NotOwner(void) { - CFE_SB_PipeId_t PipeID = 0; - uint8 PipeTblIdx = 0; + CFE_SB_PipeId_t PipeID; + CFE_SB_PipeD_t *PipeDscPtr; CFE_ES_ResourceID_t OrigOwner; SETUP(CFE_SB_CreatePipe(&PipeID, 4, "TestPipe1")); - PipeTblIdx = CFE_SB_GetPipeIdx(PipeID); + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeID); + + OrigOwner = PipeDscPtr->AppId; + PipeDscPtr->AppId = UT_SB_ResourceID_Modify(OrigOwner, 1); - OrigOwner = CFE_SB.PipeTbl[PipeTblIdx].AppId; - CFE_SB.PipeTbl[PipeTblIdx].AppId = UT_SB_ResourceID_Modify(OrigOwner, 1); ASSERT_EQ(CFE_SB_SetPipeOpts(PipeID, 0), CFE_SB_BAD_ARGUMENT); - CFE_SB.PipeTbl[PipeTblIdx].AppId = OrigOwner; + PipeDscPtr->AppId = OrigOwner; EVTSENT(CFE_SB_SETPIPEOPTS_OWNER_ERR_EID); @@ -2043,7 +2051,7 @@ void Test_SetPipeOpts_NotOwner(void) */ void Test_SetPipeOpts(void) { - CFE_SB_PipeId_t PipeID = 0; + CFE_SB_PipeId_t PipeID; SETUP(CFE_SB_CreatePipe(&PipeID, 4, "TestPipe1")); @@ -2062,7 +2070,7 @@ void Test_GetPipeOpts_BadID(void) { uint8 Opts = 0; - ASSERT_EQ(CFE_SB_GetPipeOpts(CFE_PLATFORM_SB_MAX_PIPES, &Opts), CFE_SB_BAD_ARGUMENT); + ASSERT_EQ(CFE_SB_GetPipeOpts(SB_UT_ALTERNATE_INVALID_PIPEID, &Opts), CFE_SB_BAD_ARGUMENT); EVTSENT(CFE_SB_GETPIPEOPTS_ID_ERR_EID); @@ -2073,7 +2081,7 @@ void Test_GetPipeOpts_BadID(void) */ void Test_GetPipeOpts_BadPtr(void) { - CFE_SB_PipeId_t PipeID = 0; + CFE_SB_PipeId_t PipeID; SETUP(CFE_SB_CreatePipe(&PipeID, 4, "TestPipe1")); @@ -2090,7 +2098,7 @@ void Test_GetPipeOpts_BadPtr(void) */ void Test_GetPipeOpts(void) { - CFE_SB_PipeId_t PipeID = 0; + CFE_SB_PipeId_t PipeID; uint8 Opts = 0; SETUP(CFE_SB_CreatePipe(&PipeID, 4, "TestPipe1")); @@ -2137,7 +2145,7 @@ void Test_Subscribe_SubscribeEx(void) ASSERT(CFE_SB_SubscribeEx(MsgId, PipeId, Quality, MsgLim)); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_PIPE_ADDED_EID); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -2151,7 +2159,7 @@ void Test_Subscribe_SubscribeEx(void) */ void Test_Subscribe_InvalidPipeId(void) { - CFE_SB_PipeId_t PipeId = 2; + CFE_SB_PipeId_t PipeId = SB_UT_PIPEID_2; CFE_SB_MsgId_t MsgId = SB_UT_ALTERNATE_INVALID_MID; ASSERT_EQ(CFE_SB_Subscribe(MsgId, PipeId), CFE_SB_BAD_ARGUMENT); @@ -2199,7 +2207,7 @@ void Test_Subscribe_MaxMsgLim(void) ASSERT(CFE_SB_SubscribeEx(MsgId, PipeId, Quality, MsgLim)); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_PIPE_ADDED_EID); @@ -2221,9 +2229,10 @@ void Test_Subscribe_DuplicateSubscription(void) ASSERT(CFE_SB_Subscribe(MsgId, PipeId)); ASSERT(CFE_SB_Subscribe(MsgId, PipeId)); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_PIPE_ADDED_EID); + EVTSENT(CFE_SB_DUP_SUBSCRIP_EID); TEARDOWN(CFE_SB_DeletePipe(PipeId)); @@ -2243,9 +2252,10 @@ void Test_Subscribe_LocalSubscription(void) ASSERT(CFE_SB_SubscribeLocal(MsgId, PipeId, MsgLim)); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_PIPE_ADDED_EID); + EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); TEARDOWN(CFE_SB_DeletePipe(PipeId)); @@ -2274,17 +2284,18 @@ void Test_Subscribe_MaxDestCount(void) { if (i < CFE_PLATFORM_SB_MAX_DEST_PER_PKT) { - SETUP(CFE_SB_Subscribe(MsgId, i)); + SETUP(CFE_SB_Subscribe(MsgId, PipeId[i])); } else { - ASSERT_EQ(CFE_SB_Subscribe(MsgId, i), CFE_SB_MAX_DESTS_MET); + ASSERT_EQ(CFE_SB_Subscribe(MsgId, PipeId[i]), CFE_SB_MAX_DESTS_MET); } } - EVTCNT(3 * (CFE_PLATFORM_SB_MAX_DEST_PER_PKT + 1)); + EVTCNT((2 * CFE_PLATFORM_SB_MAX_DEST_PER_PKT) + 3); EVTSENT(CFE_SB_PIPE_ADDED_EID); + EVTSENT(CFE_SB_MAX_DESTS_MET_EID); /* Delete pipes */ for (i = 0; i < CFE_PLATFORM_SB_MAX_DEST_PER_PKT + 1; i++) @@ -2368,7 +2379,7 @@ void Test_Subscribe_SendPrevSubs(void) ASSERT(CFE_SB_SendPrevSubsCmd(&SendPrevSubsMsg)); - EVTCNT(19); + EVTCNT(12); EVTSENT(CFE_SB_PART_SUB_PKT_EID); @@ -2384,7 +2395,7 @@ void Test_Subscribe_SendPrevSubs(void) void Test_Subscribe_PipeNonexistent(void) { CFE_SB_MsgId_t MsgId = SB_UT_CMD_MID; - CFE_SB_PipeId_t PipeId = 55; + CFE_SB_PipeId_t PipeId = SB_UT_ALTERNATE_INVALID_PIPEID; ASSERT_EQ(CFE_SB_Subscribe(MsgId, PipeId), CFE_SB_BAD_ARGUMENT); @@ -2413,7 +2424,7 @@ void Test_Subscribe_SubscriptionReporting(void) /* For internal TransmitMsg call that will report subscription */ MsgIdRpt = CFE_SB_ValueToMsgId(CFE_SB_ONESUB_TLM_MID); - Size = sizeof(CFE_SB.SubRprtMsg); + Size = sizeof(CFE_SB_SingleSubscriptionTlm_t); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetMsgId), &MsgIdRpt, sizeof(MsgIdRpt), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetSize), &Size, sizeof(Size), false); @@ -2426,7 +2437,7 @@ void Test_Subscribe_SubscriptionReporting(void) /* Subscribe to message: LOCAL */ ASSERT(CFE_SB_SubscribeFull(MsgId, PipeId, Quality, CFE_PLATFORM_SB_DEFAULT_MSG_LIMIT, CFE_SB_LOCAL)); - EVTCNT(8); + EVTCNT(6); EVTSENT(CFE_SB_SUBSCRIPTION_RPT_EID); @@ -2443,6 +2454,7 @@ void Test_Subscribe_SubscriptionReporting(void) void Test_Subscribe_InvalidPipeOwner(void) { CFE_SB_PipeId_t PipeId; + CFE_SB_PipeD_t *PipeDscPtr; CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; uint16 PipeDepth = 10; CFE_ES_ResourceID_t RealOwner; @@ -2450,10 +2462,11 @@ void Test_Subscribe_InvalidPipeOwner(void) SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "TestPipe")); /* Change owner of pipe through memory corruption */ - RealOwner = CFE_SB.PipeTbl[PipeId].AppId; + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + RealOwner = PipeDscPtr->AppId; /* Choose a value that is sure not to be owner */ - CFE_SB.PipeTbl[PipeId].AppId = UT_SB_ResourceID_Modify(RealOwner, 1); + PipeDscPtr->AppId = UT_SB_ResourceID_Modify(RealOwner, 1); CFE_SB_Subscribe(MsgId, PipeId); EVTCNT(3); @@ -2461,7 +2474,7 @@ void Test_Subscribe_InvalidPipeOwner(void) EVTSENT(CFE_SB_SUB_INV_CALLER_EID); /* Restore owner id and delete pipe since test is complete */ - CFE_SB.PipeTbl[PipeId].AppId = RealOwner; + PipeDscPtr->AppId = RealOwner; TEARDOWN(CFE_SB_DeletePipe(PipeId)); } /* end Test_Subscribe_InvalidPipeOwner */ @@ -2496,7 +2509,7 @@ void Test_Unsubscribe_Basic(void) ASSERT(CFE_SB_Unsubscribe(MsgId, TestPipe)); - EVTCNT(4); + EVTCNT(3); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -2524,7 +2537,7 @@ void Test_Unsubscribe_Local(void) ASSERT(CFE_SB_UnsubscribeLocal(SB_UT_LAST_VALID_MID, TestPipe)); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -2539,6 +2552,7 @@ void Test_Unsubscribe_InvalParam(void) { CFE_SB_PipeId_t TestPipe; CFE_ES_ResourceID_t CallerId; + CFE_SB_PipeD_t *PipeDscPtr; uint16 PipeDepth = 50; CFE_SB_PipeId_t SavedPipeId; @@ -2558,17 +2572,18 @@ void Test_Unsubscribe_InvalParam(void) * bad pipe ID is caught by CFE_SB_GetPipeIdx() before it gets to * CFE_SB_ValidatePipeId() */ - SavedPipeId = CFE_SB.PipeTbl[0].PipeId; - CFE_SB.PipeTbl[0].PipeId = CFE_PLATFORM_SB_MAX_PIPES; - CFE_SB.PipeTbl[0].InUse = 1; - ASSERT_EQ(CFE_SB_Unsubscribe(SB_UT_FIRST_VALID_MID, CFE_PLATFORM_SB_MAX_PIPES), CFE_SB_BAD_ARGUMENT); + PipeDscPtr = CFE_SB_LocatePipeDescByID(TestPipe); + SavedPipeId = CFE_SB_PipeDescGetID(PipeDscPtr); + PipeDscPtr->PipeId = SB_UT_ALTERNATE_INVALID_PIPEID; + ASSERT_EQ(CFE_SB_Unsubscribe(SB_UT_FIRST_VALID_MID, TestPipe), CFE_SB_BAD_ARGUMENT); /* We must restore the old value so CFE_SB_DeletePipe() works */ - CFE_SB.PipeTbl[0].PipeId = SavedPipeId; + PipeDscPtr->PipeId = SavedPipeId; EVTCNT(4); EVTSENT(CFE_SB_UNSUB_ARG_ERR_EID); + EVTSENT(CFE_SB_UNSUB_INV_PIPE_EID); TEARDOWN(CFE_SB_DeletePipe(TestPipe)); @@ -2614,9 +2629,9 @@ void Test_Unsubscribe_InvalidPipe(void) SETUP(CFE_SB_CreatePipe(&TestPipe, PipeDepth, "TestPipe")); SETUP(CFE_SB_Subscribe(MsgId, TestPipe)); - ASSERT_EQ(CFE_SB_Unsubscribe(MsgId, TestPipe + 1), CFE_SB_BAD_ARGUMENT); + ASSERT_EQ(CFE_SB_Unsubscribe(MsgId, SB_UT_ALTERNATE_INVALID_PIPEID), CFE_SB_BAD_ARGUMENT); - EVTCNT(4); + EVTCNT(3); EVTSENT(CFE_SB_UNSUB_INV_PIPE_EID); @@ -2631,6 +2646,7 @@ void Test_Unsubscribe_InvalidPipeOwner(void) { CFE_SB_PipeId_t PipeId; CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; + CFE_SB_PipeD_t *PipeDscPtr; CFE_ES_ResourceID_t RealOwner; uint16 PipeDepth = 10; @@ -2639,17 +2655,18 @@ void Test_Unsubscribe_InvalidPipeOwner(void) SETUP(CFE_SB_Subscribe(MsgId, PipeId)); /* Change owner of pipe through memory corruption */ - RealOwner = CFE_SB.PipeTbl[PipeId].AppId; + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + RealOwner = PipeDscPtr->AppId; /* Choose a value that is sure not be owner */ - CFE_SB.PipeTbl[PipeId].AppId = UT_SB_ResourceID_Modify(RealOwner, 1); + PipeDscPtr->AppId = UT_SB_ResourceID_Modify(RealOwner, 1); ASSERT_EQ(CFE_SB_Unsubscribe(MsgId, PipeId), CFE_SB_BAD_ARGUMENT); - EVTCNT(4); + EVTCNT(3); EVTSENT(CFE_SB_UNSUB_INV_CALLER_EID); - CFE_SB.PipeTbl[PipeId].AppId = RealOwner; + PipeDscPtr->AppId = RealOwner; TEARDOWN(CFE_SB_DeletePipe(PipeId)); @@ -2676,9 +2693,10 @@ void Test_Unsubscribe_FirstDestWithMany(void) ASSERT(CFE_SB_Unsubscribe(MsgId, TestPipe1)); - EVTCNT(10); + EVTCNT(7); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); + EVTSENT(CFE_SB_SUBSCRIPTION_REMOVED_EID); TEARDOWN(CFE_SB_DeletePipe(TestPipe1)); TEARDOWN(CFE_SB_DeletePipe(TestPipe2)); @@ -2707,9 +2725,10 @@ void Test_Unsubscribe_MiddleDestWithMany(void) ASSERT(CFE_SB_Unsubscribe(MsgId, TestPipe2)); - EVTCNT(10); + EVTCNT(7); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); + EVTSENT(CFE_SB_SUBSCRIPTION_REMOVED_EID); TEARDOWN(CFE_SB_DeletePipe(TestPipe1)); TEARDOWN(CFE_SB_DeletePipe(TestPipe2)); @@ -2739,9 +2758,10 @@ void Test_Unsubscribe_GetDestPtr(void) RouteId = CFE_SBR_GetRouteId(MsgId); ASSERT_TRUE(CFE_SB_GetDestPtr(RouteId, TestPipe2) == NULL); - EVTCNT(7); + EVTCNT(5); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); + EVTSENT(CFE_SB_SUBSCRIPTION_REMOVED_EID); TEARDOWN(CFE_SB_DeletePipe(TestPipe1)); TEARDOWN(CFE_SB_DeletePipe(TestPipe2)); @@ -2846,7 +2866,7 @@ void Test_TransmitMsg_BasicSend(void) ASSERT(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true)); - EVTCNT(3); + EVTCNT(2); TEARDOWN(CFE_SB_DeletePipe(PipeId)); @@ -2903,7 +2923,7 @@ void Test_TransmitMsg_SequenceCount(void) ASSERT_EQ(SeqCnt, 2); ASSERT_EQ(UT_GetStubCount(UT_KEY(CFE_MSG_SetSequenceCount)), 2); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); SETUP(CFE_SB_Unsubscribe(MsgId, PipeId)); /* should have no subscribers now */ @@ -2948,7 +2968,7 @@ void Test_TransmitMsg_QueuePutError(void) ASSERT(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true)); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_Q_WR_ERR_EID); @@ -2987,7 +3007,7 @@ void Test_TransmitMsg_PipeFull(void) /* Pipe overflow causes TransmitMsg to return CFE_SUCCESS */ ASSERT(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true)); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_Q_FULL_ERR_EID); @@ -3028,7 +3048,7 @@ void Test_TransmitMsg_MsgLimitExceeded(void) */ ASSERT(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true)); - EVTCNT(5); + EVTCNT(4); EVTSENT(CFE_SB_MSGID_LIM_ERR_EID); @@ -3059,7 +3079,7 @@ void Test_TransmitMsg_GetPoolBufErr(void) UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetPoolBuf), 1, CFE_ES_ERR_MEM_BLOCK_SIZE); ASSERT_EQ(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true), CFE_SB_BUF_ALOC_ERR); - EVTCNT(4); + EVTCNT(3); EVTSENT(CFE_SB_GET_BUF_ERR_EID); @@ -3164,7 +3184,7 @@ void Test_TransmitBuffer_IncrementSeqCnt(void) ASSERT_EQ(SeqCnt, 1); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -3216,7 +3236,7 @@ void Test_TransmitBuffer_NoIncrement(void) ASSERT_TRUE(SendPtr == ReceivePtr); ASSERT_EQ(SeqCnt, 22); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -3304,7 +3324,7 @@ void Test_TransmitMsg_DisabledDestination(void) ASSERT(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true)); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -3320,11 +3340,11 @@ void Test_TransmitBufferFull(void) CFE_SB_PipeId_t PipeId; CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; CFE_SB_BufferD_t SBBufD; - CFE_MSG_Message_t Msg; + CFE_SB_Buffer_t MsgBuf; int32 PipeDepth; CFE_SBR_RouteId_t RouteId; - SBBufD.Buffer = &Msg; + SBBufD.Buffer = &MsgBuf; PipeDepth = 2; SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "TestPipe")); SETUP(CFE_SB_Subscribe(MsgId, PipeId)); @@ -3333,7 +3353,7 @@ void Test_TransmitBufferFull(void) ASSERT(CFE_SB_TransmitBufferFull(&SBBufD, RouteId, MsgId)); - EVTCNT(3); + EVTCNT(2); TEARDOWN(CFE_SB_DeletePipe(PipeId)); @@ -3410,9 +3430,7 @@ void Test_ReceiveBuffer_API(void) void Test_ReceiveBuffer_InvalidPipeId(void) { CFE_SB_Buffer_t *SBBufPtr; - CFE_SB_PipeId_t InvalidPipeId = 20; - - CFE_SB.PipeTbl[InvalidPipeId].InUse = CFE_SB_NOT_IN_USE; + CFE_SB_PipeId_t InvalidPipeId = SB_UT_ALTERNATE_INVALID_PIPEID; ASSERT_EQ(CFE_SB_ReceiveBuffer(&SBBufPtr, InvalidPipeId, CFE_SB_POLL), CFE_SB_BAD_ARGUMENT); @@ -3502,7 +3520,7 @@ void Test_ReceiveBuffer_PipeReadError(void) UT_SetDeferredRetcode(UT_KEY(OS_QueueGet), 1, OS_ERROR); ASSERT_EQ(CFE_SB_ReceiveBuffer(&SBBufPtr, PipeId, CFE_SB_PEND_FOREVER), CFE_SB_PIPE_RD_ERR); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_Q_RD_ERR_EID); @@ -3519,7 +3537,6 @@ void Test_ReceiveBuffer_PendForever(void) CFE_SB_MsgId_t MsgId = SB_UT_TLM_MID; CFE_SB_PipeId_t PipeId; SB_UT_Test_Tlm_t TlmPkt; - CFE_SB_PipeD_t *PipeDscPtr; uint32 PipeDepth = 10; CFE_MSG_Type_t Type = CFE_MSG_Type_Tlm; CFE_MSG_Size_t Size = sizeof(TlmPkt); @@ -3535,14 +3552,10 @@ void Test_ReceiveBuffer_PendForever(void) ASSERT_TRUE(SBBufPtr != NULL); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); - PipeDscPtr = CFE_SB_GetPipePtr(PipeId); - PipeDscPtr->ToTrashBuff = PipeDscPtr->CurrentBuff; - PipeDscPtr->CurrentBuff = NULL; - TEARDOWN(CFE_SB_DeletePipe(PipeId)); } /* end Test_ReceiveBuffer_PendForever */ @@ -3564,7 +3577,7 @@ void Test_CleanupApp_API(void) CFE_SB_ZeroCopyGetPtr(PipeDepth, &ZeroCpyBufHndl); /* Set second application ID to provide complete branch path coverage */ - CFE_SB.PipeTbl[1].InUse = CFE_SB_IN_USE; + CFE_SB.PipeTbl[1].PipeId = SB_UT_PIPEID_1; CFE_SB.PipeTbl[1].AppId = AppID; ASSERT_TRUE(CFE_SB.ZeroCopyTail != NULL); @@ -3579,7 +3592,7 @@ void Test_CleanupApp_API(void) ASSERT_TRUE(CFE_SB.ZeroCopyTail == NULL); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_PIPE_ADDED_EID); @@ -3724,7 +3737,6 @@ void Test_SB_SpecialCases(void) SB_UT_ADD_SUBTEST(Test_OS_MutSem_ErrLogic); SB_UT_ADD_SUBTEST(Test_ReqToSendEvent_ErrLogic); SB_UT_ADD_SUBTEST(Test_PutDestBlk_ErrLogic); - SB_UT_ADD_SUBTEST(Test_CFE_SB_GetPipeIdx); SB_UT_ADD_SUBTEST(Test_CFE_SB_Buffers); SB_UT_ADD_SUBTEST(Test_CFE_SB_BadPipeInfo); SB_UT_ADD_SUBTEST(Test_SB_TransmitMsgPaths_Nominal); @@ -3751,7 +3763,7 @@ void Test_OS_MutSem_ErrLogic(void) ASSERT(CFE_SB_Subscribe(MsgId, PipeId)); - EVTCNT(3); + EVTCNT(2); EVTSENT(CFE_SB_PIPE_ADDED_EID); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); @@ -3796,19 +3808,6 @@ void Test_PutDestBlk_ErrLogic(void) } /* end Test_PutDestBlk_ErrLogic */ -/* -** Test internal function to get the pipe table index for the given pipe ID -*/ -void Test_CFE_SB_GetPipeIdx(void) -{ - CFE_SB.PipeTbl[0].PipeId = 0; - CFE_SB.PipeTbl[0].InUse = CFE_SB_NOT_IN_USE; - ASSERT_EQ(CFE_SB_GetPipeIdx(0), CFE_SB_INVALID_PIPE); - - EVTCNT(0); - -} /* end Test_CFE_SB_GetPipeIdx */ - /* ** Test functions that involve a buffer in the SB buffer pool */ @@ -3855,6 +3854,7 @@ void Test_CFE_SB_Buffers(void) void Test_CFE_SB_BadPipeInfo(void) { CFE_SB_PipeId_t PipeId; + CFE_SB_PipeD_t *PipeDscPtr; uint16 PipeDepth = 10; CFE_SB_Qos_t CFE_SB_Default_Qos; CFE_ES_ResourceID_t AppID; @@ -3862,17 +3862,17 @@ void Test_CFE_SB_BadPipeInfo(void) SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "TestPipe1")); /* Set the pipe ID to an erroneous value and attempt to delete the pipe */ - CFE_SB.PipeTbl[0].PipeId = 1; - CFE_SB.PipeTbl[0].InUse = 1; + PipeDscPtr = CFE_SB_LocatePipeDescByID(PipeId); + PipeDscPtr->PipeId = SB_UT_PIPEID_1; CFE_ES_GetAppID(&AppID); - ASSERT_EQ(CFE_SB_DeletePipeFull(0, AppID), CFE_SB_BAD_ARGUMENT); + ASSERT_EQ(CFE_SB_DeletePipeFull(SB_UT_PIPEID_0, AppID), CFE_SB_BAD_ARGUMENT); EVTCNT(2); /* Reset the pipe ID and delete the pipe */ - CFE_SB.PipeTbl[0].PipeId = 0; + PipeDscPtr->PipeId = PipeId; - ASSERT_EQ(CFE_SB_SubscribeFull(SB_UT_FIRST_VALID_MID ,0, CFE_SB_Default_Qos, + ASSERT_EQ(CFE_SB_SubscribeFull(SB_UT_FIRST_VALID_MID , PipeId, CFE_SB_Default_Qos, CFE_PLATFORM_SB_DEFAULT_MSG_LIMIT, 2), CFE_SB_BAD_ARGUMENT); EVTCNT(4); @@ -4034,7 +4034,7 @@ void Test_SB_TransmitMsgPaths_FullErr(void) ASSERT_TRUE(!UT_EventIsInHistory(CFE_SB_Q_FULL_ERR_EID_BIT)); - EVTCNT(3); + EVTCNT(2); TEARDOWN(CFE_SB_DeletePipe(PipeId)); } /* end Test_SB_TransmitMsgPaths */ @@ -4068,7 +4068,7 @@ void Test_SB_TransmitMsgPaths_WriteErr(void) ASSERT(CFE_SB_TransmitMsg(&TlmPkt.Hdr.Msg, true)); - EVTCNT(3); + EVTCNT(2); ASSERT_TRUE(!UT_EventIsInHistory(CFE_SB_Q_WR_ERR_EID)); @@ -4131,9 +4131,10 @@ void Test_ReceiveBuffer_UnsubResubPath(void) ASSERT_TRUE(SBBufPtr != NULL); - EVTCNT(6); + EVTCNT(4); EVTSENT(CFE_SB_SUBSCRIPTION_RCVD_EID); + EVTSENT(CFE_SB_SUBSCRIPTION_REMOVED_EID); TEARDOWN(CFE_SB_DeletePipe(PipeId)); diff --git a/fsw/cfe-core/unit-test/sb_UT.h b/fsw/cfe-core/unit-test/sb_UT.h index 1420e762a..d2acfb22b 100644 --- a/fsw/cfe-core/unit-test/sb_UT.h +++ b/fsw/cfe-core/unit-test/sb_UT.h @@ -2440,23 +2440,6 @@ void Test_ReqToSendEvent_ErrLogic(void); ******************************************************************************/ void Test_PutDestBlk_ErrLogic(void); -/*****************************************************************************/ -/** -** \brief Test internal function to get the pipe table index for the given pipe -** ID -** -** \par Description -** This function tests the internal function to get the pipe table index -** for the given pipe ID when the ID is not in use. -** -** \par Assumptions, External Events, and Notes: -** None -** -** \returns -** This function does not return a value. -******************************************************************************/ -void Test_CFE_SB_GetPipeIdx(void); - /*****************************************************************************/ /** ** \brief Test functions that involve a buffer in the SB buffer pool diff --git a/fsw/cfe-core/unit-test/tbl_UT.c b/fsw/cfe-core/unit-test/tbl_UT.c index ad413dfda..2ef682879 100644 --- a/fsw/cfe-core/unit-test/tbl_UT.c +++ b/fsw/cfe-core/unit-test/tbl_UT.c @@ -2807,7 +2807,7 @@ void Test_CFE_TBL_Load(void) RtnCode = CFE_TBL_Load(App1TblHandle2, CFE_TBL_SRC_FILE, "TblSrcFileName.dat"); - EventsCorrect = (UT_EventIsInHistory(CFE_SUCCESS) == true && + EventsCorrect = (UT_EventIsInHistory(CFE_TBL_LOAD_TBLNAME_MISMATCH_ERR_EID) == true && UT_GetNumEventsSent() == 1); UT_Report(__FILE__, __LINE__, RtnCode == CFE_TBL_ERR_FILE_FOR_WRONG_TABLE && EventsCorrect, @@ -2846,7 +2846,7 @@ void Test_CFE_TBL_Load(void) UT_InitData(); UT_SetDeferredRetcode(UT_KEY(Test_CFE_TBL_ValidationFunc), 1, -1); RtnCode = CFE_TBL_Load(App1TblHandle1, CFE_TBL_SRC_ADDRESS, &TestTable1); - EventsCorrect = (UT_EventIsInHistory(CFE_SUCCESS) == true && + EventsCorrect = (UT_EventIsInHistory(CFE_TBL_VALIDATION_ERR_EID) == true && UT_GetNumEventsSent() == 1); UT_Report(__FILE__, __LINE__, RtnCode == -1 && EventsCorrect, @@ -2859,7 +2859,7 @@ void Test_CFE_TBL_Load(void) UT_InitData(); UT_SetDeferredRetcode(UT_KEY(Test_CFE_TBL_ValidationFunc), 1, 1); RtnCode = CFE_TBL_Load(App1TblHandle1, CFE_TBL_SRC_ADDRESS, &TestTable1); - EventsCorrect = (UT_EventIsInHistory(CFE_SUCCESS) == true && + EventsCorrect = (UT_EventIsInHistory(CFE_TBL_LOAD_VAL_ERR_EID) == true && UT_GetNumEventsSent() == 2); UT_Report(__FILE__, __LINE__, RtnCode == -1 && EventsCorrect, diff --git a/fsw/cfe-core/unit-test/ut_support.c b/fsw/cfe-core/unit-test/ut_support.c index e42dda886..b18a75203 100644 --- a/fsw/cfe-core/unit-test/ut_support.c +++ b/fsw/cfe-core/unit-test/ut_support.c @@ -398,6 +398,7 @@ static bool UT_CheckEventHistoryFromFunc(UT_EntryKey_t Func, uint16 EventIDToSea UT_GetDataBuffer(Func, (void**)&EvBuf, &MaxSize, &Position); if (EvBuf != NULL && MaxSize > 0) { + Position /= sizeof(*EvBuf); while (Position > 0) { if (*EvBuf == EventIDToSearchFor) diff --git a/fsw/cfe-core/ut-stubs/ut_es_stubs.c b/fsw/cfe-core/ut-stubs/ut_es_stubs.c index 6f7ad94e7..e6dabf5b6 100644 --- a/fsw/cfe-core/ut-stubs/ut_es_stubs.c +++ b/fsw/cfe-core/ut-stubs/ut_es_stubs.c @@ -1320,3 +1320,49 @@ int32 CFE_ES_TaskID_ToIndex(CFE_ES_ResourceID_t TaskID, uint32 *Idx) return return_code; } + +CFE_ES_ResourceID_t CFE_ES_FindNextAvailableId(CFE_ES_ResourceID_t StartId, uint32 TableSize, bool (*CheckFunc)(CFE_ES_ResourceID_t)) +{ + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_FindNextAvailableId), StartId); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_FindNextAvailableId), TableSize); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_FindNextAvailableId), CheckFunc); + + int32 return_code; + + /* Using "1" by default here produces a sequential result when called multiple times */ + return_code = UT_DEFAULT_IMPL_RC(CFE_ES_FindNextAvailableId, 1); + + if (return_code < 0) + { + return CFE_ES_RESOURCEID_UNDEFINED; + } + + /* + * The test case may set the return code to indicate the offset from the start ID + */ + return CFE_ES_ResourceID_FromInteger(CFE_ES_ResourceID_ToInteger(StartId) + return_code); +} + +int32 CFE_ES_ResourceID_ToIndex(uint32 Serial, uint32 TableSize, uint32 *Idx) +{ + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_ResourceID_ToIndex), Serial); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_ResourceID_ToIndex), TableSize); + UT_Stub_RegisterContextGenericArg(UT_KEY(CFE_ES_ResourceID_ToIndex), Idx); + + int32 return_code; + + return_code = UT_DEFAULT_IMPL(CFE_ES_ResourceID_ToIndex); + + if (return_code < 0) + { + /* fill with a very bad value that should cause a problem if used */ + *Idx = 0xDEADBEEF; + } + else if (UT_Stub_CopyToLocal(UT_KEY(CFE_ES_ResourceID_ToIndex), Idx, sizeof(*Idx)) < sizeof(*Idx)) + { + /* fill with default value if unspecified by test case */ + *Idx = Serial % TableSize; + } + + return return_code; +} diff --git a/fsw/cfe-core/ut-stubs/ut_sb_stubs.c b/fsw/cfe-core/ut-stubs/ut_sb_stubs.c index f34d7be20..a6bf2162d 100644 --- a/fsw/cfe-core/ut-stubs/ut_sb_stubs.c +++ b/fsw/cfe-core/ut-stubs/ut_sb_stubs.c @@ -289,7 +289,7 @@ int32 CFE_SB_GetPipeIdByName(CFE_SB_PipeId_t *PipeIdPtr, const char *PipeName) else { status = CFE_SB_BAD_ARGUMENT; - *PipeIdPtr = 0; + *PipeIdPtr = CFE_SB_INVALID_PIPE; } }