From 6932f1fe9180f4fd3f6756e4074b2c4b27a703cf Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 16 Oct 2020 12:05:36 -0400 Subject: [PATCH 1/3] Fix #950, race condition in control request Because the process of handling a control request involves calling other subsystems, the ES lock needs to be released. However, this also means that the app record can change state for other reasons, such as the app self-exiting at the same time. To avoid this possibility, process in two phases: First assemble a list of tasks that have timed out and need to be cleaned up, while ES is locked. Next actually perform the cleanup, while ES is unlocked. In areas during cleanup that need to update the ES global, the lock is locally re-acquired and released. --- fsw/cfe-core/src/es/cfe_es_apps.c | 766 ++++++++++++++++----------- fsw/cfe-core/src/es/cfe_es_apps.h | 4 +- fsw/cfe-core/src/inc/cfe_es_events.h | 14 +- fsw/cfe-core/unit-test/es_UT.c | 77 ++- 4 files changed, 516 insertions(+), 345 deletions(-) diff --git a/fsw/cfe-core/src/es/cfe_es_apps.c b/fsw/cfe-core/src/es/cfe_es_apps.c index ebd7916de..8cb13dd16 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.c +++ b/fsw/cfe-core/src/es/cfe_es_apps.c @@ -822,9 +822,11 @@ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, */ bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg) { - uint32 i; - CFE_ES_AppRecord_t *AppPtr; CFE_ES_AppTableScanState_t *State = (CFE_ES_AppTableScanState_t *)Arg; + uint32 i; + CFE_ES_AppRecord_t *AppPtr; + CFE_ES_ResourceID_t AppTimeoutList[CFE_PLATFORM_ES_MAX_APPLICATIONS]; + uint32 NumAppTimeouts; if (State->PendingAppStateChanges == 0) { @@ -845,6 +847,7 @@ bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg) * reset the background scan timer to the full value, * and take a snapshot of the the command counter. */ + NumAppTimeouts = 0; State->BackgroundScanTimer = CFE_PLATFORM_ES_APP_SCAN_RATE; State->LastScanCommandCount = CFE_ES_TaskData.CommandCounter; State->PendingAppStateChanges = 0; @@ -888,14 +891,10 @@ bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg) { AppPtr->ControlReq.AppTimerMsec = 0; - /* - * Temporarily unlock the table, and invoke the - * control request function for this app. - */ - CFE_ES_UnlockSharedData(__func__,__LINE__); - CFE_ES_ProcessControlRequest(AppPtr); - CFE_ES_LockSharedData(__func__,__LINE__); - } /* end if */ + /* Add it to the list to be processed later */ + AppTimeoutList[NumAppTimeouts] = CFE_ES_AppRecordGetID(AppPtr); + ++NumAppTimeouts; + } } else if (AppPtr->AppState == CFE_ES_AppState_RUNNING && AppPtr->ControlReq.AppControlRequest > CFE_ES_RunStatus_APP_RUN) @@ -915,6 +914,22 @@ bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg) CFE_ES_UnlockSharedData(__func__,__LINE__); + + /* + * Now invoke the CFE_ES_ProcessControlRequest() routine for any app + * which has reached that point. + */ + for ( i = 0; i < NumAppTimeouts; i++ ) + { + /* + * Call CFE_ES_ProcessControlRequest() with a reference to + * the _copies_ of the app record details. (This avoids + * needing to access the global records outside of the lock). + */ + CFE_ES_ProcessControlRequest(AppTimeoutList[i]); + } + + /* * This state machine is considered active if there are any * pending app state changes. Returning "true" will cause this job @@ -932,180 +947,228 @@ bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg) ** Purpose: This function will perform the requested control action for an application. **--------------------------------------------------------------------------------------- */ -void CFE_ES_ProcessControlRequest(CFE_ES_AppRecord_t *AppRecPtr) +void CFE_ES_ProcessControlRequest(CFE_ES_ResourceID_t AppId) { + CFE_ES_AppRecord_t *AppRecPtr; + uint32 PendingControlReq; + CFE_ES_AppStartParams_t OrigStartParams; + CFE_Status_t CleanupStatus; + CFE_Status_t StartupStatus; + CFE_ES_ResourceID_t NewAppId; + const char *ReqName; + char MessageDetail[48]; + uint16 EventID; + CFE_EVS_EventType_Enum_t EventType; + + /* Init/clear all local state variables */ + ReqName = NULL; + MessageDetail[0] = 0; + EventID = 0; + EventType = 0; + StartupStatus = CFE_SUCCESS; + PendingControlReq = 0; + NewAppId = CFE_ES_RESOURCEID_UNDEFINED; + AppRecPtr = CFE_ES_LocateAppRecordByID(AppId); + memset(&OrigStartParams, 0, sizeof(OrigStartParams)); - int32 Status; - CFE_ES_AppStartParams_t AppStartParams; - CFE_ES_ResourceID_t NewAppId; - /* - ** First get a copy of the Apps Start Parameters - */ - memcpy(&AppStartParams, &(AppRecPtr->StartParams), sizeof(CFE_ES_AppStartParams_t)); + /* + * Take a local snapshot of the important app record data + * This way it becomes private and can be accessed without + * concerns about other threads/tasks, even after the global + * data records are eventually cleared. + */ + CFE_ES_LockSharedData(__func__,__LINE__); - /* - ** Now, find out what kind of Application control is being requested - */ - switch ( AppRecPtr->ControlReq.AppControlRequest ) - { + if (CFE_ES_AppRecordIsMatch(AppRecPtr, AppId)) + { + PendingControlReq = AppRecPtr->ControlReq.AppControlRequest; + OrigStartParams = AppRecPtr->StartParams; + } - case CFE_ES_RunStatus_APP_EXIT: - /* - ** Kill the app, and dont restart it - */ - Status = CFE_ES_CleanUpApp(AppRecPtr); + CFE_ES_UnlockSharedData(__func__,__LINE__); - if ( Status == CFE_SUCCESS ) - { - CFE_EVS_SendEvent(CFE_ES_EXIT_APP_INF_EID, CFE_EVS_EventType_INFORMATION, - "Exit Application %s Completed.",AppStartParams.Name); - } - else - { - CFE_EVS_SendEvent(CFE_ES_EXIT_APP_ERR_EID, CFE_EVS_EventType_ERROR, - "Exit Application %s Failed: CleanUpApp Error 0x%08X.",AppStartParams.Name, (unsigned int)Status); - } - break; + /* + * All control requests start by deleting the app/task and + * all associated resources. + * + * The reload/restart requests will start it again, and it gets + * a new appID. For other requests it just leaves it deleted. + * + * Note that Cleanup can fail for a variety of reasons, including + * situations where e.g. a task ID had become stale because the task + * already exited itself. In most cases these are minor errors and + * reflect problems with the consistency of the old app record. + * + * Even when this happens the cleanup should still do its best effort + * to release all relevant global data entries. So it should not + * prevent starting the new app, if a restart/reload is indicated. + */ + CleanupStatus = CFE_ES_CleanUpApp(AppId); - case CFE_ES_RunStatus_APP_ERROR: - /* - ** Kill the app, and dont restart it - */ - Status = CFE_ES_CleanUpApp(AppRecPtr); + /* + * Attempt to restart the app if the request indicated to do so, + * regardless of the CleanupStatus. + */ + if ( PendingControlReq == CFE_ES_RunStatus_SYS_RESTART || + PendingControlReq == CFE_ES_RunStatus_SYS_RELOAD ) + { + StartupStatus = CFE_ES_AppCreate(&NewAppId, + OrigStartParams.FileName, + OrigStartParams.EntryPoint, + OrigStartParams.Name, + OrigStartParams.Priority, + OrigStartParams.StackSize, + OrigStartParams.ExceptionAction); + } - if ( Status == CFE_SUCCESS ) - { - CFE_EVS_SendEvent(CFE_ES_ERREXIT_APP_INF_EID, CFE_EVS_EventType_INFORMATION, - "Exit Application %s on Error Completed.",AppStartParams.Name); - } - else - { - CFE_EVS_SendEvent(CFE_ES_ERREXIT_APP_ERR_EID, CFE_EVS_EventType_ERROR, - "Exit Application %s on Error Failed: CleanUpApp Error 0x%08X.",AppStartParams.Name, (unsigned int)Status); - } - break; + /* + * Determine the event ID associated with the control request, + * which indicates the success/failure of the operation and + * any other relevant detail. + * + * Note that the specific event ID that gets generated is the only + * other difference between all these control request types. + */ + switch ( PendingControlReq ) + { + case CFE_ES_RunStatus_APP_EXIT: + ReqName = "Exit"; + if (CleanupStatus != CFE_SUCCESS) + { + /* error event for this request */ + EventID = CFE_ES_EXIT_APP_ERR_EID; + } + else + { + /* success event for this request */ + EventID = CFE_ES_EXIT_APP_INF_EID; + } + break; - case CFE_ES_RunStatus_SYS_DELETE: - /* - ** Kill the app, and dont restart it - */ - Status = CFE_ES_CleanUpApp(AppRecPtr); + case CFE_ES_RunStatus_APP_ERROR: + ReqName = "Exit"; + if ( CleanupStatus != CFE_SUCCESS ) + { + /* error event for this request */ + EventID = CFE_ES_ERREXIT_APP_ERR_EID; + } + else + { + /* success event for this request */ + EventID = CFE_ES_ERREXIT_APP_INF_EID; + } + break; - if ( Status == CFE_SUCCESS ) - { - CFE_EVS_SendEvent(CFE_ES_STOP_INF_EID, CFE_EVS_EventType_INFORMATION, - "Stop Application %s Completed.",AppStartParams.Name); - } - else - { - CFE_EVS_SendEvent(CFE_ES_STOP_ERR3_EID, CFE_EVS_EventType_ERROR, - "Stop Application %s Failed: CleanUpApp Error 0x%08X.",AppStartParams.Name, (unsigned int)Status); - } - break; + case CFE_ES_RunStatus_SYS_DELETE: + ReqName = "Stop"; + if ( CleanupStatus != CFE_SUCCESS ) + { + /* error event for this request */ + EventID = CFE_ES_STOP_ERR3_EID; + } + else + { + /* success event for this request */ + EventID = CFE_ES_STOP_INF_EID; + } + break; - case CFE_ES_RunStatus_SYS_RESTART: - /* - ** Kill the app - */ - Status = CFE_ES_CleanUpApp(AppRecPtr); + case CFE_ES_RunStatus_SYS_RESTART: + ReqName = "Restart"; + if ( CleanupStatus != CFE_SUCCESS ) + { + /* error event for this request */ + EventID = CFE_ES_RESTART_APP_ERR4_EID; + } + else if ( StartupStatus != CFE_SUCCESS ) + { + /* error event for this request */ + EventID = CFE_ES_RESTART_APP_ERR3_EID; + } + else + { + /* success event for this request */ + EventID = CFE_ES_RESTART_APP_INF_EID; + } + break; - if ( Status == CFE_SUCCESS ) - { - /* - ** And start it back up again - */ - Status = CFE_ES_AppCreate(&NewAppId, (char *)AppStartParams.FileName, - (char *)AppStartParams.EntryPoint, - (char *)AppStartParams.Name, - AppStartParams.Priority, - AppStartParams.StackSize, - AppStartParams.ExceptionAction); - - if ( Status == CFE_SUCCESS ) - { - CFE_EVS_SendEvent(CFE_ES_RESTART_APP_INF_EID, CFE_EVS_EventType_INFORMATION, - "Restart Application %s Completed.", AppStartParams.Name); - } - else - { - CFE_EVS_SendEvent(CFE_ES_RESTART_APP_ERR3_EID, CFE_EVS_EventType_ERROR, - "Restart Application %s Failed: AppCreate Error 0x%08X.", AppStartParams.Name, (unsigned int)Status); - } - } - else - { - CFE_EVS_SendEvent(CFE_ES_RESTART_APP_ERR4_EID, CFE_EVS_EventType_ERROR, - "Restart Application %s Failed: CleanUpApp Error 0x%08X.", AppStartParams.Name, (unsigned int)Status); - } - break; + case CFE_ES_RunStatus_SYS_RELOAD: + ReqName = "Reload"; + if ( CleanupStatus != CFE_SUCCESS ) + { + /* error event for this request */ + EventID = CFE_ES_RELOAD_APP_ERR4_EID; + } + else if ( StartupStatus != CFE_SUCCESS ) + { + /* error event for this request */ + EventID = CFE_ES_RELOAD_APP_ERR3_EID; + } + else + { + /* success event for this request */ + EventID = CFE_ES_RELOAD_APP_INF_EID; + } + break; - case CFE_ES_RunStatus_SYS_RELOAD: - /* - ** Kill the app + /* + * These two cases below should never occur so they are always + * reported as errors, but the CFE_ES_CleanUpApp() should hopefully + * have fixed it either way. */ - Status = CFE_ES_CleanUpApp(AppRecPtr); - - if ( Status == CFE_SUCCESS ) - { - /* - ** And start it back up again - */ - Status = CFE_ES_AppCreate(&NewAppId, (char *)AppStartParams.FileName, - (char *)AppStartParams.EntryPoint, - (char *)AppStartParams.Name, - AppStartParams.Priority, - AppStartParams.StackSize, - AppStartParams.ExceptionAction); - if ( Status == CFE_SUCCESS ) - { - CFE_EVS_SendEvent(CFE_ES_RELOAD_APP_INF_EID, CFE_EVS_EventType_INFORMATION, - "Reload Application %s Completed.", AppStartParams.Name); - } - else - { - CFE_EVS_SendEvent(CFE_ES_RELOAD_APP_ERR3_EID, CFE_EVS_EventType_ERROR, - "Reload Application %s Failed: AppCreate Error 0x%08X.", AppStartParams.Name, (unsigned int)Status); - } - } - else - { - CFE_EVS_SendEvent(CFE_ES_RELOAD_APP_ERR4_EID, CFE_EVS_EventType_ERROR, - "Reload Application %s Failed: CleanUpApp Error 0x%08X.", AppStartParams.Name, (unsigned int)Status); - } - - break; - - case CFE_ES_RunStatus_SYS_EXCEPTION: - - CFE_EVS_SendEvent(CFE_ES_PCR_ERR1_EID, CFE_EVS_EventType_ERROR, - "ES_ProcControlReq: Invalid State (EXCEPTION) Application %s.", - AppStartParams.Name); - /* - * Bug #58: This message/event keeps repeating itself indefinitely. - * - * Change the request state to DELETE so the next scan will clean - * up this table entry. - */ - AppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_DELETE; - break; - - default: + case CFE_ES_RunStatus_SYS_EXCEPTION: + ReqName = "ES_ProcControlReq: Invalid State"; + EventID = CFE_ES_PCR_ERR1_EID; + snprintf(MessageDetail, sizeof(MessageDetail), "EXCEPTION"); + break; - CFE_EVS_SendEvent(CFE_ES_PCR_ERR2_EID, CFE_EVS_EventType_ERROR, - "ES_ProcControlReq: Unknown State ( %d ) Application %s.", - (int)AppRecPtr->ControlReq.AppControlRequest, AppStartParams.Name); + default: + ReqName = "ES_ProcControlReq: Unknown State"; + EventID = CFE_ES_PCR_ERR2_EID; + snprintf(MessageDetail, sizeof(MessageDetail), "( %lu )", + (unsigned long)PendingControlReq); + break; + } - /* - * Bug #58: This message/event keeps repeating itself indefinitely. - * - * Change the request state to DELETE so the next scan will clean - * up this table entry. - */ - AppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_DELETE; - break; + if (EventID != 0 && ReqName != NULL) + { + if ( MessageDetail[0] != 0 ) + { + /* Detail message already set, assume it is an error event */ + EventType = CFE_EVS_EventType_ERROR; + } + else if ( StartupStatus != CFE_SUCCESS ) + { + /* Make detail message for event containing startup error code */ + EventType = CFE_EVS_EventType_ERROR; + snprintf(MessageDetail, sizeof(MessageDetail), + "Failed: AppCreate Error 0x%08X.",(unsigned int)StartupStatus); + } + else if ( CleanupStatus != CFE_SUCCESS ) + { + /* Make detail message for event containing cleanup error code */ + EventType = CFE_EVS_EventType_ERROR; + snprintf(MessageDetail, sizeof(MessageDetail), + "Failed: CleanUpApp Error 0x%08X.",(unsigned int)CleanupStatus); + } + else if (CFE_ES_ResourceID_IsDefined(NewAppId)) + { + /* Record success message for event where app is restarted */ + EventType = CFE_EVS_EventType_INFORMATION; + snprintf(MessageDetail, sizeof(MessageDetail), "Completed, AppID=%lu", + CFE_ES_ResourceID_ToInteger(NewAppId)); + } + else + { + /* Record success message for event */ + EventType = CFE_EVS_EventType_INFORMATION; + snprintf(MessageDetail, sizeof(MessageDetail), "Completed."); + } - } + CFE_EVS_SendEvent(EventID, EventType, "%s Application %s %s", + ReqName, OrigStartParams.Name, MessageDetail); + } } /* End Function */ @@ -1116,154 +1179,248 @@ void CFE_ES_ProcessControlRequest(CFE_ES_AppRecord_t *AppRecPtr) ** Purpose: Delete an application by cleaning up all of it's resources. **--------------------------------------------------------------------------------------- */ -int32 CFE_ES_CleanUpApp(CFE_ES_AppRecord_t *AppRecPtr) +int32 CFE_ES_CleanUpApp(CFE_ES_ResourceID_t AppId) { - uint32 i; - int32 Status; - CFE_ES_ResourceID_t MainTaskId; - CFE_ES_ResourceID_t CurrTaskId; - int32 ReturnCode = CFE_SUCCESS; - CFE_ES_TaskRecord_t *TaskRecPtr; - CFE_ES_MemPoolRecord_t *MemPoolRecPtr; - CFE_ES_MemHandle_t PoolId; - CFE_ES_ResourceID_t AppId; + uint32 i; + int32 Status; + int32 ReturnCode; + CFE_ES_ResourceID_t TaskList[OS_MAX_TASKS]; + CFE_ES_MemHandle_t PoolList[CFE_PLATFORM_ES_MAX_MEMORY_POOLS]; + osal_id_t ModuleId; + uint32 NumTasks; + uint32 NumPools; + CFE_ES_AppRecord_t *AppRecPtr; + CFE_ES_TaskRecord_t *TaskRecPtr; + CFE_ES_MemPoolRecord_t *MemPoolRecPtr; - /* - * Retrieve the abstract AppID for calling cleanup - * routine in _other_ modules. - */ - AppId = CFE_ES_AppRecordGetID(AppRecPtr); - /* - ** Call the Table Clean up function - */ -#ifndef EXCLUDE_CFE_TBL - CFE_TBL_CleanUpApp(AppId); -#endif - /* - ** Call the Software Bus clean up function - */ - CFE_SB_CleanUpApp(AppId); + NumTasks = 0; + NumPools = 0; + ModuleId = OS_OBJECT_ID_UNDEFINED; + ReturnCode = CFE_SUCCESS; - /* - ** Call the TIME Clean up function - */ - CFE_TIME_CleanUpApp(AppId); + AppRecPtr = CFE_ES_LocateAppRecordByID(AppId); - /* - ** Call the EVS Clean up function - */ - Status = CFE_EVS_CleanUpApp(AppId); - if ( Status != CFE_SUCCESS ) - { - CFE_ES_WriteToSysLog("CFE_ES_CleanUpApp: Call to CFE_EVS_CleanUpApp returned Error: 0x%08X\n",(unsigned int)Status); - ReturnCode = CFE_ES_APP_CLEANUP_ERR; - } + /* + * Collect a list of resources previously owned by this app, which + * must be done while the global data is locked. + */ + CFE_ES_LockSharedData(__func__,__LINE__); + if (CFE_ES_AppRecordIsMatch(AppRecPtr, AppId)) + { + if (AppRecPtr->Type == CFE_ES_AppType_EXTERNAL) + { + CFE_ES_Global.RegisteredExternalApps--; - /* - ** Delete the ES Resources - */ - CFE_ES_LockSharedData(__func__,__LINE__); + /* + * Get the Module ID, if it was an external app + * + * (this will be OS_OBJECT_ID_UNDEFINED if it was not loaded dynamically) + */ + ModuleId = AppRecPtr->StartParams.ModuleId; + } - /* - ** Get Main Task ID - */ - MainTaskId = AppRecPtr->MainTaskId; + /* + * Collect all tasks associated with this app + */ + TaskRecPtr = CFE_ES_Global.TaskTable; + for ( i = 0; i < OS_MAX_TASKS; i++ ) + { + if ( CFE_ES_TaskRecordIsUsed(TaskRecPtr) && + CFE_ES_ResourceID_Equal(TaskRecPtr->AppId, AppId)) + { + TaskList[NumTasks] = CFE_ES_TaskRecordGetID(TaskRecPtr); - /* - ** Delete any child tasks associated with this app - */ - TaskRecPtr = CFE_ES_Global.TaskTable; - for ( i = 0; i < OS_MAX_TASKS; i++ ) - { - /* delete only CHILD tasks - not the MainTaskId, which will be deleted later (below) */ - if ( CFE_ES_TaskRecordIsUsed(TaskRecPtr) && - CFE_ES_ResourceID_Equal(TaskRecPtr->AppId, AppId)) - { - CurrTaskId = CFE_ES_TaskRecordGetID(TaskRecPtr); - if (!CFE_ES_ResourceID_Equal(CurrTaskId, MainTaskId)) - { - Status = CFE_ES_CleanupTaskResources(CurrTaskId); - if ( Status != CFE_SUCCESS ) - { - CFE_ES_SysLogWrite_Unsync("CFE_ES_CleanUpApp: CleanUpTaskResources for Task ID:%lu returned Error: 0x%08X\n", - CFE_ES_ResourceID_ToInteger(CurrTaskId), (unsigned int)Status); - ReturnCode = CFE_ES_APP_CLEANUP_ERR; - } - } /* end if */ - } + /* Store the main task ID at index 0 (swap with whatever was there) */ + if (CFE_ES_ResourceID_Equal(TaskList[NumTasks], AppRecPtr->MainTaskId) && + NumTasks != 0) + { + TaskList[NumTasks] = TaskList[0]; + TaskList[0] = AppRecPtr->MainTaskId; + } - ++TaskRecPtr; - } /* end for */ + /* Mark record for removal */ + CFE_ES_TaskRecordSetUsed(TaskRecPtr, CFE_ES_RESOURCEID_RESERVED); + ++NumTasks; + } - /* - ** Delete all of the OS resources, close files, and delete the main task - */ - Status = CFE_ES_CleanupTaskResources(MainTaskId); - if ( Status != CFE_SUCCESS ) - { - CFE_ES_SysLogWrite_Unsync("CFE_ES_CleanUpApp: CleanUpTaskResources for Task ID:%lu returned Error: 0x%08X\n", - CFE_ES_ResourceID_ToInteger(MainTaskId), (unsigned int)Status); - ReturnCode = CFE_ES_APP_CLEANUP_ERR; + ++TaskRecPtr; + } /* end for */ - } + CFE_ES_Global.RegisteredTasks -= NumTasks; - /* - ** Remove the app from the AppTable - */ - if ( AppRecPtr->Type == CFE_ES_AppType_EXTERNAL ) - { - /* - ** Unload the module only if it is an external app - */ - Status = OS_ModuleUnload(AppRecPtr->StartParams.ModuleId); - if ( Status == OS_ERROR ) - { - CFE_ES_SysLogWrite_Unsync("CFE_ES_CleanUpApp: Module (ID:0x%08lX) Unload failed. RC=0x%08X\n", - OS_ObjectIdToInteger(AppRecPtr->StartParams.ModuleId), (unsigned int)Status); - ReturnCode = CFE_ES_APP_CLEANUP_ERR; - } - CFE_ES_Global.RegisteredExternalApps--; - } + /* + * Collect memory pools associated with this app + */ + MemPoolRecPtr = CFE_ES_Global.MemPoolTable; + for ( i = 0; i < CFE_PLATFORM_ES_MAX_MEMORY_POOLS; i++ ) + { + if ( CFE_ES_MemPoolRecordIsUsed(MemPoolRecPtr) && + CFE_ES_ResourceID_Equal(MemPoolRecPtr->OwnerAppID, AppId)) + { + PoolList[NumPools] = CFE_ES_MemPoolRecordGetID(MemPoolRecPtr); + ++NumPools; + } - CFE_ES_AppRecordSetFree(AppRecPtr); + ++MemPoolRecPtr; + } /* end for */ - /* - ** Delete any memory pools associated with this app - */ - MemPoolRecPtr = CFE_ES_Global.MemPoolTable; - for ( i = 0; i < CFE_PLATFORM_ES_MAX_MEMORY_POOLS; i++ ) - { - if ( CFE_ES_MemPoolRecordIsUsed(MemPoolRecPtr) && - CFE_ES_ResourceID_Equal(MemPoolRecPtr->OwnerAppID, AppId)) - { - PoolId = CFE_ES_MemPoolRecordGetID(MemPoolRecPtr); + /* + * Set the record to RESERVED. + * + * This prevents reallocation of this slot while the remainder + * of resources are freed. + */ + CFE_ES_AppRecordSetUsed(AppRecPtr, CFE_ES_RESOURCEID_RESERVED); - /* - * This needs to release the lock first because - * CFE_ES_PoolDelete acquires the lock. - */ - CFE_ES_UnlockSharedData(__func__, __LINE__); - Status = CFE_ES_PoolDelete(PoolId); - CFE_ES_LockSharedData(__func__, __LINE__); + ReturnCode = CFE_SUCCESS; + } + else + { + CFE_ES_SysLogWrite_Unsync("CFE_ES_CleanUpApp: AppID %lu is not valid for deletion\n", + CFE_ES_ResourceID_ToInteger(AppId)); + ReturnCode = CFE_ES_APP_CLEANUP_ERR; + } - if ( Status != CFE_SUCCESS ) - { - CFE_ES_SysLogWrite_Unsync("CFE_ES_MemPoolCleanupApp: delete pool %lu returned Error: 0x%08X\n", - CFE_ES_ResourceID_ToInteger(PoolId), (unsigned int)Status); - ReturnCode = CFE_ES_APP_CLEANUP_ERR; - } - } + CFE_ES_UnlockSharedData(__func__, __LINE__); - ++MemPoolRecPtr; - } /* end for */ + if (ReturnCode != CFE_SUCCESS) + { + return ReturnCode; + } + /* + * Now actually delete all the resources associated with the task. + * + * Most of this involves calling into other subsystems, so it is + * done while the ES global data is UNLOCKED to avoid holding more + * than one lock at a time. + */ - CFE_ES_UnlockSharedData(__func__,__LINE__); + /* + ** Call the Table Clean up function + */ + CFE_TBL_CleanUpApp(AppId); - return(ReturnCode); + /* + ** Call the Software Bus clean up function + */ + CFE_SB_CleanUpApp(AppId); + + /* + ** Call the TIME Clean up function + */ + CFE_TIME_CleanUpApp(AppId); + + /* + ** Call the EVS Clean up function + */ + Status = CFE_EVS_CleanUpApp(AppId); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("CFE_ES_CleanUpApp: Call to CFE_EVS_CleanUpApp returned Error: 0x%08X\n",(unsigned int)Status); + ReturnCode = CFE_ES_APP_CLEANUP_ERR; + } + + /* + * Delete all tasks. + * + * Note that the main task is always positioned at index 0 in this list. + * + * This iterates the list in reverse order, such that the child + * tasks are deleted first (in any order) and main task is deleted last. + */ + i = NumTasks; + while (i > 0) + { + --i; + Status = CFE_ES_CleanupTaskResources(TaskList[i]); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("CFE_ES_CleanUpApp: CleanUpTaskResources for Task ID:%lu returned Error: 0x%08X\n", + CFE_ES_ResourceID_ToInteger(TaskList[i]), (unsigned int)Status); + ReturnCode = CFE_ES_APP_CLEANUP_ERR; + } + } + + /* + * Delete all mem pools. + */ + for (i=0; i < NumPools; ++i) + { + Status = CFE_ES_PoolDelete(PoolList[i]); + if ( Status != CFE_SUCCESS ) + { + CFE_ES_WriteToSysLog("CFE_ES_MemPoolCleanupApp: delete pool %lu returned Error: 0x%08X\n", + CFE_ES_ResourceID_ToInteger(PoolList[i]), (unsigned int)Status); + ReturnCode = CFE_ES_APP_CLEANUP_ERR; + } + } + + /* + ** Unload the module, if applicable + */ + if ( OS_ObjectIdDefined(ModuleId) ) + { + /* + ** Unload the module only if it is an external app + */ + Status = OS_ModuleUnload(ModuleId); + if ( Status != OS_SUCCESS ) + { + CFE_ES_WriteToSysLog("CFE_ES_CleanUpApp: Module (ID:0x%08lX) Unload failed. RC=0x%08X\n", + OS_ObjectIdToInteger(ModuleId), (unsigned int)Status); + ReturnCode = CFE_ES_APP_CLEANUP_ERR; + } + } + + /* + * Finally, re-acquire the ES lock and set all + * table entries free for re-use. + */ + CFE_ES_LockSharedData(__func__,__LINE__); + +#ifdef jphfix + /* + * This just confirms that the main task ID associated with this app was properly + * located and deleted during the previous process. + * + * If not, display a log message about it - this indicates table corruption or a + * bug with the record keeping. + */ + if (NumTasks == 0 || !CFE_ES_ResourceID_Equal(TaskList[0], AppRecPtr->MainTaskId)) + { + CFE_ES_SysLogWrite_Unsync("CFE_ES_CleanUpApp: MainTask ID:%lu not found when deleting AppID %lu\n", + CFE_ES_ResourceID_ToInteger(AppRecPtr->MainTaskId), CFE_ES_ResourceID_ToInteger(AppId)); + ReturnCode = CFE_ES_APP_CLEANUP_ERR; + } +#endif + + /* + * Free all task records. + */ + for (i=0; i < NumTasks; ++i) + { + TaskRecPtr = CFE_ES_LocateTaskRecordByID(TaskList[i]); + if (CFE_ES_TaskRecordIsMatch(TaskRecPtr, CFE_ES_RESOURCEID_RESERVED)) + { + CFE_ES_TaskRecordSetFree(TaskRecPtr); + } + } + + /* + * Now finally delete the record and allow re-use of the slot. + */ + if (CFE_ES_AppRecordIsMatch(AppRecPtr, CFE_ES_RESOURCEID_RESERVED)) + { + CFE_ES_AppRecordSetFree(AppRecPtr); + } + + CFE_ES_UnlockSharedData(__func__,__LINE__); + + return(ReturnCode); } /* end function */ @@ -1387,13 +1544,14 @@ void CFE_ES_CleanupObjectCallback(osal_id_t ObjectId, void *arg) ** Name: CFE_ES_CleanupTaskResources ** ** Purpose: Clean up the OS resources associated with an individual Task +** Note: This is called when the ES global is UNLOCKED - so it should not touch +** any ES global data structures. It should only clean up at the OSAL level. **--------------------------------------------------------------------------------------- */ int32 CFE_ES_CleanupTaskResources(CFE_ES_ResourceID_t TaskId) { CFE_ES_CleanupState_t CleanState; int32 Result; - CFE_ES_TaskRecord_t *TaskRecPtr; osal_id_t OsalId; /* Get the Task ID for calling OSAL APIs (convert type) */ @@ -1424,16 +1582,15 @@ int32 CFE_ES_CleanupTaskResources(CFE_ES_ResourceID_t TaskId) CleanState.DeletedObjects = 0; } - /* - * Locate the ES Task table entry - */ - TaskRecPtr = CFE_ES_LocateTaskRecordByID(TaskId); - /* ** Delete the task itself + ** + ** Note, if the task self exited, then the ID becomes invalid. + ** In this case the OS_ERR_INVALID_ID status is returned, but + ** that is OK, there is nothing else needed to do. */ Result = OS_TaskDelete(OsalId); - if (Result == OS_SUCCESS) + if (Result == OS_SUCCESS || Result == OS_ERR_INVALID_ID) { Result = CleanState.OverallStatus; if (Result == CFE_SUCCESS && CleanState.FoundObjects > 0) @@ -1447,15 +1604,6 @@ int32 CFE_ES_CleanupTaskResources(CFE_ES_ResourceID_t TaskId) Result = CFE_ES_TASK_DELETE_ERR; } - /* - ** Invalidate ES Task Table entry - */ - if (TaskRecPtr != NULL) - { - CFE_ES_TaskRecordSetFree(TaskRecPtr); - } - - CFE_ES_Global.RegisteredTasks--; return(Result); } diff --git a/fsw/cfe-core/src/es/cfe_es_apps.h b/fsw/cfe-core/src/es/cfe_es_apps.h index fa29774b4..4cf2c11bc 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.h +++ b/fsw/cfe-core/src/es/cfe_es_apps.h @@ -199,12 +199,12 @@ bool CFE_ES_RunERLogDump(uint32 ElapsedTime, void *Arg); /* ** Perform the requested control action for an application */ -void CFE_ES_ProcessControlRequest(CFE_ES_AppRecord_t *AppRecPtr); +void CFE_ES_ProcessControlRequest(CFE_ES_ResourceID_t AppId); /* ** Clean up all app resources and delete it */ -int32 CFE_ES_CleanUpApp(CFE_ES_AppRecord_t *AppRecPtr); +int32 CFE_ES_CleanUpApp(CFE_ES_ResourceID_t AppId); /* ** Clean up all Task resources and detete the task diff --git a/fsw/cfe-core/src/inc/cfe_es_events.h b/fsw/cfe-core/src/inc/cfe_es_events.h index c7bad610e..8b0f4b432 100644 --- a/fsw/cfe-core/src/inc/cfe_es_events.h +++ b/fsw/cfe-core/src/inc/cfe_es_events.h @@ -167,8 +167,8 @@ **/ #define CFE_ES_RESTART_APP_DBG_EID 9 -/** \brief 'Restart Application \%s Completed.' -** \event 'Restart Application \%s Completed.' +/** \brief 'Restart Application \%s Completed, AppID=%lu' +** \event 'Restart Application \%s Completed, AppID=%lu' ** ** \par Type: INFORMATION ** @@ -178,7 +178,8 @@ ** That was started when the \link #CFE_ES_RESTART_APP_CC Restart Application command \endlink ** was issued. ** -** The \c 's' field identifies the name of the Application that was reloaded. +** The \c 's' field identifies the name of the Application that was restarted, and +** the %lu field identifies the new Application ID */ #define CFE_ES_RESTART_APP_INF_EID 10 @@ -202,8 +203,8 @@ #define CFE_ES_RELOAD_APP_DBG_EID 11 -/** \brief 'Reload Application \%s Completed.' -** \event 'Reload Application \%s Completed.' +/** \brief 'Reload Application \%s Completed, AppID=%lu' +** \event 'Reload Application \%s Completed, AppID=%lu' ** ** \par Type: INFORMATION ** @@ -213,7 +214,8 @@ ** That was started when the \link #CFE_ES_RELOAD_APP_CC Restart Application command \endlink ** was issued. ** -** The \c 's' field identifies the name of the Application that was reloaded. +** The \c 's' field identifies the name of the Application that was reloaded, and +** the %lu field identifies the new Application ID */ #define CFE_ES_RELOAD_APP_INF_EID 12 diff --git a/fsw/cfe-core/unit-test/es_UT.c b/fsw/cfe-core/unit-test/es_UT.c index fe99f690e..3a134cf50 100644 --- a/fsw/cfe-core/unit-test/es_UT.c +++ b/fsw/cfe-core/unit-test/es_UT.c @@ -1437,8 +1437,7 @@ void TestApps(void) CFE_ES_RunAppTableScan(0, &CFE_ES_TaskData.BackgroundAppScanState); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_PCR_ERR2_EID) && - UtAppRecPtr->ControlReq.AppTimerMsec == 0 && - UtAppRecPtr->ControlReq.AppControlRequest == CFE_ES_RunStatus_SYS_DELETE, + UtAppRecPtr->ControlReq.AppTimerMsec == 0, "CFE_ES_RunAppTableScan", "Waiting; process control request"); @@ -1466,7 +1465,6 @@ void TestApps(void) CFE_ES_RunAppTableScan(0, &CFE_ES_TaskData.BackgroundAppScanState); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_PCR_ERR2_EID) && - UtAppRecPtr->ControlReq.AppControlRequest == CFE_ES_RunStatus_SYS_DELETE && UtAppRecPtr->ControlReq.AppTimerMsec == 0, "CFE_ES_RunAppTableScan", "Stopped; process control request"); @@ -1490,7 +1488,8 @@ void TestApps(void) ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); UtAppRecPtr->ControlReq.AppControlRequest = 0x12345; - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_PCR_ERR2_EID), "CFE_ES_ProcessControlRequest", @@ -1512,7 +1511,8 @@ void TestApps(void) OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_EXIT; - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_EXIT_APP_INF_EID), "CFE_ES_ProcessControlRequest", @@ -1526,7 +1526,8 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_EXIT; UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_EXIT_APP_ERR_EID), "CFE_ES_ProcessControlRequest", @@ -1541,7 +1542,8 @@ void TestApps(void) CFE_ES_RunStatus_SYS_DELETE; UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_STOP_ERR3_EID), "CFE_ES_ProcessControlRequest", @@ -1556,7 +1558,8 @@ void TestApps(void) CFE_ES_RunStatus_SYS_RESTART; UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_RESTART_APP_ERR4_EID), "CFE_ES_ProcessControlRequest", @@ -1571,7 +1574,8 @@ void TestApps(void) CFE_ES_RunStatus_SYS_RESTART; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UT_SetForceFail(UT_KEY(OS_TaskCreate), OS_ERROR); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_RESTART_APP_ERR3_EID), "CFE_ES_ProcessControlRequest", @@ -1586,7 +1590,8 @@ void TestApps(void) CFE_ES_RunStatus_SYS_RELOAD; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_RELOAD_APP_ERR4_EID), "CFE_ES_ProcessControlRequest", @@ -1601,7 +1606,8 @@ void TestApps(void) CFE_ES_RunStatus_SYS_RELOAD; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UT_SetForceFail(UT_KEY(OS_TaskCreate), OS_ERROR); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_RELOAD_APP_ERR3_EID), "CFE_ES_ProcessControlRequest", @@ -1625,7 +1631,8 @@ void TestApps(void) OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_ERROR; - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_ERREXIT_APP_INF_EID), "CFE_ES_ProcessControlRequest", @@ -1640,7 +1647,8 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_ERROR; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_ERREXIT_APP_ERR_EID), "CFE_ES_ProcessControlRequest", @@ -1662,7 +1670,8 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_DELETE; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_STOP_INF_EID), "CFE_ES_ProcessControlRequest", @@ -1684,7 +1693,8 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RESTART; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_RESTART_APP_INF_EID), "CFE_ES_ProcessControlRequest", @@ -1706,7 +1716,8 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RELOAD; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_RELOAD_APP_INF_EID), "CFE_ES_ProcessControlRequest", @@ -1730,7 +1741,8 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_EXCEPTION; OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); - CFE_ES_ProcessControlRequest(UtAppRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); + CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_PCR_ERR1_EID), "CFE_ES_ProcessControlRequest", @@ -1800,8 +1812,9 @@ void TestApps(void) OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UT_SetForceFail(UT_KEY(OS_TaskDelete), OS_ERROR); UT_SetForceFail(UT_KEY(OS_close), OS_ERROR); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_ES_APP_CLEANUP_ERR, + CFE_ES_CleanUpApp(Id) == CFE_ES_APP_CLEANUP_ERR, "CFE_ES_CleanUpApp", "Task OS delete and close failure"); @@ -1814,8 +1827,9 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, NULL, NULL); ES_UT_SetupForOSCleanup(); UT_SetDeferredRetcode(UT_KEY(OS_MutSemDelete), 1, OS_ERROR); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_ES_APP_CLEANUP_ERR, + CFE_ES_CleanUpApp(Id) == CFE_ES_APP_CLEANUP_ERR, "CFE_ES_CleanUpApp", "Task mutex delete failure"); @@ -1826,8 +1840,9 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UT_SetDeferredRetcode(UT_KEY(OS_ModuleUnload), 1, OS_ERROR); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_ES_APP_CLEANUP_ERR, + CFE_ES_CleanUpApp(Id) == CFE_ES_APP_CLEANUP_ERR, "CFE_ES_CleanUpApp", "Module unload failure"); @@ -1838,8 +1853,9 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_ES_APP_CLEANUP_ERR, + CFE_ES_CleanUpApp(Id) == CFE_ES_APP_CLEANUP_ERR, "CFE_ES_CleanUpApp", "EVS application cleanup failure"); @@ -2015,8 +2031,9 @@ void TestApps(void) OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); /* Associate a child task with the app to be deleted */ ES_UT_SetupChildTaskId(UtAppRecPtr, NULL, NULL); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_SUCCESS, + CFE_ES_CleanUpApp(Id) == CFE_SUCCESS, "CFE_ES_CleanUpApp", "Main task ID matches task ID, nominal"); UT_Report(__FILE__, __LINE__, @@ -2038,8 +2055,9 @@ void TestApps(void) ES_UT_SetupMemPoolId(&UtPoolRecPtr); UtPoolRecPtr->OwnerAppID = CFE_ES_AppRecordGetID(UtAppRecPtr); UtPoolRecPtr->PoolID = CFE_ES_ResourceID_FromInteger(99999); /* Mismatch */ + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_ES_APP_CLEANUP_ERR, + CFE_ES_CleanUpApp(Id) == CFE_ES_APP_CLEANUP_ERR, "CFE_ES_CleanUpApp", "Mem Pool delete error"); UT_Report(__FILE__, __LINE__, @@ -2065,12 +2083,13 @@ void TestApps(void) UtAppRecPtr->MainTaskId = CFE_ES_TaskRecordGetID(UtTaskRecPtr); UT_SetForceFail(UT_KEY(OS_TaskDelete), OS_ERROR); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_ES_APP_CLEANUP_ERR, + CFE_ES_CleanUpApp(Id) == CFE_ES_APP_CLEANUP_ERR, "CFE_ES_CleanUpApp", "Main task ID doesn't match task ID, CFE_ES_APP_CLEANUP_ERR"); UT_Report(__FILE__, __LINE__, - !CFE_ES_TaskRecordIsUsed(UtTaskRecPtr), + CFE_ES_TaskRecordIsUsed(UtTaskRecPtr), "CFE_ES_CleanUpApp", "Main task ID doesn't match task ID, second task unchanged"); @@ -2087,14 +2106,15 @@ void TestApps(void) /* switch the main task association (makes it wrong) */ UtAppRecPtr->MainTaskId = CFE_ES_TaskRecordGetID(UtTaskRecPtr); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_SUCCESS, + CFE_ES_CleanUpApp(Id) == CFE_SUCCESS, "CFE_ES_CleanUpApp", "Application ID mismatch; core application"); UT_Report(__FILE__, __LINE__, - !CFE_ES_TaskRecordIsUsed(UtTaskRecPtr), + CFE_ES_TaskRecordIsUsed(UtTaskRecPtr), "CFE_ES_CleanUpApp", "Application ID mismatch; core application"); @@ -2113,8 +2133,9 @@ void TestApps(void) OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, "UT", "ut-module"); + Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, - CFE_ES_CleanUpApp(UtAppRecPtr) == CFE_SUCCESS && + CFE_ES_CleanUpApp(Id) == CFE_SUCCESS && !CFE_ES_TaskRecordIsUsed(UtTaskRecPtr) && CFE_ES_Global.RegisteredExternalApps == 0, "CFE_ES_CleanUpApp", From 0749d692c0c402ed2f1f22913966225fe6345680 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 16 Oct 2020 12:19:27 -0400 Subject: [PATCH 2/3] Fix #173, refactor app and lib loading procedure Reorganize the global data structures for apps and libraries into components that can be shared between the two concepts. Break up the monolithic AppCreate and LoadLibrary functions and have these call subroutines that operate on the common components. --- fsw/cfe-core/src/es/cfe_es_api.c | 2 +- fsw/cfe-core/src/es/cfe_es_apps.c | 618 ++++++++++++--------- fsw/cfe-core/src/es/cfe_es_apps.h | 108 +++- fsw/cfe-core/src/es/cfe_es_resource.h | 4 +- fsw/cfe-core/src/es/cfe_es_start.c | 170 +++--- fsw/cfe-core/unit-test/es_UT.c | 185 +++--- fsw/cfe-core/unit-test/ut_osprintf_stubs.c | 6 +- 7 files changed, 604 insertions(+), 489 deletions(-) diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index 22cbbe1e5..78b2feb25 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -256,7 +256,7 @@ int32 CFE_ES_ReloadApp(CFE_ES_ResourceID_t AppID, const char *AppFileName) { CFE_ES_SysLogWrite_Unsync("CFE_ES_ReloadApp: Reload Application %s Initiated. New filename = %s\n", CFE_ES_AppRecordGetName(AppRecPtr), AppFileName); - strncpy((char *)AppRecPtr->StartParams.FileName, AppFileName, OS_MAX_PATH_LEN); + strncpy(AppRecPtr->StartParams.BasicInfo.FileName, AppFileName, OS_MAX_PATH_LEN); AppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RELOAD; } else diff --git a/fsw/cfe-core/src/es/cfe_es_apps.c b/fsw/cfe-core/src/es/cfe_es_apps.c index 8cb13dd16..a20402195 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.c +++ b/fsw/cfe-core/src/es/cfe_es_apps.c @@ -343,6 +343,236 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) } +/* +**------------------------------------------------------------------------------------- +** Name: CFE_ES_LoadModule +** +** Helper function to load + configure (but not start) a new app/lib module +** +** Loads the module file via OSAL and stores all relevant info in the table entry as necessary. +** +**------------------------------------------------------------------------------------- +*/ +int32 CFE_ES_LoadModule(const CFE_ES_ModuleLoadParams_t* LoadParams, CFE_ES_ModuleLoadStatus_t *LoadStatus) +{ + osal_id_t ModuleId; + cpuaddr StartAddr; + int32 ReturnCode; + int32 StatusCode; + + StartAddr = 0; + ReturnCode = CFE_SUCCESS; + + if (LoadParams->FileName[0] != 0) + { + /* + ** Load the module via OSAL. + */ + StatusCode = OS_ModuleLoad ( &ModuleId, + LoadParams->Name, + LoadParams->FileName ); + + if (StatusCode != OS_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Could not load file:%s. EC = 0x%08X\n", + LoadParams->FileName, (unsigned int)StatusCode); + ModuleId = OS_OBJECT_ID_UNDEFINED; + ReturnCode = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; + } + } + else + { + ModuleId = OS_OBJECT_ID_UNDEFINED; + } + + /* + ** If the Load was OK, then lookup the address of the entry point + */ + if (ReturnCode == CFE_SUCCESS && LoadParams->EntryPoint[0] != 0) + { + StatusCode = OS_SymbolLookup(&StartAddr, LoadParams->EntryPoint); + if (StatusCode != OS_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Could not find symbol:%s. EC = 0x%08X\n", + LoadParams->EntryPoint, (unsigned int)StatusCode); + ReturnCode = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; + } + } + + if ( ReturnCode == CFE_SUCCESS ) + { + /* store the data in the app record after successful load+lookup */ + LoadStatus->ModuleId = ModuleId; + LoadStatus->EntryAddress = StartAddr; + } + else if (OS_ObjectIdDefined(ModuleId)) + { + /* If the module had been successfully loaded, then unload it, + * so that it does not consume resources */ + StatusCode = OS_ModuleUnload(ModuleId); + if ( StatusCode != OS_SUCCESS ) /* There's not much we can do except notify */ + { + CFE_ES_WriteToSysLog("ES Startup: Failed to unload: %s. EC = 0x%08X\n", + LoadParams->Name, (unsigned int)StatusCode); + } + } + + return ReturnCode; +} + +/* +**------------------------------------------------------------------------------------- +** Name: CFE_ES_GetAppEntryPoint +** +** Helper function to act as the intermediate entry point of an app +** This is to support starting apps before having a fully completed entry in the +** global app table. The app startup will delay until the app creation is completed +** and verified, then the actual entry point will be determined. +** +**------------------------------------------------------------------------------------- +*/ +int32 CFE_ES_GetAppEntryPoint(osal_task_entry *FuncPtr) +{ + CFE_ES_AppRecord_t *AppRecPtr; + int32 ReturnCode; + int32 Timeout; + + /* + * Use the same timeout as was used for the startup script itself. + */ + ReturnCode = CFE_ES_ERR_APP_REGISTER; + Timeout = CFE_PLATFORM_ES_STARTUP_SCRIPT_TIMEOUT_MSEC; + + while(true) + { + OS_TaskDelay(CFE_PLATFORM_ES_STARTUP_SYNC_POLL_MSEC); + + CFE_ES_LockSharedData(__func__,__LINE__); + AppRecPtr = CFE_ES_GetAppRecordByContext(); + if (AppRecPtr != NULL) + { + AppRecPtr->AppState = CFE_ES_AppState_EARLY_INIT; + *FuncPtr = (osal_task_entry)AppRecPtr->ModuleInfo.EntryAddress; + ReturnCode = CFE_SUCCESS; + } + CFE_ES_UnlockSharedData(__func__,__LINE__); + + if (ReturnCode == CFE_SUCCESS || Timeout <= 0) + { + /* end of loop condition */ + break; + } + + Timeout -= CFE_PLATFORM_ES_STARTUP_SYNC_POLL_MSEC; + } + + return (ReturnCode); +} + +/* +**------------------------------------------------------------------------------------- +** Name: CFE_ES_AppEntryPoint +** +** Helper function to act as the intermediate entry point of an app +** This is to support starting apps before having a fully completed entry in the +** global app table. The app startup will delay until the app creation is completed +** and verified, then the actual entry point will be determined. +** +**------------------------------------------------------------------------------------- +*/ +void CFE_ES_AppEntryPoint(void) +{ + osal_task_entry RealEntryFunc; + + if (CFE_ES_GetAppEntryPoint(&RealEntryFunc) == CFE_SUCCESS && + RealEntryFunc != NULL) + { + (*RealEntryFunc)(); + } +} + +/* +**------------------------------------------------------------------------------------- +** Name: CFE_ES_StartMainTask +** +** Helper function to start (but not load) a new app/lib module +** +** Note that OSAL does not separate the action of creating and start a task, providing +** only OS_TaskCreate which does both. But there is a potential race condition if +** the real task code starts and calls e.g. CFE_ES_RegisterApp() or any other function +** that depends on having an AppID context, before its fully registered in the global app table. +** +** Therefore this calls a dedicated CFE_ES_AppEntryPoint which then will wait until +** the task is fully registered in the global, before calling the actual app entry point. +** +**------------------------------------------------------------------------------------- +*/ +int32 CFE_ES_StartAppTask(const CFE_ES_AppStartParams_t* StartParams, CFE_ES_ResourceID_t RefAppId, CFE_ES_ResourceID_t *TaskIdPtr) +{ + CFE_ES_TaskRecord_t *TaskRecPtr; + osal_id_t OsalTaskId; + CFE_ES_ResourceID_t TaskId; + int32 StatusCode; + int32 ReturnCode; + + /* + ** Create the primary task for the newly loaded task + */ + StatusCode = OS_TaskCreate(&OsalTaskId, /* task id */ + StartParams->BasicInfo.Name, /* task name */ + CFE_ES_AppEntryPoint, /* task function pointer */ + NULL, /* stack pointer (allocate) */ + StartParams->StackSize, /* stack size */ + StartParams->Priority, /* task priority */ + OS_FP_ENABLED); /* task options */ + + CFE_ES_LockSharedData(__func__,__LINE__); + + if ( StatusCode == OS_SUCCESS ) + { + /* + * As this is a newly-created task, this shouldn't fail. + * The entry is not (yet) matching the task ID - it will be + * initialized here. + */ + TaskId = CFE_ES_ResourceID_FromOSAL(OsalTaskId); + TaskRecPtr = CFE_ES_LocateTaskRecordByID(TaskId); + if ( CFE_ES_TaskRecordIsUsed(TaskRecPtr) ) + { + CFE_ES_SysLogWrite_Unsync("ES Startup: Error: ES_TaskTable slot for ID %lx in use at task creation!\n", + OS_ObjectIdToInteger(OsalTaskId)); + } + + /* + * Clear any other/stale data that might be in the entry, + * and reset all fields to the correct value. + */ + memset(TaskRecPtr, 0, sizeof(*TaskRecPtr)); + + TaskRecPtr->AppId = RefAppId; + strncpy(TaskRecPtr->TaskName, StartParams->BasicInfo.Name, sizeof(TaskRecPtr->TaskName)-1); + CFE_ES_TaskRecordSetUsed(TaskRecPtr, TaskId); + + /* + ** Increment the registered Task count. + */ + CFE_ES_Global.RegisteredTasks++; + ReturnCode = CFE_SUCCESS; + *TaskIdPtr = TaskId; + } + else + { + CFE_ES_SysLogWrite_Unsync("ES Startup: AppCreate Error: TaskCreate %s Failed. EC = 0x%08X!\n", + StartParams->BasicInfo.Name,(unsigned int)StatusCode); + ReturnCode = CFE_STATUS_EXTERNAL_RESOURCE_FAIL; + *TaskIdPtr = CFE_ES_RESOURCEID_UNDEFINED; + } + + CFE_ES_UnlockSharedData(__func__,__LINE__); + + return ReturnCode; +} + /* **--------------------------------------------------------------------------------------- ** Name: ES_AppCreate @@ -356,19 +586,15 @@ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens) */ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, const char *FileName, - const void *EntryPointData, + const char *EntryPointName, const char *AppName, uint32 Priority, uint32 StackSize, uint32 ExceptionAction) { - cpuaddr StartAddr; - int32 ReturnCode; CFE_Status_t Status; - osal_id_t ModuleId; - osal_id_t MainTaskId; + CFE_ES_ResourceID_t MainTaskId; CFE_ES_AppRecord_t *AppRecPtr; - CFE_ES_TaskRecord_t *TaskRecPtr; CFE_ES_ResourceID_t PendingAppId; /* @@ -428,6 +654,31 @@ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, { /* Fully clear the entry, just in case of stale data */ memset(AppRecPtr, 0, sizeof(*AppRecPtr)); + + /* + * Fill out the parameters in the StartParams sub-structure + */ + AppRecPtr->Type = CFE_ES_AppType_EXTERNAL; + strncpy(AppRecPtr->StartParams.BasicInfo.Name, AppName, + sizeof(AppRecPtr->StartParams.BasicInfo.Name)-1); + strncpy(AppRecPtr->StartParams.BasicInfo.FileName, FileName, + sizeof(AppRecPtr->StartParams.BasicInfo.FileName)-1); + if (EntryPointName != NULL && strcmp(EntryPointName, "NULL") != 0) + { + strncpy(AppRecPtr->StartParams.BasicInfo.EntryPoint, EntryPointName, + sizeof(AppRecPtr->StartParams.BasicInfo.EntryPoint)-1); + } + + AppRecPtr->StartParams.StackSize = StackSize; + AppRecPtr->StartParams.ExceptionAction = ExceptionAction; + AppRecPtr->StartParams.Priority = Priority; + + /* + * Fill out the Task State info + */ + AppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_RUN; + AppRecPtr->ControlReq.AppTimerMsec = 0; + CFE_ES_AppRecordSetUsed(AppRecPtr, CFE_ES_RESOURCEID_RESERVED); CFE_ES_Global.LastAppId = PendingAppId; Status = CFE_SUCCESS; @@ -437,142 +688,63 @@ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, CFE_ES_UnlockSharedData(__func__,__LINE__); /* - ** If a slot was found, create the application - */ - if (Status == CFE_SUCCESS) + * If ID allocation was not successful, return now. + * A message regarding the issue should have already been logged + */ + if (Status != CFE_SUCCESS) { - /* - ** Load the module - */ - ReturnCode = OS_ModuleLoad ( &ModuleId, AppName, FileName ); - - /* - ** If the Load was OK, then lookup the address of the entry point - */ - if ( ReturnCode == OS_SUCCESS ) - { - ReturnCode = OS_SymbolLookup( &StartAddr, (const char*)EntryPointData ); - if ( ReturnCode != OS_SUCCESS ) - { - CFE_ES_WriteToSysLog("ES Startup: Could not find symbol:%s. EC = 0x%08X\n", - (const char*)EntryPointData, (unsigned int)ReturnCode); - - CFE_ES_LockSharedData(__func__,__LINE__); - CFE_ES_AppRecordSetFree(AppRecPtr); /* Release slot */ - CFE_ES_UnlockSharedData(__func__,__LINE__); - - /* Unload the module from memory, so that it does not consume resources */ - ReturnCode = OS_ModuleUnload(ModuleId); - if ( ReturnCode != OS_SUCCESS ) /* There's not much we can do except notify */ - { - CFE_ES_WriteToSysLog("ES Startup: Failed to unload APP: %s. EC = 0x%08X\n", - AppName, (unsigned int)ReturnCode); - } - - return(CFE_ES_ERR_APP_CREATE); - } - } - else /* load not successful */ - { - CFE_ES_WriteToSysLog("ES Startup: Could not load cFE application file:%s. EC = 0x%08X\n", - FileName, (unsigned int)ReturnCode); - - CFE_ES_LockSharedData(__func__,__LINE__); - CFE_ES_AppRecordSetFree(AppRecPtr); /* Release slot */ - CFE_ES_UnlockSharedData(__func__,__LINE__); - - return(CFE_ES_ERR_APP_CREATE); - } - - /* - ** If the EntryPoint symbol was found, then start creating the App - */ - CFE_ES_LockSharedData(__func__,__LINE__); - /* - ** Allocate and populate the ES_AppTable entry - */ - AppRecPtr->Type = CFE_ES_AppType_EXTERNAL; - - /* - ** Fill out the parameters in the AppStartParams sub-structure - */ - strncpy((char *)AppRecPtr->StartParams.Name, AppName, OS_MAX_API_NAME); - AppRecPtr->StartParams.Name[OS_MAX_API_NAME - 1] = '\0'; - - strncpy((char *)AppRecPtr->StartParams.EntryPoint, (const char *)EntryPointData, OS_MAX_API_NAME); - AppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; - strncpy((char *)AppRecPtr->StartParams.FileName, FileName, OS_MAX_PATH_LEN); - AppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - - AppRecPtr->StartParams.StackSize = StackSize; - - AppRecPtr->StartParams.StartAddress = StartAddr; - AppRecPtr->StartParams.ModuleId = ModuleId; - - AppRecPtr->StartParams.ExceptionAction = ExceptionAction; - AppRecPtr->StartParams.Priority = Priority; - - /* - ** Fill out the Task State info - */ - AppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_RUN; - AppRecPtr->ControlReq.AppTimerMsec = 0; - - /* - ** Create the primary task for the newly loaded task - */ - ReturnCode = OS_TaskCreate(&MainTaskId, /* task id */ - AppName, /* task name */ - (osal_task_entry)StartAddr, /* task function pointer */ - NULL, /* stack pointer */ - StackSize, /* stack size */ - Priority, /* task priority */ - OS_FP_ENABLED); /* task options */ - + return Status; + } - if(ReturnCode != OS_SUCCESS) - { - CFE_ES_SysLogWrite_Unsync("ES Startup: AppCreate Error: TaskCreate %s Failed. EC = 0x%08X!\n", - AppName,(unsigned int)ReturnCode); + /* + * Load the module based on StartParams configured above. + */ + Status = CFE_ES_LoadModule(&AppRecPtr->StartParams.BasicInfo, &AppRecPtr->ModuleInfo); - CFE_ES_AppRecordSetFree(AppRecPtr); /* Release slot */ - CFE_ES_UnlockSharedData(__func__,__LINE__); + /* + * If the Load was OK, then complete the initialization + */ + if (Status == CFE_SUCCESS) + { + Status = CFE_ES_StartAppTask(&AppRecPtr->StartParams, PendingAppId, &MainTaskId); + } + else + { + MainTaskId = CFE_ES_RESOURCEID_UNDEFINED; + } - Status = CFE_ES_ERR_APP_CREATE; - } - else - { + /* + * Finalize data in the app table entry, which must be done under lock. + * This transitions the entry from being RESERVED to the real ID. + */ + CFE_ES_LockSharedData(__func__,__LINE__); - /* - ** Record the ES_TaskTable entry - */ - AppRecPtr->MainTaskId = CFE_ES_ResourceID_FromOSAL(MainTaskId); - TaskRecPtr = CFE_ES_LocateTaskRecordByID(AppRecPtr->MainTaskId); + if ( Status == CFE_SUCCESS ) + { + /* + * important - set the ID to its proper value + * which turns this into a real/valid table entry + */ + AppRecPtr->MainTaskId = MainTaskId; + CFE_ES_AppRecordSetUsed(AppRecPtr, PendingAppId); - if ( CFE_ES_TaskRecordIsUsed(TaskRecPtr) ) - { - CFE_ES_SysLogWrite_Unsync("ES Startup: Error: ES_TaskTable slot in use at task creation!\n"); - } - CFE_ES_TaskRecordSetUsed(TaskRecPtr,AppRecPtr->MainTaskId); - TaskRecPtr->AppId = PendingAppId; - /* The main task name is the same as the app name */ - strncpy(TaskRecPtr->TaskName, AppName, - sizeof(TaskRecPtr->TaskName)-1); - TaskRecPtr->TaskName[sizeof(TaskRecPtr->TaskName)-1]='\0'; - CFE_ES_AppRecordSetUsed(AppRecPtr, PendingAppId); - CFE_ES_SysLogWrite_Unsync("ES Startup: %s loaded and created\n", AppName); - *ApplicationIdPtr = PendingAppId; - - /* - ** Increment the registered App and Registered External Task variables. - */ - CFE_ES_Global.RegisteredTasks++; - CFE_ES_Global.RegisteredExternalApps++; + /* + ** Increment the registered App counter. + */ + CFE_ES_Global.RegisteredExternalApps++; + } + else + { + /* + * Set the table entry back to free + */ + CFE_ES_AppRecordSetFree(AppRecPtr); + PendingAppId = CFE_ES_RESOURCEID_UNDEFINED; + } - CFE_ES_UnlockSharedData(__func__,__LINE__); + CFE_ES_UnlockSharedData(__func__,__LINE__); - } /* End If OS_TaskCreate */ - } + *ApplicationIdPtr = PendingAppId; return Status; @@ -587,15 +759,13 @@ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, */ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, const char *FileName, - const void *EntryPointData, + const char *EntryPointName, const char *LibName) { CFE_ES_LibraryEntryFuncPtr_t FunctionPointer; CFE_ES_LibRecord_t * LibSlotPtr; int32 Status; CFE_ES_ResourceID_t PendingLibId; - osal_id_t ModuleId; - bool IsModuleLoaded; /* * The FileName must not be NULL @@ -613,11 +783,8 @@ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, /* ** Allocate an ES_LibTable entry */ - IsModuleLoaded = false; FunctionPointer = NULL; - ModuleId = OS_OBJECT_ID_UNDEFINED; PendingLibId = CFE_ES_RESOURCEID_UNDEFINED; - Status = CFE_ES_ERR_LOAD_LIB; /* error that will be returned if no slots found */ /* ** Find an ES AppTable entry, and set to RESERVED @@ -663,7 +830,20 @@ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, { /* Fully clear the entry, just in case of stale data */ memset(LibSlotPtr, 0, sizeof(*LibSlotPtr)); - strcpy(LibSlotPtr->LibName, LibName); /* Size already checked */ + + /* + * Fill out the parameters in the AppStartParams sub-structure + */ + strncpy(LibSlotPtr->BasicInfo.Name, LibName, + sizeof(LibSlotPtr->BasicInfo.Name)-1); + strncpy(LibSlotPtr->BasicInfo.FileName, FileName, + sizeof(LibSlotPtr->BasicInfo.FileName)-1); + if (EntryPointName != NULL && strcmp(EntryPointName, "NULL") != 0) + { + strncpy(LibSlotPtr->BasicInfo.EntryPoint, EntryPointName, + sizeof(LibSlotPtr->BasicInfo.EntryPoint)-1); + } + CFE_ES_LibRecordSetUsed(LibSlotPtr, CFE_ES_RESOURCEID_RESERVED); CFE_ES_Global.LastLibId = PendingLibId; Status = CFE_SUCCESS; @@ -683,128 +863,51 @@ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, } /* - * ------------------- - * IMPORTANT: - * - * there is now a reserved entry in the global library table, - * which must be freed if something goes wrong hereafter. - * - * Avoid any inline "return" statements - all paths must proceed to - * the end of this function where the cleanup will be done. - * - * Record sufficient breadcrumbs along the way, such that proper - * cleanup can be done in case it is necessary. - * ------------------- - */ - - /* - * STAGE 2: - * Do the OS_ModuleLoad() if is called for (i.e. ModuleLoadFile is NOT null) + * Load the module based on StartParams configured above. */ - if (Status == CFE_SUCCESS && FileName != NULL) + Status = CFE_ES_LoadModule(&LibSlotPtr->BasicInfo, &LibSlotPtr->ModuleInfo); + if (Status == CFE_SUCCESS) { - Status = OS_ModuleLoad( &ModuleId, LibName, FileName ); - if (Status == OS_SUCCESS) - { - Status = CFE_SUCCESS; /* just in case CFE_SUCCESS is different than OS_SUCCESS */ - IsModuleLoaded = true; - } - else - { - /* load not successful. Note OS errors are better displayed as decimal integers. */ - CFE_ES_WriteToSysLog("ES Startup: Could not load cFE Shared Library: %d\n", (int)Status); - Status = CFE_ES_ERR_LOAD_LIB; /* convert OS error to CFE error code */ - } + FunctionPointer = (CFE_ES_LibraryEntryFuncPtr_t)LibSlotPtr->ModuleInfo.EntryAddress; + if (FunctionPointer != NULL) + { + Status = (*FunctionPointer)(PendingLibId); + if (Status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("ES Startup: Load Shared Library Init Error = 0x%08x\n", + (unsigned int)Status); + } + } } /* - * STAGE 3: - * Figure out the Entry point / Initialization function. - * - * This depends on whether it is a dynamically loaded or a statically linked library, - * or it could be omitted altogether for libraries which do not require an init function. - * - * For dynamically loaded objects where FileName is non-NULL, the - * "EntryPointData" is a normal C string (const char *) with the name of the function. - * - * If the name of the function is the string "NULL" -- then treat this as no function - * needed and skip the lookup entirely (this is to support startup scripts where some - * string must be in the entry point field). + * Finalize data in the app table entry, which must be done under lock. + * This transitions the entry from being RESERVED to the real type, + * either MAIN_TASK (success) or returning to INVALID (failure). */ - if (Status == CFE_SUCCESS && EntryPointData != NULL) - { - if (strcmp(EntryPointData, "NULL") != 0) - { - /* - * If the entry point is explicitly set as NULL, - * this means the library has no init function - skip the lookup. - * Otherwise lookup the address of the entry point - */ - cpuaddr StartAddr; - - Status = OS_SymbolLookup( &StartAddr, EntryPointData ); - if (Status == OS_SUCCESS) - { - Status = CFE_SUCCESS; /* just in case CFE_SUCCESS is different than OS_SUCCESS */ - FunctionPointer = (CFE_ES_LibraryEntryFuncPtr_t)StartAddr; - } - else - { - /* could not find symbol. Note OS errors are better displayed as decimal integers */ - CFE_ES_WriteToSysLog("ES Startup: Could not find Library Init symbol:%s. EC = %d\n", - (const char *)EntryPointData, (int)Status); - Status = CFE_ES_ERR_LOAD_LIB; /* convert OS error to CFE error code */ - } - } - } + CFE_ES_LockSharedData(__func__,__LINE__); - /* - * STAGE 4: - * Call the Initialization function, if one was identified during the previous stage - */ - if (Status == CFE_SUCCESS && FunctionPointer != NULL) + if ( Status == CFE_SUCCESS ) { - /* - ** Call the library initialization routine + /* + * important - set the ID to its proper value + * which turns this into a real/valid table entry */ - Status = (*FunctionPointer)(*LibraryIdPtr); - if (Status != CFE_SUCCESS) - { - CFE_ES_WriteToSysLog("ES Startup: Load Shared Library Init Error = 0x%08x\n", (unsigned int)Status); - } - } + CFE_ES_LibRecordSetUsed(LibSlotPtr, PendingLibId); - /* - * LAST STAGE: - * Do final clean-up - * - * If fully successful, then increment the "RegisteredLibs" counter. - * Otherwise in case of an error, do clean up based on the breadcrumbs - */ - if(Status == CFE_SUCCESS) - { - /* Increment the counter, which needs to be done under lock */ - CFE_ES_LockSharedData(__func__,__LINE__); - CFE_ES_LibRecordSetUsed(LibSlotPtr, PendingLibId); - CFE_ES_Global.RegisteredLibs++; - CFE_ES_UnlockSharedData(__func__,__LINE__); + /* + * Increment the registered Lib counter. + */ + CFE_ES_Global.RegisteredLibs++; } else { - /* - * If the above code had loaded a module, then unload it - */ - if (IsModuleLoaded) - { - OS_ModuleUnload( ModuleId ); - } - - /* Release Slot - No need to lock as it is resetting just a single value */ - CFE_ES_LibRecordSetFree(LibSlotPtr); - - PendingLibId = CFE_ES_RESOURCEID_UNDEFINED; + CFE_ES_LibRecordSetFree(LibSlotPtr); + PendingLibId = CFE_ES_RESOURCEID_UNDEFINED; } + CFE_ES_UnlockSharedData(__func__,__LINE__); + *LibraryIdPtr = PendingLibId; return(Status); @@ -1014,9 +1117,9 @@ void CFE_ES_ProcessControlRequest(CFE_ES_ResourceID_t AppId) PendingControlReq == CFE_ES_RunStatus_SYS_RELOAD ) { StartupStatus = CFE_ES_AppCreate(&NewAppId, - OrigStartParams.FileName, - OrigStartParams.EntryPoint, - OrigStartParams.Name, + OrigStartParams.BasicInfo.FileName, + OrigStartParams.BasicInfo.EntryPoint, + OrigStartParams.BasicInfo.Name, OrigStartParams.Priority, OrigStartParams.StackSize, OrigStartParams.ExceptionAction); @@ -1167,7 +1270,7 @@ void CFE_ES_ProcessControlRequest(CFE_ES_ResourceID_t AppId) } CFE_EVS_SendEvent(EventID, EventType, "%s Application %s %s", - ReqName, OrigStartParams.Name, MessageDetail); + ReqName, OrigStartParams.BasicInfo.Name, MessageDetail); } } /* End Function */ @@ -1218,7 +1321,7 @@ int32 CFE_ES_CleanUpApp(CFE_ES_ResourceID_t AppId) * * (this will be OS_OBJECT_ID_UNDEFINED if it was not loaded dynamically) */ - ModuleId = AppRecPtr->StartParams.ModuleId; + ModuleId = AppRecPtr->ModuleInfo.ModuleId; } /* @@ -1645,18 +1748,17 @@ int32 CFE_ES_GetAppInfoInternal(CFE_ES_AppRecord_t *AppRecPtr, CFE_ES_AppInfo_t sizeof(AppInfoPtr->Name)-1); AppInfoPtr->Name[sizeof(AppInfoPtr->Name)-1] = '\0'; - strncpy((char *)AppInfoPtr->EntryPoint, - AppRecPtr->StartParams.EntryPoint, + strncpy(AppInfoPtr->EntryPoint, AppRecPtr->StartParams.BasicInfo.EntryPoint, sizeof(AppInfoPtr->EntryPoint) - 1); AppInfoPtr->EntryPoint[sizeof(AppInfoPtr->EntryPoint) - 1] = '\0'; - strncpy((char *)AppInfoPtr->FileName, (char *)AppRecPtr->StartParams.FileName, + strncpy(AppInfoPtr->FileName, AppRecPtr->StartParams.BasicInfo.FileName, sizeof(AppInfoPtr->FileName) - 1); AppInfoPtr->FileName[sizeof(AppInfoPtr->FileName) - 1] = '\0'; - AppInfoPtr->ModuleId = AppRecPtr->StartParams.ModuleId; + AppInfoPtr->ModuleId = AppRecPtr->ModuleInfo.ModuleId; AppInfoPtr->StackSize = AppRecPtr->StartParams.StackSize; - CFE_SB_SET_MEMADDR(AppInfoPtr->StartAddress, AppRecPtr->StartParams.StartAddress); + CFE_SB_SET_MEMADDR(AppInfoPtr->StartAddress, AppRecPtr->ModuleInfo.EntryAddress); AppInfoPtr->ExceptionAction = AppRecPtr->StartParams.ExceptionAction; AppInfoPtr->Priority = AppRecPtr->StartParams.Priority; diff --git a/fsw/cfe-core/src/es/cfe_es_apps.h b/fsw/cfe-core/src/es/cfe_es_apps.h index 4cf2c11bc..2c7540e50 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.h +++ b/fsw/cfe-core/src/es/cfe_es_apps.h @@ -65,21 +65,61 @@ typedef struct /* -** CFE_ES_AppStartParams_t is a structure of information used when an application is -** created in the system. It is stored in the cFE ES App Table +** CFE_ES_ModuleLoadParams_t contains the information used when a module +** (library or app) load request initially processed in the system. It captures +** the fundamental information - the name, the file to load, its entry point. +** It contains information directly provided by the user, not runtime status or +** other derived information. +** +** This information should remain fairly constant after initial allocation, even +** if the application is restarted for some reason. The major exception is the +** ReloadApp command, which can change the FileName. */ typedef struct { - char Name[OS_MAX_API_NAME]; - char EntryPoint[OS_MAX_API_NAME]; - char FileName[OS_MAX_PATH_LEN]; + char Name[OS_MAX_API_NAME]; + char EntryPoint[OS_MAX_API_NAME]; + char FileName[OS_MAX_PATH_LEN]; - uint32 StackSize; - cpuaddr StartAddress; - osal_id_t ModuleId; +} CFE_ES_ModuleLoadParams_t; + +/* +** CFE_ES_ModuleLoadStatus_t is a structure of information used when a module +** (library or app) is actually loaded in the system. It captures the +** runtime information - the module ID and starting address. +** +** This information may change if the module is reloaded. +*/ +typedef struct +{ + cpuaddr EntryAddress; + osal_id_t ModuleId; - uint16 ExceptionAction; - uint16 Priority; +} CFE_ES_ModuleLoadStatus_t; + + + +/* +** CFE_ES_AppStartParams_t is a structure of information used when an application is +** created in the system. +** +** This is an extension of the CFE_ES_ModuleLoadParams_t which adds information +** about the task stack size and priority. It is only used for apps, as libraries +** do not have a task associated. +*/ +typedef struct +{ + /* + * Basic (static) information about the module + */ + CFE_ES_ModuleLoadParams_t BasicInfo; + + /* + * Extra information the pertains to applications only, not libraries. + */ + cpusize StackSize; + uint16 Priority; + CFE_ES_ExceptionAction_Enum_t ExceptionAction; } CFE_ES_AppStartParams_t; @@ -89,12 +129,13 @@ typedef struct */ typedef struct { - CFE_ES_ResourceID_t AppId; /* The actual AppID of this entry, or undefined */ - CFE_ES_AppState_Enum_t AppState; /* Is the app running, or stopped, or waiting? */ - uint32 Type; /* The type of App: CORE or EXTERNAL */ - CFE_ES_AppStartParams_t StartParams; /* The start parameters for an App */ - CFE_ES_ControlReq_t ControlReq; /* The Control Request Record for External cFE Apps */ - CFE_ES_ResourceID_t MainTaskId; /* The Application's Main Task ID */ + CFE_ES_ResourceID_t AppId; /* The actual AppID of this entry, or undefined */ + CFE_ES_AppState_Enum_t AppState; /* Is the app running, or stopped, or waiting? */ + CFE_ES_AppType_Enum_t Type; /* The type of App: CORE or EXTERNAL */ + CFE_ES_AppStartParams_t StartParams; /* The start parameters for an App */ + CFE_ES_ModuleLoadStatus_t ModuleInfo; /* Runtime module information */ + CFE_ES_ControlReq_t ControlReq; /* The Control Request Record for External cFE Apps */ + CFE_ES_ResourceID_t MainTaskId; /* The Application's Main Task ID */ } CFE_ES_AppRecord_t; @@ -119,8 +160,9 @@ typedef struct */ typedef struct { - CFE_ES_ResourceID_t LibId; /* The actual LibID of this entry, or undefined */ - char LibName[OS_MAX_API_NAME]; /* Library Name */ + CFE_ES_ResourceID_t LibId; /* The actual LibID of this entry, or undefined */ + CFE_ES_ModuleLoadParams_t BasicInfo; /* Basic (static) information about the module */ + CFE_ES_ModuleLoadStatus_t ModuleInfo; /* Runtime information about the module */ } CFE_ES_LibRecord_t; /* @@ -151,13 +193,39 @@ void CFE_ES_StartApplications(uint32 ResetType, const char *StartFilePath ); */ int32 CFE_ES_ParseFileEntry(const char **TokenList, uint32 NumTokens); +/* +** Internal function to load a module (app or library) +** This only loads the code and looks up relevent runtime information. +** It does not start any tasks. +*/ +int32 CFE_ES_LoadModule(const CFE_ES_ModuleLoadParams_t* LoadParams, CFE_ES_ModuleLoadStatus_t *LoadStatus); + +/* +** Internal function to determine the entry point of an app. +** If the app isn't fully registered in the global app table, +** then this delays until the app is completely configured and the entry point is +** confirmed to be valid. +*/ +int32 CFE_ES_GetAppEntryPoint(osal_task_entry *FuncPtr); + +/* +** Intermediate entry point of an app. Determines the actual +** entry point from the global data structures. +*/ +void CFE_ES_AppEntryPoint(void); + +/* +** Internal function to start the main task of an app. +*/ +int32 CFE_ES_StartAppTask(const CFE_ES_AppStartParams_t* StartParams, CFE_ES_ResourceID_t RefAppId, CFE_ES_ResourceID_t *TaskIdPtr); + /* ** Internal function to create/start a new cFE app ** based on the parameters passed in */ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, const char *FileName, - const void *EntryPointData, + const char *EntryPointName, const char *AppName, uint32 Priority, uint32 StackSize, @@ -167,7 +235,7 @@ int32 CFE_ES_AppCreate(CFE_ES_ResourceID_t *ApplicationIdPtr, */ int32 CFE_ES_LoadLibrary(CFE_ES_ResourceID_t *LibraryIdPtr, const char *FileName, - const void *EntryPointData, + const char *EntryPointName, const char *LibName); /* diff --git a/fsw/cfe-core/src/es/cfe_es_resource.h b/fsw/cfe-core/src/es/cfe_es_resource.h index 9ca10533f..82c936cd3 100644 --- a/fsw/cfe-core/src/es/cfe_es_resource.h +++ b/fsw/cfe-core/src/es/cfe_es_resource.h @@ -214,7 +214,7 @@ static inline bool CFE_ES_AppRecordIsMatch(const CFE_ES_AppRecord_t *AppRecPtr, */ static inline const char* CFE_ES_AppRecordGetName(const CFE_ES_AppRecord_t *AppRecPtr) { - return AppRecPtr->StartParams.Name; + return AppRecPtr->StartParams.BasicInfo.Name; } @@ -307,7 +307,7 @@ static inline bool CFE_ES_LibRecordIsMatch(const CFE_ES_LibRecord_t *LibRecPtr, */ static inline const char* CFE_ES_LibRecordGetName(const CFE_ES_LibRecord_t *LibRecPtr) { - return LibRecPtr->LibName; + return LibRecPtr->BasicInfo.Name; } diff --git a/fsw/cfe-core/src/es/cfe_es_start.c b/fsw/cfe-core/src/es/cfe_es_start.c index 9f8c8eb66..2a883ef13 100644 --- a/fsw/cfe-core/src/es/cfe_es_start.c +++ b/fsw/cfe-core/src/es/cfe_es_start.c @@ -753,10 +753,9 @@ void CFE_ES_CreateObjects(void) { int32 ReturnCode; uint16 i; - osal_id_t OsalId; CFE_ES_AppRecord_t *AppRecPtr; - CFE_ES_TaskRecord_t *TaskRecPtr; CFE_ES_ResourceID_t PendingAppId; + CFE_ES_ResourceID_t PendingTaskId; CFE_ES_WriteToSysLog("ES Startup: Starting Object Creation calls.\n"); @@ -776,7 +775,27 @@ void CFE_ES_CreateObjects(void) AppRecPtr = CFE_ES_LocateAppRecordByID(PendingAppId); if (AppRecPtr != NULL) { + /* + ** Fill out the parameters in the AppStartParams sub-structure + */ + AppRecPtr->Type = CFE_ES_AppType_CORE; + strncpy(AppRecPtr->StartParams.BasicInfo.Name, CFE_ES_ObjectTable[i].ObjectName, + sizeof(AppRecPtr->StartParams.BasicInfo.Name)-1); + + /* FileName and EntryPoint is not valid for core apps */ + AppRecPtr->StartParams.StackSize = CFE_ES_ObjectTable[i].ObjectSize; + AppRecPtr->StartParams.ExceptionAction = CFE_ES_ExceptionAction_PROC_RESTART; + AppRecPtr->StartParams.Priority = CFE_ES_ObjectTable[i].ObjectPriority; + AppRecPtr->ModuleInfo.EntryAddress = (cpuaddr)CFE_ES_ObjectTable[i].FuncPtrUnion.VoidPtr; + + /* + ** Fill out the Task State info + */ + AppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_RUN; + AppRecPtr->ControlReq.AppTimerMsec = 0; + CFE_ES_AppRecordSetUsed(AppRecPtr, CFE_ES_RESOURCEID_RESERVED); + CFE_ES_Global.LastAppId = PendingAppId; } CFE_ES_UnlockSharedData(__func__,__LINE__); @@ -786,111 +805,60 @@ void CFE_ES_CreateObjects(void) */ if (AppRecPtr != NULL) { - - CFE_ES_LockSharedData(__func__,__LINE__); - - AppRecPtr->Type = CFE_ES_AppType_CORE; - - /* - ** Fill out the parameters in the AppStartParams sub-structure - */ - strncpy((char *)AppRecPtr->StartParams.Name, (char *)CFE_ES_ObjectTable[i].ObjectName, OS_MAX_API_NAME); - AppRecPtr->StartParams.Name[OS_MAX_API_NAME - 1] = '\0'; - /* EntryPoint field is not valid here for base apps */ - /* FileName is not valid for base apps, either */ - AppRecPtr->StartParams.StackSize = CFE_ES_ObjectTable[i].ObjectSize; - AppRecPtr->StartParams.StartAddress = (cpuaddr)CFE_ES_ObjectTable[i].FuncPtrUnion.VoidPtr; - AppRecPtr->StartParams.ExceptionAction = CFE_ES_ExceptionAction_PROC_RESTART; - AppRecPtr->StartParams.Priority = CFE_ES_ObjectTable[i].ObjectPriority; - - - /* - ** Create the task - */ - ReturnCode = OS_TaskCreate(&OsalId, /* task id */ - CFE_ES_ObjectTable[i].ObjectName, /* task name */ - CFE_ES_ObjectTable[i].FuncPtrUnion.MainAppPtr, /* task function pointer */ - NULL, /* stack pointer */ - CFE_ES_ObjectTable[i].ObjectSize, /* stack size */ - CFE_ES_ObjectTable[i].ObjectPriority, /* task priority */ - OS_FP_ENABLED); /* task options */ - - if(ReturnCode != OS_SUCCESS) - { - CFE_ES_AppRecordSetFree(AppRecPtr); - CFE_ES_UnlockSharedData(__func__,__LINE__); - - CFE_ES_WriteToSysLog("ES Startup: OS_TaskCreate error creating core App: %s: EC = 0x%08X\n", - CFE_ES_ObjectTable[i].ObjectName, (unsigned int)ReturnCode); - - /* - ** Delay to allow the message to be read - */ - OS_TaskDelay(CFE_ES_PANIC_DELAY); - - /* - ** cFE Cannot continue to start up. - */ - CFE_PSP_Panic(CFE_PSP_PANIC_CORE_APP); - - } - else - { - AppRecPtr->MainTaskId = CFE_ES_ResourceID_FromOSAL(OsalId); - TaskRecPtr = CFE_ES_LocateTaskRecordByID(AppRecPtr->MainTaskId); - - /* - ** Allocate and populate the CFE_ES_Global.TaskTable entry - */ - if ( CFE_ES_TaskRecordIsUsed(TaskRecPtr) ) - { - CFE_ES_SysLogWrite_Unsync("ES Startup: CFE_ES_Global.TaskTable record used error for App: %s, continuing.\n", - CFE_ES_ObjectTable[i].ObjectName); - } - CFE_ES_TaskRecordSetUsed(TaskRecPtr, AppRecPtr->MainTaskId); - TaskRecPtr->AppId = PendingAppId; - strncpy(TaskRecPtr->TaskName, CFE_ES_ObjectTable[i].ObjectName, sizeof(TaskRecPtr->TaskName)-1); - TaskRecPtr->TaskName[sizeof(TaskRecPtr->TaskName)-1] = '\0'; - - CFE_ES_SysLogWrite_Unsync("ES Startup: Core App: %s created. App ID: %lu\n", - CFE_ES_ObjectTable[i].ObjectName, - CFE_ES_ResourceID_ToInteger(PendingAppId)); + /* + ** Start the core app main task + ** (core apps are already in memory - no loading needed) + */ + ReturnCode = CFE_ES_StartAppTask(&AppRecPtr->StartParams, PendingAppId, &PendingTaskId); - CFE_ES_AppRecordSetUsed(AppRecPtr, PendingAppId); - - /* - ** Increment the registered App and Registered External Task variables. - */ - CFE_ES_Global.RegisteredTasks++; - CFE_ES_Global.RegisteredCoreApps++; - - CFE_ES_UnlockSharedData(__func__,__LINE__); - - } + /* + * Finalize data in the app table entry, which must be done under lock. + * This transitions the entry from being RESERVED to the real type, + * either MAIN_TASK (success) or returning to INVALID (failure). + */ + CFE_ES_LockSharedData(__func__,__LINE__); + + if ( ReturnCode == OS_SUCCESS ) + { + AppRecPtr->MainTaskId = PendingTaskId; + CFE_ES_AppRecordSetUsed(AppRecPtr, PendingAppId); + + /* + ** Increment the Core App counter. + */ + CFE_ES_Global.RegisteredCoreApps++; + ReturnCode = CFE_SUCCESS; + } + else + { + /* failure mode - just clear the whole app table entry. + * This will set the AppType back to CFE_ES_ResourceType_INVALID (0), + * as well as clearing any other data that had been written */ + memset(AppRecPtr, 0, sizeof(*AppRecPtr)); + } + + CFE_ES_UnlockSharedData(__func__,__LINE__); } - else /* appSlot not found -- This should never happen!*/ + else { - CFE_ES_WriteToSysLog("ES Startup: Error, No free application slots available for CORE App!\n"); - /* - ** Delay to allow the message to be read - */ - OS_TaskDelay(CFE_ES_PANIC_DELAY); - - /* - ** cFE Cannot continue to start up. - */ - CFE_PSP_Panic(CFE_PSP_PANIC_CORE_APP); - + /* appSlot not found -- This should never happen!*/ + CFE_ES_WriteToSysLog("ES Startup: Error, No free application slots available for CORE App!\n"); + ReturnCode = CFE_ES_ERR_APP_CREATE; } - /* - * CFE_ES_MainTaskSyncDelay() will delay this thread until the - * newly-started thread calls CFE_ES_WaitForSystemState() - */ - if (CFE_ES_MainTaskSyncDelay(CFE_ES_AppState_RUNNING, CFE_PLATFORM_CORE_MAX_STARTUP_MSEC) != CFE_SUCCESS) + if ( ReturnCode == CFE_SUCCESS ) + { + /* + * CFE_ES_MainTaskSyncDelay() will delay this thread until the + * newly-started thread calls CFE_ES_WaitForSystemState() + */ + ReturnCode = CFE_ES_MainTaskSyncDelay(CFE_ES_AppState_RUNNING, CFE_PLATFORM_CORE_MAX_STARTUP_MSEC*1000); + } + + if ( ReturnCode != CFE_SUCCESS ) { - CFE_ES_WriteToSysLog("ES Startup: Core App %s did not complete initialization\n", - CFE_ES_ObjectTable[i].ObjectName); + CFE_ES_WriteToSysLog("ES Startup: OS_TaskCreate error creating core App: %s: EC = 0x%08X\n", + CFE_ES_ObjectTable[i].ObjectName, (unsigned int)ReturnCode); /* ** Delay to allow the message to be read diff --git a/fsw/cfe-core/unit-test/es_UT.c b/fsw/cfe-core/unit-test/es_UT.c index 3a134cf50..951918a1b 100644 --- a/fsw/cfe-core/unit-test/es_UT.c +++ b/fsw/cfe-core/unit-test/es_UT.c @@ -278,9 +278,9 @@ void ES_UT_SetupSingleAppId(CFE_ES_AppType_Enum_t AppType, CFE_ES_AppState_Enum_ if (AppName) { - strncpy(LocalAppPtr->StartParams.Name, AppName, - sizeof(LocalAppPtr->StartParams.Name)-1); - LocalAppPtr->StartParams.Name[sizeof(LocalAppPtr->StartParams.Name)-1] = 0; + strncpy(LocalAppPtr->StartParams.BasicInfo.Name, AppName, + sizeof(LocalAppPtr->StartParams.BasicInfo.Name)-1); + LocalAppPtr->StartParams.BasicInfo.Name[sizeof(LocalAppPtr->StartParams.BasicInfo.Name)-1] = 0; strncpy(LocalTaskPtr->TaskName, AppName, sizeof(LocalTaskPtr->TaskName)-1); LocalTaskPtr->TaskName[sizeof(LocalTaskPtr->TaskName)-1] = 0; @@ -360,9 +360,9 @@ void ES_UT_SetupSingleLibId(const char *LibName, CFE_ES_LibRecord_t **OutLibRec) if (LibName) { - strncpy(LocalLibPtr->LibName, LibName, - sizeof(LocalLibPtr->LibName)-1); - LocalLibPtr->LibName[sizeof(LocalLibPtr->LibName)-1] = 0; + strncpy(LocalLibPtr->BasicInfo.Name, LibName, + sizeof(LocalLibPtr->BasicInfo.Name)-1); + LocalLibPtr->BasicInfo.Name[sizeof(LocalLibPtr->BasicInfo.Name)-1] = 0; } if (OutLibRec) @@ -986,10 +986,11 @@ void TestStartupErrorPaths(void) ++TaskRecPtr; } + UT_SetHookFunction(UT_KEY(OS_TaskCreate), ES_UT_SetAppStateHook, NULL); CFE_ES_CreateObjects(); UT_Report(__FILE__, __LINE__, UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_RECORD_USED]) && - UT_GetStubCount(UT_KEY(OS_printf)) == 23, + UT_GetStubCount(UT_KEY(OS_printf)) == 13, "CFE_ES_CreateObjects", "Record used error"); @@ -1008,11 +1009,12 @@ void TestStartupErrorPaths(void) } UT_SetDeferredRetcode(UT_KEY(CFE_TBL_EarlyInit), 1, -1); + UT_SetHookFunction(UT_KEY(OS_TaskCreate), ES_UT_SetAppStateHook, NULL); CFE_ES_CreateObjects(); UT_Report(__FILE__, __LINE__, UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_RECORD_USED]) && UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_EARLYINIT]) && - UT_GetStubCount(UT_KEY(OS_printf)) == 24, + UT_GetStubCount(UT_KEY(OS_printf)) == 14, "CFE_ES_CreateObjects", "Error returned when calling function"); @@ -1022,10 +1024,11 @@ void TestStartupErrorPaths(void) ES_ResetUnitTest(); UT_SetForceFail(UT_KEY(OS_TaskCreate), OS_ERROR); UT_SetForceFail(UT_KEY(OS_BinSemCreate), OS_ERROR); + UT_SetHookFunction(UT_KEY(OS_TaskCreate), ES_UT_SetAppStateHook, NULL); CFE_ES_CreateObjects(); UT_Report(__FILE__, __LINE__, UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_CORE_APP_CREATE]) && - UT_GetStubCount(UT_KEY(OS_printf)) == 13, + UT_GetStubCount(UT_KEY(OS_printf)) == 18, "CFE_ES_CreateObjects", "Error creating core application"); @@ -1175,12 +1178,9 @@ void TestApps(void) UT_SetReadBuffer(StartupScript, NumBytes); CFE_ES_StartApplications(CFE_PSP_RST_TYPE_PROCESSOR, CFE_PLATFORM_ES_NONVOL_STARTUP_FILE); - UT_Report(__FILE__, __LINE__, - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_FILE_LINE_TOO_LONG]) && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_ES_APP_STARTUP_OPEN]) && - UT_GetStubCount(UT_KEY(OS_printf)) == 8, - "CFE_ES_StartApplications", - "Line too long"); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_FILE_LINE_TOO_LONG])); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_ES_APP_STARTUP_OPEN])); + UtAssert_UINT32_EQ(UT_GetStubCount(UT_KEY(OS_printf)), 5); /* Create a valid startup script for subsequent tests */ strncpy(StartupScript, @@ -1232,13 +1232,11 @@ void TestApps(void) /* Test successfully starting an application */ ES_ResetUnitTest(); UT_SetReadBuffer(StartupScript, NumBytes); + UT_SetHookFunction(UT_KEY(OS_TaskCreate), ES_UT_SetAppStateHook, NULL); CFE_ES_StartApplications(CFE_PSP_RST_TYPE_PROCESSOR, CFE_PLATFORM_ES_NONVOL_STARTUP_FILE); - UT_Report(__FILE__, __LINE__, - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_ES_APP_STARTUP_OPEN]) && - UT_GetStubCount(UT_KEY(OS_printf)) == 8, - "CFE_ES_StartApplications", - "Start application; successful"); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_ES_APP_STARTUP_OPEN])); + UtAssert_UINT32_EQ(UT_GetStubCount(UT_KEY(OS_printf)), 5); /* Test parsing the startup script with an unknown entry type */ ES_ResetUnitTest(); @@ -1277,11 +1275,8 @@ void TestApps(void) 170, 4096, 1); - UT_Report(__FILE__, __LINE__, - Return == CFE_ES_ERR_APP_CREATE && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_APP_CREATE]), - "CFE_ES_AppCreate", - "Task create failure"); + UtAssert_INT32_EQ(Return, CFE_STATUS_EXTERNAL_RESOURCE_FAIL); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_APP_CREATE])); /* Test application creation with NULL file name */ ES_ResetUnitTest(); @@ -1350,11 +1345,8 @@ void TestApps(void) 170, 8192, 1); - UT_Report(__FILE__, __LINE__, - Return == CFE_ES_ERR_APP_CREATE && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_EXTRACT_FILENAME_UT55]), - "CFE_ES_AppCreate", - "File load failure"); + UtAssert_INT32_EQ(Return, CFE_STATUS_EXTERNAL_RESOURCE_FAIL); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_EXTRACT_FILENAME_UT55])); /* Test application loading and creation where all app slots are taken */ ES_ResetUnitTest(); @@ -1390,11 +1382,8 @@ void TestApps(void) 170, 8192, 1); - UT_Report(__FILE__, __LINE__, - Return == CFE_ES_ERR_APP_CREATE && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_CANNOT_FIND_SYMBOL]), - "CFE_ES_AppCreate", - "Entry point symbol lookup failure"); + UtAssert_INT32_EQ(Return, CFE_STATUS_EXTERNAL_RESOURCE_FAIL); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_CANNOT_FIND_SYMBOL])); /* Test application loading and creation where the entry point symbol @@ -1410,12 +1399,9 @@ void TestApps(void) 170, 8192, 1); - UT_Report(__FILE__, __LINE__, - Return == CFE_ES_ERR_APP_CREATE && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_CANNOT_FIND_SYMBOL]) && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_MODULE_UNLOAD_FAILED]), - "CFE_ES_AppCreate", - "Module unload failure after entry point lookup failure"); + UtAssert_INT32_EQ(Return, CFE_STATUS_EXTERNAL_RESOURCE_FAIL); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_CANNOT_FIND_SYMBOL])); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_MODULE_UNLOAD_FAILED])); /* * Set up a situation where attempting to get appID by context, @@ -1498,17 +1484,17 @@ void TestApps(void) /* Test a successful control action request to exit an application */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - strncpy((char *) UtAppRecPtr->StartParams.FileName, + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.FileName, "/ram/Filename", OS_MAX_PATH_LEN); - UtAppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - strncpy((char *) UtAppRecPtr->StartParams.EntryPoint, + UtAppRecPtr->StartParams.BasicInfo.FileName[OS_MAX_PATH_LEN - 1] = '\0'; + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.EntryPoint, "NotNULL", OS_MAX_API_NAME); - UtAppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = + UtAppRecPtr->StartParams.BasicInfo.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; UtAppRecPtr->StartParams.Priority = 255; UtAppRecPtr->StartParams.StackSize = 8192; UtAppRecPtr->StartParams.ExceptionAction = 0; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_EXIT; Id = CFE_ES_AppRecordGetID(UtAppRecPtr); @@ -1525,7 +1511,7 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_EXIT; UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1541,7 +1527,7 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_DELETE; UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1557,7 +1543,7 @@ void TestApps(void) UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RESTART; UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1572,7 +1558,7 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RESTART; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UT_SetForceFail(UT_KEY(OS_TaskCreate), OS_ERROR); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); @@ -1588,7 +1574,7 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RELOAD; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); @@ -1604,7 +1590,7 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RELOAD; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UT_SetForceFail(UT_KEY(OS_TaskCreate), OS_ERROR); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); @@ -1618,17 +1604,17 @@ void TestApps(void) */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - strncpy((char *) UtAppRecPtr->StartParams.FileName, + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.FileName, "/ram/FileName", OS_MAX_PATH_LEN); - UtAppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - strncpy((char *) UtAppRecPtr->StartParams.EntryPoint, "NULL", + UtAppRecPtr->StartParams.BasicInfo.FileName[OS_MAX_PATH_LEN - 1] = '\0'; + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.EntryPoint, "NULL", OS_MAX_API_NAME); - UtAppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = + UtAppRecPtr->StartParams.BasicInfo.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; UtAppRecPtr->StartParams.Priority = 255; UtAppRecPtr->StartParams.StackSize = 8192; UtAppRecPtr->StartParams.ExceptionAction = 0; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_ERROR; Id = CFE_ES_AppRecordGetID(UtAppRecPtr); @@ -1646,7 +1632,7 @@ void TestApps(void) UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_ERROR; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1657,19 +1643,19 @@ void TestApps(void) /* Test a successful control action request to stop an application */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - strncpy((char *) UtAppRecPtr->StartParams.FileName, + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.FileName, "/ram/FileName", OS_MAX_PATH_LEN); - UtAppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - strncpy((char *) UtAppRecPtr->StartParams.EntryPoint, "NULL", + UtAppRecPtr->StartParams.BasicInfo.FileName[OS_MAX_PATH_LEN - 1] = '\0'; + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.EntryPoint, "NULL", OS_MAX_API_NAME); - UtAppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = + UtAppRecPtr->StartParams.BasicInfo.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; UtAppRecPtr->StartParams.Priority = 255; UtAppRecPtr->StartParams.StackSize = 8192; UtAppRecPtr->StartParams.ExceptionAction = 0; UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_DELETE; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1680,19 +1666,19 @@ void TestApps(void) /* Test a successful control action request to restart an application */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - strncpy((char *) UtAppRecPtr->StartParams.FileName, + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.FileName, "/ram/FileName", OS_MAX_PATH_LEN); - UtAppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - strncpy((char *) UtAppRecPtr->StartParams.EntryPoint, "NULL", + UtAppRecPtr->StartParams.BasicInfo.FileName[OS_MAX_PATH_LEN - 1] = '\0'; + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.EntryPoint, "NULL", OS_MAX_API_NAME); - UtAppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = + UtAppRecPtr->StartParams.BasicInfo.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; UtAppRecPtr->StartParams.Priority = 255; UtAppRecPtr->StartParams.StackSize = 8192; UtAppRecPtr->StartParams.ExceptionAction = 0; UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RESTART; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1703,19 +1689,19 @@ void TestApps(void) /* Test a successful control action request to reload an application */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - strncpy((char *) UtAppRecPtr->StartParams.FileName, + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.FileName, "/ram/FileName", OS_MAX_PATH_LEN); - UtAppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - strncpy((char *) UtAppRecPtr->StartParams.EntryPoint, "NULL", + UtAppRecPtr->StartParams.BasicInfo.FileName[OS_MAX_PATH_LEN - 1] = '\0'; + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.EntryPoint, "NULL", OS_MAX_API_NAME); - UtAppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = + UtAppRecPtr->StartParams.BasicInfo.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; UtAppRecPtr->StartParams.Priority = 255; UtAppRecPtr->StartParams.StackSize = 8192; UtAppRecPtr->StartParams.ExceptionAction = 0; UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_RELOAD; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1728,19 +1714,19 @@ void TestApps(void) */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - strncpy((char *) UtAppRecPtr->StartParams.FileName, + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.FileName, "/ram/FileName", OS_MAX_PATH_LEN); - UtAppRecPtr->StartParams.FileName[OS_MAX_PATH_LEN - 1] = '\0'; - strncpy((char *) UtAppRecPtr->StartParams.EntryPoint, "NULL", + UtAppRecPtr->StartParams.BasicInfo.FileName[OS_MAX_PATH_LEN - 1] = '\0'; + strncpy((char *) UtAppRecPtr->StartParams.BasicInfo.EntryPoint, "NULL", OS_MAX_API_NAME); - UtAppRecPtr->StartParams.EntryPoint[OS_MAX_API_NAME - 1] = + UtAppRecPtr->StartParams.BasicInfo.EntryPoint[OS_MAX_API_NAME - 1] = '\0'; UtAppRecPtr->StartParams.Priority = 255; UtAppRecPtr->StartParams.StackSize = 8192; UtAppRecPtr->StartParams.ExceptionAction = 0; UtAppRecPtr->ControlReq.AppControlRequest = CFE_ES_RunStatus_SYS_EXCEPTION; - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); CFE_ES_ProcessControlRequest(Id); UT_Report(__FILE__, __LINE__, @@ -1809,7 +1795,7 @@ void TestApps(void) ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); ES_UT_SetupForOSCleanup(); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UT_SetForceFail(UT_KEY(OS_TaskDelete), OS_ERROR); UT_SetForceFail(UT_KEY(OS_close), OS_ERROR); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); @@ -1823,7 +1809,7 @@ void TestApps(void) */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, NULL, NULL); ES_UT_SetupForOSCleanup(); UT_SetDeferredRetcode(UT_KEY(OS_MutSemDelete), 1, OS_ERROR); @@ -1838,7 +1824,7 @@ void TestApps(void) */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UT_SetDeferredRetcode(UT_KEY(OS_ModuleUnload), 1, OS_ERROR); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, @@ -1851,7 +1837,7 @@ void TestApps(void) */ ES_ResetUnitTest(); ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); UT_SetDeferredRetcode(UT_KEY(CFE_EVS_CleanUpApp), 1, -1); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, @@ -2023,12 +2009,12 @@ void TestApps(void) ES_ResetUnitTest(); /* Setup an entry which will be deleted */ ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); /* Setup a second entry which will NOT be deleted */ ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, NULL, &UtTaskRecPtr); ES_UT_SetupMemPoolId(&UtPoolRecPtr); UtPoolRecPtr->OwnerAppID = CFE_ES_AppRecordGetID(UtAppRecPtr); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); /* Associate a child task with the app to be deleted */ ES_UT_SetupChildTaskId(UtAppRecPtr, NULL, NULL); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); @@ -2051,7 +2037,7 @@ void TestApps(void) ES_ResetUnitTest(); /* Setup an entry which will be deleted */ ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); ES_UT_SetupMemPoolId(&UtPoolRecPtr); UtPoolRecPtr->OwnerAppID = CFE_ES_AppRecordGetID(UtAppRecPtr); UtPoolRecPtr->PoolID = CFE_ES_ResourceID_FromInteger(99999); /* Mismatch */ @@ -2072,10 +2058,10 @@ void TestApps(void) /* Setup an entry which will be deleted */ ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, NULL); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); /* Setup a second entry which will NOT be deleted */ ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, NULL, &UtTaskRecPtr); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, NULL, NULL); + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, NULL, NULL); /* Associate a child task with the app to be deleted */ ES_UT_SetupChildTaskId(UtAppRecPtr, NULL, NULL); @@ -2131,7 +2117,7 @@ void TestApps(void) /* Setup an entry which will be deleted */ ES_UT_SetupSingleAppId(CFE_ES_AppType_EXTERNAL, CFE_ES_AppState_RUNNING, NULL, &UtAppRecPtr, &UtTaskRecPtr); - OS_ModuleLoad(&UtAppRecPtr->StartParams.ModuleId, "UT", + OS_ModuleLoad(&UtAppRecPtr->ModuleInfo.ModuleId, "UT", "ut-module"); Id = CFE_ES_AppRecordGetID(UtAppRecPtr); UT_Report(__FILE__, __LINE__, @@ -2202,7 +2188,7 @@ void TestResourceID(void) void TestLibs(void) { CFE_ES_LibRecord_t *UtLibRecPtr; - char LongLibraryName[sizeof(UtLibRecPtr->LibName)+1]; + char LongLibraryName[sizeof(UtLibRecPtr->BasicInfo.Name)+1]; CFE_ES_ResourceID_t Id; uint32 j; int32 Return; @@ -2216,11 +2202,8 @@ void TestLibs(void) "filename", "EntryPoint", "LibName"); - UT_Report(__FILE__, __LINE__, - Return == -444 && - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_SHARED_LIBRARY_INIT]), - "CFE_ES_LoadLibrary", - "Load shared library initialization failure"); + UtAssert_INT32_EQ(Return, -444); + UtAssert_NONZERO(UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_SHARED_LIBRARY_INIT])); /* Test Load library returning an error on a null pointer argument */ Return = CFE_ES_LoadLibrary(&Id, @@ -2242,8 +2225,8 @@ void TestLibs(void) "Load shared library bad argument (NULL library name)"); /* Test Load library returning an error on a too long library name */ - memset(&LongLibraryName[0], 'a', sizeof(UtLibRecPtr->LibName)); - LongLibraryName[sizeof(UtLibRecPtr->LibName)] = '\0'; + memset(&LongLibraryName[0], 'a', sizeof(LongLibraryName)-1); + LongLibraryName[sizeof(LongLibraryName)-1] = '\0'; Return = CFE_ES_LoadLibrary(&Id, "filename", "EntryPoint", @@ -2290,10 +2273,7 @@ void TestLibs(void) "/cf/apps/tst_lib.bundle", "TST_LIB_Init", "TST_LIB"); - UT_Report(__FILE__, __LINE__, - Return == CFE_ES_ERR_LOAD_LIB, - "CFE_ES_LoadLibrary", - "Load shared library failure"); + UtAssert_INT32_EQ(Return, CFE_STATUS_EXTERNAL_RESOURCE_FAIL); /* Test shared library loading and initialization where the library * entry point symbol cannot be found @@ -2304,10 +2284,7 @@ void TestLibs(void) "/cf/apps/tst_lib.bundle", "TST_LIB_Init", "TST_LIB"); - UT_Report(__FILE__, __LINE__, - Return == CFE_ES_ERR_LOAD_LIB, - "CFE_ES_LoadLibrary", - "Could not find library initialization symbol"); + UtAssert_INT32_EQ(Return, CFE_STATUS_EXTERNAL_RESOURCE_FAIL); /* Test shared library loading and initialization where the library * initialization function fails and then must be cleaned up diff --git a/fsw/cfe-core/unit-test/ut_osprintf_stubs.c b/fsw/cfe-core/unit-test/ut_osprintf_stubs.c index 6face1351..facd86a3c 100644 --- a/fsw/cfe-core/unit-test/ut_osprintf_stubs.c +++ b/fsw/cfe-core/unit-test/ut_osprintf_stubs.c @@ -93,7 +93,7 @@ const char *UT_OSP_MESSAGES[] = /* ES Startup: Error Re-Formating Volatile(RAM) Volume. EC = 0x~ */ [UT_OSP_REFORMAT_VOLATILE] = "ES Startup: Error Re-Formating Volatile(RAM) Volume. EC = 0x%08X\n", /* ES Startup: Could not load cFE application file:ut/filename.x. EC = 0x~ */ - [UT_OSP_EXTRACT_FILENAME_UT55] = "ES Startup: Could not load cFE application file:%s. EC = 0x%08X\n", + [UT_OSP_EXTRACT_FILENAME_UT55] = "ES Startup: Could not load file:%s. EC = 0x%08X\n", /* ES Startup: Unable to extract filename from path: ut46/ */ [UT_OSP_EXTRACT_FILENAME_UT46] = "ES Startup: Unable to extract filename from path: %s.\n", /* ES Startup: No free application slots available */ @@ -123,7 +123,7 @@ const char *UT_OSP_MESSAGES[] = /* ES Startup: Error Creating Volatile(RAM) Volume. EC = 0x~ */ [UT_OSP_CREATE_VOLATILE] = "ES Startup: Error Creating Volatile(RAM) Volume. EC = 0x%08X\n", /* ES Startup: Failed to unload APP: AppName. EC = 0x~ */ - [UT_OSP_MODULE_UNLOAD_FAILED] = "ES Startup: Failed to unload APP: %s. EC = 0x%08X\n", + [UT_OSP_MODULE_UNLOAD_FAILED] = "ES Startup: Failed to unload: %s. EC = 0x%08X\n", /* POWERON RESET called from CFE_ES_ResetCFE (Commanded). */ [UT_OSP_POR_COMMANDED] = "POWERON RESET called from CFE_ES_ResetCFE (Commanded).\n", /* ES Startup: Error Re-Mounting Volatile(RAM) Volume. EC = 0x~ */ @@ -159,7 +159,7 @@ const char *UT_OSP_MESSAGES[] = /* ES Startup: Error, No free application slots available for CORE App! */ [UT_OSP_NO_FREE_CORE_APP_SLOTS] = "ES Startup: Error, No free application slots available for CORE App!\n", /* ES Startup: CFE_ES_Global.TaskTable record used error for App: CFE_EVS, continuing. */ - [UT_OSP_RECORD_USED] = "ES Startup: CFE_ES_Global.TaskTable record used error for App: %s, continuing.\n", + [UT_OSP_RECORD_USED] = "ES Startup: Error: ES_TaskTable slot for ID %lx in use at task creation!\n", /* CFE_ES_ExitChildTask called from invalid task context */ [UT_OSP_TASKEXIT_BAD_CONTEXT] = "CFE_ES_ExitChildTask called from invalid task context\n", }; From 1c75d338435a6ff1ccd7475edc4186455c0ea845 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Mon, 19 Oct 2020 16:34:18 -0400 Subject: [PATCH 3/3] Fix #28, Provide Library API similar to App API Allows the existing "CFE_ES_AppInfo_t" structure to be extended to libraries as well as applications by introducing a new value (3) for the Type field. Allows Libraries to be queried via API calls similar to App API. Also extends the Query All/Query One commands to operate on Libraries or Applications. --- fsw/cfe-core/src/es/cfe_es_api.c | 258 ++++++++++++++---- fsw/cfe-core/src/es/cfe_es_apps.c | 211 ++++---------- fsw/cfe-core/src/es/cfe_es_apps.h | 33 ++- fsw/cfe-core/src/es/cfe_es_task.c | 105 +++++-- fsw/cfe-core/src/es/cfe_es_task.h | 6 + fsw/cfe-core/src/inc/cfe_es.h | 76 +++++- fsw/cfe-core/src/inc/cfe_es_extern_typedefs.h | 7 +- 7 files changed, 444 insertions(+), 252 deletions(-) diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index 78b2feb25..3955160bd 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -965,8 +965,10 @@ int32 CFE_ES_GetTaskName(char *TaskName, CFE_ES_ResourceID_t TaskId, uint32 Buff */ int32 CFE_ES_GetAppInfo(CFE_ES_AppInfo_t *AppInfo, CFE_ES_ResourceID_t AppId) { - int32 ReturnCode = CFE_SUCCESS; CFE_ES_AppRecord_t *AppRecPtr; + CFE_ES_TaskRecord_t *TaskRecPtr; + int32 Status; + uint32 i; if ( AppInfo == NULL ) { @@ -976,73 +978,233 @@ int32 CFE_ES_GetAppInfo(CFE_ES_AppInfo_t *AppInfo, CFE_ES_ResourceID_t AppId) memset(AppInfo, 0, sizeof(*AppInfo)); - /* - ** Get App Record - */ AppRecPtr = CFE_ES_LocateAppRecordByID(AppId); - if ( AppRecPtr == NULL ) + + CFE_ES_LockSharedData(__func__,__LINE__); + + if ( !CFE_ES_AppRecordIsMatch(AppRecPtr, AppId) ) { - CFE_ES_WriteToSysLog("CFE_ES_GetAppInfo: App ID Invalid: %lu\n", + /* + * Log a message if called with an invalid ID. + */ + CFE_ES_WriteToSysLog("CFE_ES_GetAppInfo: App ID not active: %lu\n", CFE_ES_ResourceID_ToInteger(AppId)); - return CFE_ES_ERR_RESOURCEID_NOT_VALID; - } + + Status = CFE_ES_ERR_RESOURCEID_NOT_VALID; + } + else + { + AppInfo->AppId = AppId; + AppInfo->Type = AppRecPtr->Type; + + CFE_ES_CopyModuleBasicInfo(&AppRecPtr->StartParams.BasicInfo, AppInfo); + CFE_ES_CopyModuleStatusInfo(&AppRecPtr->ModuleInfo, AppInfo); + + AppInfo->StackSize = AppRecPtr->StartParams.StackSize; + AppInfo->ExceptionAction = AppRecPtr->StartParams.ExceptionAction; + AppInfo->Priority = AppRecPtr->StartParams.Priority; + AppInfo->MainTaskId = AppRecPtr->MainTaskId; + + /* + ** Calculate the number of child tasks + */ + AppInfo->NumOfChildTasks = 0; + TaskRecPtr = CFE_ES_Global.TaskTable; + for (i=0; iAppId, AppId)) + { + if (CFE_ES_ResourceID_Equal(CFE_ES_TaskRecordGetID(TaskRecPtr), AppInfo->MainTaskId)) + { + /* This is the main task - capture its name and execution count */ + AppInfo->ExecutionCounter = TaskRecPtr->ExecutionCounter; + strncpy(AppInfo->MainTaskName, TaskRecPtr->TaskName, + sizeof(AppInfo->MainTaskName) - 1); + AppInfo->MainTaskName[sizeof(AppInfo->MainTaskName) - 1] = '\0'; + } + else + { + /* This is a child task, no extra info, just increment count */ + ++AppInfo->NumOfChildTasks; + } + } + ++TaskRecPtr; + } + + Status = CFE_SUCCESS; + } + + CFE_ES_UnlockSharedData(__func__,__LINE__); /* - * Note - cannot check if the AppID is active here, - * as the table is not locked. The internal function - * should lock and check. - */ - ReturnCode = CFE_ES_GetAppInfoInternal(AppRecPtr, AppInfo); - if (ReturnCode != CFE_SUCCESS) + ** Get the address information from the OSAL + */ + if (Status == CFE_SUCCESS) { - CFE_ES_WriteToSysLog("CFE_ES_GetAppInfo: App ID Not Active: %lu\n", - CFE_ES_ResourceID_ToInteger(AppId)); + CFE_ES_CopyModuleAddressInfo(AppInfo->ModuleId, AppInfo); } - return(ReturnCode); + return Status; +} + +/* +** Function: CFE_ES_GetLibInfo - See API and header file for details +*/ +int32 CFE_ES_GetLibInfo(CFE_ES_AppInfo_t *LibInfo, CFE_ES_ResourceID_t LibId) +{ + int32 Status; + CFE_ES_LibRecord_t *LibRecPtr; + + if ( LibInfo == NULL ) + { + CFE_ES_WriteToSysLog("CFE_ES_GetLibInfo: Invalid Parameter ( Null Pointer )\n"); + return CFE_ES_ERR_BUFFER; + } + + LibRecPtr = CFE_ES_LocateLibRecordByID(LibId); + + CFE_ES_LockSharedData(__func__,__LINE__); + + if ( !CFE_ES_LibRecordIsMatch(LibRecPtr, LibId) ) + { + /* + * Log a message if called with an invalid ID. + */ + CFE_ES_SysLogWrite_Unsync("CFE_ES_GetLibInfo: Lib ID not active: %lu\n", + CFE_ES_ResourceID_ToInteger(LibId)); + + Status = CFE_ES_ERR_RESOURCEID_NOT_VALID; + } + else + { + LibInfo->AppId = CFE_ES_LibRecordGetID(LibRecPtr);; + LibInfo->Type = CFE_ES_AppType_LIBRARY; + + CFE_ES_CopyModuleBasicInfo(&LibRecPtr->BasicInfo, LibInfo); + CFE_ES_CopyModuleStatusInfo(&LibRecPtr->ModuleInfo, LibInfo); + + Status = CFE_SUCCESS; + } + + CFE_ES_UnlockSharedData(__func__,__LINE__); + + /* + ** Get the address information from the OSAL + */ + if (Status == CFE_SUCCESS) + { + CFE_ES_CopyModuleAddressInfo(LibInfo->ModuleId, LibInfo); + } + + return Status; +} + +/* +** Function: CFE_ES_GetModuleInfo - See API and header file for details +*/ +int32 CFE_ES_GetModuleInfo(CFE_ES_AppInfo_t *ModuleInfo, CFE_ES_ResourceID_t ResourceId) +{ + uint32 ResourceType; + int32 Status; + + ResourceType = CFE_ES_ResourceID_ToInteger(ResourceId); + ResourceType -= ResourceType & CFE_ES_RESOURCEID_MAX; + switch(ResourceType) + { + case CFE_ES_APPID_BASE: + Status = CFE_ES_GetAppInfo(ModuleInfo, ResourceId); + break; + case CFE_ES_LIBID_BASE: + Status = CFE_ES_GetLibInfo(ModuleInfo, ResourceId); + break; + default: + /* + * Log a message if called with an invalid ID. + */ + CFE_ES_WriteToSysLog("CFE_ES_GetModuleInfo: Resource ID not valid: %lu\n", + CFE_ES_ResourceID_ToInteger(ResourceId)); + Status = CFE_ES_ERR_RESOURCEID_NOT_VALID; + break; + + } + + return(Status); -} /* End of CFE_ES_GetAppInfo() */ +} /* End of CFE_ES_GetModuleInfo() */ /* ** Function: CFE_ES_GetTaskInfo - See API and header file for details */ int32 CFE_ES_GetTaskInfo(CFE_ES_TaskInfo_t *TaskInfo, CFE_ES_ResourceID_t TaskId) { - CFE_ES_TaskRecord_t *TaskRecPtr; - int32 ReturnCode; + CFE_ES_TaskRecord_t *TaskRecPtr; + CFE_ES_AppRecord_t *AppRecPtr; + int32 Status; - if ( TaskInfo == NULL ) - { - CFE_ES_WriteToSysLog("CFE_ES_GetTaskInfo: Invalid Parameter ( Null Pointer )\n"); - return CFE_ES_ERR_BUFFER; - } + if ( TaskInfo == NULL ) + { + CFE_ES_WriteToSysLog("CFE_ES_GetTaskInfo: Invalid Parameter ( Null Pointer )\n"); + return CFE_ES_ERR_BUFFER; + } - memset(TaskInfo, 0, sizeof(*TaskInfo)); + memset(TaskInfo, 0, sizeof(*TaskInfo)); - /* - ** Get Task Record - */ - TaskRecPtr = CFE_ES_LocateTaskRecordByID(TaskId); - if ( TaskRecPtr == NULL ) - { - CFE_ES_WriteToSysLog("CFE_ES_GetTaskInfo: Task ID Not Valid: %lu\n", - CFE_ES_ResourceID_ToInteger(TaskId)); - return CFE_ES_ERR_RESOURCEID_NOT_VALID; - } + TaskRecPtr = CFE_ES_LocateTaskRecordByID(TaskId); - /* - * Note - cannot check if the TaskID is active here, - * as the table is not locked. The internal function - * should lock and check. - */ - ReturnCode = CFE_ES_GetTaskInfoInternal(TaskRecPtr, TaskInfo); - if (ReturnCode != CFE_SUCCESS) - { - CFE_ES_WriteToSysLog("CFE_ES_GetTaskInfo: Task ID Not Active: %lu\n", - CFE_ES_ResourceID_ToInteger(TaskId)); - } + CFE_ES_LockSharedData(__func__,__LINE__); - return(ReturnCode); + if ( !CFE_ES_TaskRecordIsMatch(TaskRecPtr, TaskId) ) + { + /* task ID is bad */ + Status = CFE_ES_ERR_RESOURCEID_NOT_VALID; + CFE_ES_SysLogWrite_Unsync("CFE_ES_GetTaskInfo: Task ID Not Active: %lu\n", + CFE_ES_ResourceID_ToInteger(TaskId)); + } + else + { + + /* + ** Get the Application ID and Task Name + */ + TaskInfo->AppId = TaskRecPtr->AppId; + strncpy(TaskInfo->TaskName, + CFE_ES_TaskRecordGetName(TaskRecPtr), + sizeof(TaskInfo->TaskName)-1); + TaskInfo->TaskName[sizeof(TaskInfo->TaskName)-1] = '\0'; + + /* + ** Store away the Task ID ( for the QueryAllTasks Cmd ) + */ + TaskInfo->TaskId = CFE_ES_TaskRecordGetID(TaskRecPtr); + + /* + ** Get the Execution counter for the task + */ + TaskInfo->ExecutionCounter = TaskRecPtr->ExecutionCounter; + + /* + ** Get the Application Details + */ + AppRecPtr = CFE_ES_LocateAppRecordByID(TaskRecPtr->AppId); + if (CFE_ES_AppRecordIsMatch(AppRecPtr, TaskRecPtr->AppId)) + { + strncpy(TaskInfo->AppName, + CFE_ES_AppRecordGetName(AppRecPtr), + sizeof(TaskInfo->AppName)-1); + TaskInfo->AppName[sizeof(TaskInfo->AppName)-1] = '\0'; + Status = CFE_SUCCESS; + } + else + { + /* task ID was OK but parent app ID is bad */ + Status = CFE_ES_ERR_RESOURCEID_NOT_VALID; + } + } + + CFE_ES_UnlockSharedData(__func__,__LINE__); + + return(Status); } /* End of CFE_ES_GetTaskInfo() */ diff --git a/fsw/cfe-core/src/es/cfe_es_apps.c b/fsw/cfe-core/src/es/cfe_es_apps.c index a20402195..3800a898c 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.c +++ b/fsw/cfe-core/src/es/cfe_es_apps.c @@ -1713,7 +1713,7 @@ int32 CFE_ES_CleanupTaskResources(CFE_ES_ResourceID_t TaskId) /* **--------------------------------------------------------------------------------------- -** Name: CFE_ES_GetAppInfoInternal +** Name: CFE_ES_CopyModuleBasicInfo ** ** Purpose: Populate the cFE_ES_AppInfo structure with the data for an app. ** @@ -1721,180 +1721,71 @@ int32 CFE_ES_CleanupTaskResources(CFE_ES_ResourceID_t TaskId) ** to check the return code and log any relevant errors based on the context. **--------------------------------------------------------------------------------------- */ -int32 CFE_ES_GetAppInfoInternal(CFE_ES_AppRecord_t *AppRecPtr, CFE_ES_AppInfo_t *AppInfoPtr ) +void CFE_ES_CopyModuleBasicInfo(const CFE_ES_ModuleLoadParams_t *ParamsPtr, CFE_ES_AppInfo_t *AppInfoPtr) { - int32 Status; - int32 ReturnCode; - OS_module_prop_t ModuleInfo; - uint32 i; - CFE_ES_TaskRecord_t *TaskRecPtr; - CFE_ES_ResourceID_t AppId; + strncpy(AppInfoPtr->Name, ParamsPtr->Name, + sizeof(AppInfoPtr->Name)-1); + AppInfoPtr->Name[sizeof(AppInfoPtr->Name)-1] = '\0'; - CFE_ES_LockSharedData(__func__,__LINE__); - - if ( !CFE_ES_AppRecordIsUsed(AppRecPtr) ) - { - Status = CFE_ES_ERR_RESOURCEID_NOT_VALID; - } - else - { - Status = CFE_SUCCESS; - - AppId = CFE_ES_AppRecordGetID(AppRecPtr); - AppInfoPtr->AppId = AppId; - AppInfoPtr->Type = AppRecPtr->Type; - strncpy(AppInfoPtr->Name, - CFE_ES_AppRecordGetName(AppRecPtr), - sizeof(AppInfoPtr->Name)-1); - AppInfoPtr->Name[sizeof(AppInfoPtr->Name)-1] = '\0'; - - strncpy(AppInfoPtr->EntryPoint, AppRecPtr->StartParams.BasicInfo.EntryPoint, - sizeof(AppInfoPtr->EntryPoint) - 1); - AppInfoPtr->EntryPoint[sizeof(AppInfoPtr->EntryPoint) - 1] = '\0'; - - strncpy(AppInfoPtr->FileName, AppRecPtr->StartParams.BasicInfo.FileName, - sizeof(AppInfoPtr->FileName) - 1); - AppInfoPtr->FileName[sizeof(AppInfoPtr->FileName) - 1] = '\0'; - - AppInfoPtr->ModuleId = AppRecPtr->ModuleInfo.ModuleId; - AppInfoPtr->StackSize = AppRecPtr->StartParams.StackSize; - CFE_SB_SET_MEMADDR(AppInfoPtr->StartAddress, AppRecPtr->ModuleInfo.EntryAddress); - AppInfoPtr->ExceptionAction = AppRecPtr->StartParams.ExceptionAction; - AppInfoPtr->Priority = AppRecPtr->StartParams.Priority; - - AppInfoPtr->MainTaskId = AppRecPtr->MainTaskId; - - /* - ** Calculate the number of child tasks - */ - AppInfoPtr->NumOfChildTasks = 0; - TaskRecPtr = CFE_ES_Global.TaskTable; - for (i=0; iAppId, AppId) && - !CFE_ES_ResourceID_Equal(CFE_ES_TaskRecordGetID(TaskRecPtr), AppInfoPtr->MainTaskId) ) - { - AppInfoPtr->NumOfChildTasks++; - } - ++TaskRecPtr; - } - - /* - ** Get the execution counter for the main task - */ - TaskRecPtr = CFE_ES_LocateTaskRecordByID(AppInfoPtr->MainTaskId); - if (CFE_ES_TaskRecordIsMatch(TaskRecPtr,AppInfoPtr->MainTaskId)) - { - AppInfoPtr->ExecutionCounter = TaskRecPtr->ExecutionCounter; - strncpy(AppInfoPtr->MainTaskName, TaskRecPtr->TaskName, - sizeof(AppInfoPtr->MainTaskName) - 1); - AppInfoPtr->MainTaskName[sizeof(AppInfoPtr->MainTaskName) - 1] = '\0'; - } + strncpy(AppInfoPtr->EntryPoint, ParamsPtr->EntryPoint, + sizeof(AppInfoPtr->EntryPoint) - 1); + AppInfoPtr->EntryPoint[sizeof(AppInfoPtr->EntryPoint) - 1] = '\0'; - /* - ** Get the address information from the OSAL - */ - ReturnCode = OS_ModuleInfo ( AppInfoPtr->ModuleId, &ModuleInfo ); - if ( ReturnCode == OS_SUCCESS ) - { - AppInfoPtr->AddressesAreValid = - (sizeof(ModuleInfo.addr.code_address) <= sizeof(AppInfoPtr->CodeAddress)) && - ModuleInfo.addr.valid; - CFE_SB_SET_MEMADDR(AppInfoPtr->CodeAddress, ModuleInfo.addr.code_address); - CFE_SB_SET_MEMADDR(AppInfoPtr->CodeSize, ModuleInfo.addr.code_size); - CFE_SB_SET_MEMADDR(AppInfoPtr->DataAddress, ModuleInfo.addr.data_address); - CFE_SB_SET_MEMADDR(AppInfoPtr->DataSize, ModuleInfo.addr.data_size); - CFE_SB_SET_MEMADDR(AppInfoPtr->BSSAddress, ModuleInfo.addr.bss_address); - CFE_SB_SET_MEMADDR(AppInfoPtr->BSSSize, ModuleInfo.addr.bss_size); - } - else - { - AppInfoPtr->AddressesAreValid = false; - AppInfoPtr->CodeAddress = 0; - AppInfoPtr->CodeSize = 0; - AppInfoPtr->DataAddress = 0; - AppInfoPtr->DataSize = 0; - AppInfoPtr->BSSAddress = 0; - AppInfoPtr->BSSSize = 0; - } - - } - - CFE_ES_UnlockSharedData(__func__,__LINE__); - - return Status; - -} /* end function */ + strncpy(AppInfoPtr->FileName, ParamsPtr->FileName, + sizeof(AppInfoPtr->FileName) - 1); + AppInfoPtr->FileName[sizeof(AppInfoPtr->FileName) - 1] = '\0'; +} /* **--------------------------------------------------------------------------------------- -** Name: CFE_ES_GetAppInfoInternal +** Name: CFE_ES_CopyModuleStatusInfo ** -** Purpose: Populate the cFE_ES_TaskInfo structure with the data for a task. +** Purpose: Populate the cFE_ES_AppInfo structure with the data for an app. ** ** This internal function does not log any errors/events. The caller is expected ** to check the return code and log any relevant errors based on the context. **--------------------------------------------------------------------------------------- */ -int32 CFE_ES_GetTaskInfoInternal(CFE_ES_TaskRecord_t *TaskRecPtr, CFE_ES_TaskInfo_t *TaskInfoPtr) +void CFE_ES_CopyModuleStatusInfo(const CFE_ES_ModuleLoadStatus_t *StatusPtr, CFE_ES_AppInfo_t *AppInfoPtr) { - CFE_ES_AppRecord_t *AppRecPtr; - int32 ReturnCode; - - CFE_ES_LockSharedData(__func__,__LINE__); - - if ( CFE_ES_TaskRecordIsUsed(TaskRecPtr) ) - { - - /* - ** Get the Application ID and Task Name - */ - TaskInfoPtr->AppId = TaskRecPtr->AppId; - strncpy(TaskInfoPtr->TaskName, - CFE_ES_TaskRecordGetName(TaskRecPtr), - sizeof(TaskInfoPtr->TaskName)-1); - TaskInfoPtr->TaskName[sizeof(TaskInfoPtr->TaskName)-1] = '\0'; - - /* - ** Store away the Task ID ( for the QueryAllTasks Cmd ) - */ - TaskInfoPtr->TaskId = CFE_ES_TaskRecordGetID(TaskRecPtr); - - /* - ** Get the Execution counter for the task - */ - TaskInfoPtr->ExecutionCounter = TaskRecPtr->ExecutionCounter; - - /* - ** Get the Application Details - */ - AppRecPtr = CFE_ES_LocateAppRecordByID(TaskRecPtr->AppId); - if (CFE_ES_AppRecordIsMatch(AppRecPtr, TaskRecPtr->AppId)) - { - strncpy(TaskInfoPtr->AppName, - CFE_ES_AppRecordGetName(AppRecPtr), - sizeof(TaskInfoPtr->AppName)-1); - TaskInfoPtr->AppName[sizeof(TaskInfoPtr->AppName)-1] = '\0'; - ReturnCode = CFE_SUCCESS; - } - else - { - /* task ID was OK but parent app ID is bad */ - ReturnCode = CFE_ES_ERR_RESOURCEID_NOT_VALID; - } - } - else - { - /* task ID is bad */ - ReturnCode = CFE_ES_ERR_RESOURCEID_NOT_VALID; - } - - CFE_ES_UnlockSharedData(__func__,__LINE__); + AppInfoPtr->ModuleId = StatusPtr->ModuleId; + CFE_SB_SET_MEMADDR(AppInfoPtr->StartAddress, StatusPtr->EntryAddress); +} - return(ReturnCode); +/* +**--------------------------------------------------------------------------------------- +** Name: CFE_ES_CopyModuleAddressInfo +** +** Purpose: Populate the cFE_ES_AppInfo structure with the data for an app. +** +** This internal function does not log any errors/events. The caller is expected +** to check the return code and log any relevant errors based on the context. +**--------------------------------------------------------------------------------------- +*/ +void CFE_ES_CopyModuleAddressInfo(osal_id_t ModuleId, CFE_ES_AppInfo_t *AppInfoPtr) +{ + OS_module_prop_t ModuleInfo; + int32 ReturnCode; -} /* End of CFE_ES_GetTaskInfoInternal() */ + ReturnCode = OS_ModuleInfo ( ModuleId, &ModuleInfo ); + if ( ReturnCode == OS_SUCCESS ) + { + AppInfoPtr->AddressesAreValid = + (sizeof(ModuleInfo.addr.code_address) <= sizeof(AppInfoPtr->CodeAddress)) && + ModuleInfo.addr.valid; + } + else + { + AppInfoPtr->AddressesAreValid = false; + memset(&ModuleInfo, 0, sizeof(ModuleInfo)); + } + CFE_SB_SET_MEMADDR(AppInfoPtr->CodeAddress, ModuleInfo.addr.code_address); + CFE_SB_SET_MEMADDR(AppInfoPtr->CodeSize, ModuleInfo.addr.code_size); + CFE_SB_SET_MEMADDR(AppInfoPtr->DataAddress, ModuleInfo.addr.data_address); + CFE_SB_SET_MEMADDR(AppInfoPtr->DataSize, ModuleInfo.addr.data_size); + CFE_SB_SET_MEMADDR(AppInfoPtr->BSSAddress, ModuleInfo.addr.bss_address); + CFE_SB_SET_MEMADDR(AppInfoPtr->BSSSize, ModuleInfo.addr.bss_size); +} diff --git a/fsw/cfe-core/src/es/cfe_es_apps.h b/fsw/cfe-core/src/es/cfe_es_apps.h index 2c7540e50..e9aaa7562 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.h +++ b/fsw/cfe-core/src/es/cfe_es_apps.h @@ -279,18 +279,33 @@ int32 CFE_ES_CleanUpApp(CFE_ES_ResourceID_t AppId); */ int32 CFE_ES_CleanupTaskResources(CFE_ES_ResourceID_t TaskId); + /* -** Populate the cFE_ES_AppInfo structure with the data for an app -** This is an internal function for use in ES. -** The newer external API is : CFE_ES_GetAppInfo +**--------------------------------------------------------------------------------------- +** Name: CFE_ES_CopyModuleBasicInfo +** +** Purpose: Populate the cFE_ES_AppInfo structure from the CFE_ES_ModuleLoadParams_t data +**--------------------------------------------------------------------------------------- */ -int32 CFE_ES_GetAppInfoInternal(CFE_ES_AppRecord_t *AppRecPtr, CFE_ES_AppInfo_t *AppInfoPtr ); +void CFE_ES_CopyModuleBasicInfo(const CFE_ES_ModuleLoadParams_t *ParamsPtr, CFE_ES_AppInfo_t *AppInfoPtr); /* - * Populate the CFE_ES_TaskInfo_t structure with the data for a task - * This is an internal function for use in ES. - * (Equivalent pattern to CFE_ES_GetAppInfoInternal() but for tasks) - */ -int32 CFE_ES_GetTaskInfoInternal(CFE_ES_TaskRecord_t *TaskRecPtr, CFE_ES_TaskInfo_t *TaskInfoPtr ); +**--------------------------------------------------------------------------------------- +** Name: CFE_ES_CopyModuleStatusInfo +** +** Purpose: Populate the cFE_ES_AppInfo structure from the CFE_ES_ModuleLoadStatus_t data +**--------------------------------------------------------------------------------------- +*/ +void CFE_ES_CopyModuleStatusInfo(const CFE_ES_ModuleLoadStatus_t *StatusPtr, CFE_ES_AppInfo_t *AppInfoPtr); + +/* +**--------------------------------------------------------------------------------------- +** Name: CFE_ES_CopyModuleAddressInfo +** +** Purpose: Populate the cFE_ES_AppInfo structure with address information from OSAL. +**--------------------------------------------------------------------------------------- +*/ +void CFE_ES_CopyModuleAddressInfo(osal_id_t ModuleId, CFE_ES_AppInfo_t *AppInfoPtr); + #endif /* _cfe_es_apps_ */ diff --git a/fsw/cfe-core/src/es/cfe_es_task.c b/fsw/cfe-core/src/es/cfe_es_task.c index 3540b3f2a..8411d3ac7 100644 --- a/fsw/cfe-core/src/es/cfe_es_task.c +++ b/fsw/cfe-core/src/es/cfe_es_task.c @@ -41,6 +41,7 @@ #include "cfe_version.h" #include "cfe_es_global.h" #include "cfe_es_apps.h" +#include "cfe_es_resource.h" #include "cfe_es_events.h" #include "cfe_es_verify.h" #include "cfe_es_task.h" @@ -1118,16 +1119,21 @@ int32 CFE_ES_QueryOneCmd(const CFE_ES_QueryOne_t *data) { const CFE_ES_AppNameCmd_Payload_t *cmd = &data->Payload; char LocalApp[OS_MAX_API_NAME]; - CFE_ES_ResourceID_t AppID; + CFE_ES_ResourceID_t ResourceID; int32 Result; CFE_SB_MessageStringGet(LocalApp, (char *)cmd->Application, NULL, OS_MAX_API_NAME, sizeof(cmd->Application)); - Result = CFE_ES_GetAppIDByName(&AppID, LocalApp); + Result = CFE_ES_GetAppIDByName(&ResourceID, LocalApp); + if (Result == CFE_ES_ERR_NAME_NOT_FOUND) + { + /* Also check for a matching library name */ + Result = CFE_ES_GetLibIDByName(&ResourceID, LocalApp); + } if (Result == CFE_SUCCESS) { - Result = CFE_ES_GetAppInfo(&(CFE_ES_TaskData.OneAppPacket.Payload.AppInfo), AppID); + Result = CFE_ES_GetModuleInfo(&(CFE_ES_TaskData.OneAppPacket.Payload.AppInfo), ResourceID); } /* @@ -1182,7 +1188,10 @@ int32 CFE_ES_QueryAllCmd(const CFE_ES_QueryAll_t *data) CFE_ES_AppInfo_t AppInfo; const CFE_ES_FileNameCmd_Payload_t *CmdPtr = &data->Payload; char QueryAllFilename[OS_MAX_PATH_LEN]; + CFE_ES_ResourceID_t ResourceList[CFE_ES_QUERY_ALL_MAX_ENTRIES]; + uint32 NumResources; CFE_ES_AppRecord_t *AppRecPtr; + CFE_ES_LibRecord_t *LibRecPtr; /* ** Copy the commanded filename into local buffer to ensure size limitation and to allow for modification @@ -1190,6 +1199,38 @@ int32 CFE_ES_QueryAllCmd(const CFE_ES_QueryAll_t *data) CFE_SB_MessageStringGet(QueryAllFilename, (char *)CmdPtr->FileName, CFE_PLATFORM_ES_DEFAULT_APP_LOG_FILE, OS_MAX_PATH_LEN, sizeof(CmdPtr->FileName)); + /* + * Collect list of active resource IDs. + * + * This should be done while locked, but the actual writing + * of the AppInfo data should be done while NOT locked. + */ + CFE_ES_LockSharedData(__func__, __LINE__); + NumResources = 0; + AppRecPtr = CFE_ES_Global.AppTable; + for(i=0; i < CFE_PLATFORM_ES_MAX_APPLICATIONS && + NumResources < CFE_ES_QUERY_ALL_MAX_ENTRIES; ++i) + { + if (CFE_ES_AppRecordIsUsed(AppRecPtr)) + { + ResourceList[NumResources] = CFE_ES_AppRecordGetID(AppRecPtr); + ++NumResources; + } + ++AppRecPtr; + } + LibRecPtr = CFE_ES_Global.LibTable; + for(i=0; i < CFE_PLATFORM_ES_MAX_LIBRARIES && + NumResources < CFE_ES_QUERY_ALL_MAX_ENTRIES; ++i) + { + if (CFE_ES_LibRecordIsUsed(LibRecPtr)) + { + ResourceList[NumResources] = CFE_ES_LibRecordGetID(LibRecPtr); + ++NumResources; + } + ++LibRecPtr; + } + CFE_ES_UnlockSharedData(__func__, __LINE__); + /* ** Check to see if the file already exists */ @@ -1240,21 +1281,13 @@ int32 CFE_ES_QueryAllCmd(const CFE_ES_QueryAll_t *data) /* ** Loop through the ES AppTable for main applications */ - AppRecPtr = CFE_ES_Global.AppTable; - for(i=0;iPayload; char QueryAllFilename[OS_MAX_PATH_LEN]; + CFE_ES_ResourceID_t TaskList[OS_MAX_TASKS]; + uint32 NumTasks; CFE_ES_TaskRecord_t *TaskRecPtr; + /* ** Copy the commanded filename into local buffer to ensure size limitation and to allow for modification */ CFE_SB_MessageStringGet(QueryAllFilename, (char *)CmdPtr->FileName, CFE_PLATFORM_ES_DEFAULT_TASK_LOG_FILE, OS_MAX_PATH_LEN, sizeof(CmdPtr->FileName)); + /* + * Collect list of active task IDs. + * + * This should be done while locked, but the actual writing + * of the AppInfo data should be done while NOT locked. + */ + CFE_ES_LockSharedData(__func__, __LINE__); + NumTasks = 0; + TaskRecPtr = CFE_ES_Global.TaskTable; + for(i=0; i < OS_MAX_TASKS; ++i) + { + if (CFE_ES_TaskRecordIsUsed(TaskRecPtr)) + { + TaskList[NumTasks] = CFE_ES_TaskRecordGetID(TaskRecPtr); + ++NumTasks; + } + ++TaskRecPtr; + } + CFE_ES_UnlockSharedData(__func__, __LINE__); + /* ** Check to see if the file already exists */ @@ -1371,20 +1427,13 @@ int32 CFE_ES_QueryAllTasksCmd(const CFE_ES_QueryAllTasks_t *data) /* ** Loop through the ES AppTable for main applications */ - TaskRecPtr = CFE_ES_Global.TaskTable; - for(i=0;i