From b04f2b16b2eeabe3b24ed0a7537e9f27acc43f33 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 | 62 +++++++++++++++++++++++++ modules/es/fsw/src/cfe_es_api.c | 1 + modules/es/fsw/src/cfe_es_apps.c | 2 +- modules/es/fsw/src/cfe_es_apps.h | 1 + 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/modules/cfe_testcase/src/es_task_test.c b/modules/cfe_testcase/src/es_task_test.c index f3ce24171..cad3312f0 100644 --- a/modules/cfe_testcase/src/es_task_test.c +++ b/modules/cfe_testcase/src/es_task_test.c @@ -90,6 +90,67 @@ 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"); @@ -292,4 +353,5 @@ 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"); + UtTest_Add(TestCreateChildWithStack, NULL, NULL, "Test Child with Custom Stack"); } 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..ccedf9e05 100644 --- a/modules/es/fsw/src/cfe_es_apps.c +++ b/modules/es/fsw/src/cfe_es_apps.c @@ -588,7 +588,7 @@ int32 CFE_ES_StartAppTask(CFE_ES_TaskId_t *TaskIdPtr, const char *TaskName, CFE_ 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->StackPtr, /* stack pointer (allocate if NULL) */ Params->StackSize, /* stack size */ Params->Priority, /* task priority */ OS_FP_ENABLED); /* task options */ 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;