From 5dc12a7d2ac296ba59a3c3862936697587e67652 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 14 Feb 2024 16:33:13 -0500 Subject: [PATCH] Fix #2516, propagate stack pointer for child tasks Update CFE_ES_CreateChildTask to propagate the user-supplied stack pointer to the underlying OS_TaskCreate call. Also adds a functional test to check that the memory address of a local variable within a child task resides within the expected stack buffer. NOTE: this requires an additional fix to POSIX OSAL to make it work on that platform. --- modules/cfe_testcase/src/es_task_test.c | 70 ++++++++++++++++++++++++- modules/core_api/fsw/inc/cfe_version.h | 10 ++-- modules/es/fsw/src/cfe_es_api.c | 1 + modules/es/fsw/src/cfe_es_apps.c | 14 ++--- modules/es/fsw/src/cfe_es_apps.h | 1 + 5 files changed, 83 insertions(+), 13 deletions(-) diff --git a/modules/cfe_testcase/src/es_task_test.c b/modules/cfe_testcase/src/es_task_test.c index f3ce24171..17bf8a606 100644 --- a/modules/cfe_testcase/src/es_task_test.c +++ b/modules/cfe_testcase/src/es_task_test.c @@ -90,6 +90,66 @@ void TaskExitFunction(void) } } +#define UT_LOCAL_STACK_SIZE 4096 +static unsigned long UT_LOCAL_STACK[UT_LOCAL_STACK_SIZE]; + +void TestCheckStackPointer(void) +{ + int32 LocalVar; + cpuaddr VarAddress; + cpuaddr StackAddress; + + OS_TaskDelay(10); + + VarAddress = (cpuaddr)&LocalVar; + StackAddress = (cpuaddr)UT_LOCAL_STACK; + + UtAssert_GT(cpuaddr, VarAddress, StackAddress); + UtAssert_LT(cpuaddr, VarAddress, StackAddress + sizeof(UT_LOCAL_STACK)); + + CFE_ES_ExitChildTask(); +} + +void TestCreateChildWithStack(void) +{ + CFE_ES_TaskId_t TaskId = CFE_ES_TASKID_UNDEFINED; + int32 RetryCount; + const char * TaskName = "CHILD_W_STACK"; + CFE_ES_StackPointer_t StackPointer = UT_LOCAL_STACK; + size_t StackSize = sizeof(UT_LOCAL_STACK); + CFE_ES_TaskPriority_Atom_t Priority = CFE_PLATFORM_ES_PERF_CHILD_PRIORITY; + uint32 Flags = 0; + char TaskNameBuf[16]; + + UtPrintf("Testing: CFE_ES_CreateChildTask with user-specified stack"); + + UtAssert_INT32_EQ( + CFE_ES_CreateChildTask(&TaskId, TaskName, TestCheckStackPointer, StackPointer, StackSize, Priority, Flags), + CFE_SUCCESS); + + /* wait for task to exit itself */ + RetryCount = 0; + while (RetryCount < 10) + { + /* + * poll until CFE_ES_GetTaskName() returns an error, then the task has exited + * + * NOTE: this intentionally does not Assert the status here, because the child task is + * also doing asserts at the time this loop is running. Once the child task finishes, + * it is OK to do asserts from this task again + */ + if (CFE_Assert_STATUS_STORE(CFE_ES_GetTaskName(TaskNameBuf, TaskId, sizeof(TaskNameBuf))) != CFE_SUCCESS) + { + break; + } + OS_TaskDelay(100); + ++RetryCount; + } + + /* Retroactively confirm that the previous call to CFE_ES_GetTaskName() returned RESOURCEID_NOT_VALID */ + CFE_Assert_STATUS_MUST_BE(CFE_ES_ERR_RESOURCEID_NOT_VALID); +} + void TestCreateChild(void) { UtPrintf("Testing: CFE_ES_CreateChildTask"); @@ -114,7 +174,7 @@ void TestCreateChild(void) while (CFE_FT_Global.Count != ExpectedCount && Index < 100) { OS_TaskDelay(10); - Index ++; + Index++; } UtAssert_INT32_GT(CFE_FT_Global.Count, ExpectedCount - 1); @@ -292,4 +352,12 @@ void ESTaskTestSetup(void) UtTest_Add(TestChildTaskName, NULL, NULL, "Test Child Task Name"); UtTest_Add(TestChildTaskDelete, NULL, NULL, "Test Child Tasks Delete"); UtTest_Add(TestExitChild, NULL, NULL, "Test Exit Child"); + + /* + * NOTE: The custom stack does not work on RTEMS, test is disabled on that platform + * for the time being (custom stack may be deprecated in future CFE release). + */ +#ifndef _RTEMS_OS_ + UtTest_Add(TestCreateChildWithStack, NULL, NULL, "Test Child with Custom Stack"); +#endif } diff --git a/modules/core_api/fsw/inc/cfe_version.h b/modules/core_api/fsw/inc/cfe_version.h index 7c727bc7b..bda7467d3 100644 --- a/modules/core_api/fsw/inc/cfe_version.h +++ b/modules/core_api/fsw/inc/cfe_version.h @@ -29,12 +29,12 @@ #define CFE_BUILD_NUMBER 96 /**< @brief Development: Number of development git commits since CFE_BUILD_BASELINE */ #define CFE_BUILD_BASELINE "equuleus-rc1" /**< @brief Development: Reference git tag for build number */ #define CFE_BUILD_DEV_CYCLE "equuleus-rc2" /**< @brief Development: Release name for current development cycle */ -#define CFE_BUILD_CODENAME "Equuleus" /**< @brief: Development: Code name for the current build */ +#define CFE_BUILD_CODENAME "Equuleus" /**< @brief: Development: Code name for the current build */ /* See \ref cfsversions for definitions */ -#define CFE_MAJOR_VERSION 6 /*!< @brief Major version number */ -#define CFE_MINOR_VERSION 7 /*!< @brief Minor version number */ -#define CFE_REVISION 0 /*!< @brief Revision version number. Value of 0 indicates a development version.*/ +#define CFE_MAJOR_VERSION 6 /*!< @brief Major version number */ +#define CFE_MINOR_VERSION 7 /*!< @brief Minor version number */ +#define CFE_REVISION 0 /*!< @brief Revision version number. Value of 0 indicates a development version.*/ /** * @brief Last official release. @@ -63,7 +63,7 @@ /** * @brief Max Version String length. - * + * * Maximum length that a cFE version string can be. */ #define CFE_CFG_MAX_VERSION_STR_LEN 256 diff --git a/modules/es/fsw/src/cfe_es_api.c b/modules/es/fsw/src/cfe_es_api.c index 6b460ec6b..b625f520f 100644 --- a/modules/es/fsw/src/cfe_es_api.c +++ b/modules/es/fsw/src/cfe_es_api.c @@ -1259,6 +1259,7 @@ CFE_Status_t CFE_ES_CreateChildTask(CFE_ES_TaskId_t *TaskIdPtr, const char *Task memset(&Params, 0, sizeof(Params)); Params.Priority = Priority; Params.StackSize = StackSize; + Params.StackPtr = StackPtr; /* ** Validate some of the arguments diff --git a/modules/es/fsw/src/cfe_es_apps.c b/modules/es/fsw/src/cfe_es_apps.c index 56323d24f..098510136 100644 --- a/modules/es/fsw/src/cfe_es_apps.c +++ b/modules/es/fsw/src/cfe_es_apps.c @@ -585,13 +585,13 @@ int32 CFE_ES_StartAppTask(CFE_ES_TaskId_t *TaskIdPtr, const char *TaskName, CFE_ /* * Create the primary task for the newly loaded task */ - OsStatus = OS_TaskCreate(&OsalTaskId, /* task id */ - TaskName, /* task name matches app name for main task */ - CFE_ES_TaskEntryPoint, /* task function pointer */ - OSAL_TASK_STACK_ALLOCATE, /* stack pointer (allocate) */ - Params->StackSize, /* stack size */ - Params->Priority, /* task priority */ - OS_FP_ENABLED); /* task options */ + OsStatus = OS_TaskCreate(&OsalTaskId, /* task id */ + TaskName, /* task name matches app name for main task */ + CFE_ES_TaskEntryPoint, /* task function pointer */ + Params->StackPtr, /* stack pointer (allocate if NULL) */ + Params->StackSize, /* stack size */ + Params->Priority, /* task priority */ + OS_FP_ENABLED); /* task options */ CFE_ES_LockSharedData(__func__, __LINE__); diff --git a/modules/es/fsw/src/cfe_es_apps.h b/modules/es/fsw/src/cfe_es_apps.h index 8a4092eab..8a8c979af 100644 --- a/modules/es/fsw/src/cfe_es_apps.h +++ b/modules/es/fsw/src/cfe_es_apps.h @@ -99,6 +99,7 @@ typedef struct typedef struct { size_t StackSize; + CFE_ES_StackPointer_t StackPtr; CFE_ES_TaskPriority_Atom_t Priority; } CFE_ES_TaskStartParams_t;