mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-08-06 15:15:15 +08:00
feat(freertos): add feature to modify task stack deepth dynamically
This commit is contained in:
@ -5221,4 +5221,114 @@ when performing module tests). */
|
||||
|
||||
#endif
|
||||
|
||||
#if( configENABLE_TASK_MODIFY_STACK_DEPTH == 1 )
|
||||
|
||||
#if( INCLUDE_xTimerPendFunctionCall != 1 || configUSE_TIMERS != 1)
|
||||
#error "INCLUDE_xTimerPendFunctionCall and configUSE_TIMERS should be enable"
|
||||
#endif
|
||||
|
||||
#include "semphr.h"
|
||||
|
||||
struct prvTaskModifyParam {
|
||||
TCB_t *pxTCB;
|
||||
uint32_t newStackDepth;
|
||||
SemaphoreHandle_t sem;
|
||||
BaseType_t uxResult;
|
||||
};
|
||||
|
||||
static void prvTaskModifyStackDepth(void *param, uint32_t null_val)
|
||||
{
|
||||
struct prvTaskModifyParam *pTaskModifyParam = (struct prvTaskModifyParam *)param;
|
||||
StackType_t *pxStack;
|
||||
UBaseType_t oldStackBytes;
|
||||
TCB_t *pxTCB = (TCB_t *)pTaskModifyParam->pxTCB;
|
||||
UBaseType_t newStackBytes = (size_t)pTaskModifyParam->newStackDepth * sizeof(StackType_t);
|
||||
const UBaseType_t unitSize = sizeof(void *);
|
||||
|
||||
oldStackBytes = (size_t)pxTCB->pxEndOfStack - (size_t)pxTCB->pxTopOfStack + unitSize;
|
||||
if (oldStackBytes >= newStackBytes) {
|
||||
pTaskModifyParam->uxResult = pdFAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pxStack = pvPortMalloc(newStackBytes);
|
||||
if (!pxStack) {
|
||||
pTaskModifyParam->uxResult = pdFAIL;
|
||||
goto exit;
|
||||
}
|
||||
memset(pxStack, tskSTACK_FILL_BYTE, newStackBytes - oldStackBytes);
|
||||
vPortInitContextFromOldStack(&pxStack[newStackBytes - oldStackBytes], (StackType_t *)pxTCB->pxTopOfStack, oldStackBytes);
|
||||
|
||||
vPortFree(pxTCB->pxStack);
|
||||
|
||||
pxTCB->pxStack = pxStack;
|
||||
pxTCB->pxTopOfStack = &pxStack[newStackBytes - oldStackBytes];
|
||||
pxTCB->pxEndOfStack = (StackType_t *)((size_t)pxStack + (size_t)pTaskModifyParam->newStackDepth - unitSize);
|
||||
|
||||
pTaskModifyParam->uxResult = pdPASS;
|
||||
|
||||
exit:
|
||||
if (pTaskModifyParam->sem)
|
||||
xSemaphoreGive(pTaskModifyParam->sem);
|
||||
}
|
||||
|
||||
BaseType_t vTaskModifyStackDepth(TaskHandle_t xTask, const configSTACK_DEPTH_TYPE newStackDepth)
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
if (newStackDepth & 0x3) {
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
if (prvGetTCBFromHandle(xTask) != pxCurrentTCB) {
|
||||
struct prvTaskModifyParam taskModifyParam;
|
||||
|
||||
taskModifyParam.pxTCB = prvGetTCBFromHandle(xTask);
|
||||
taskModifyParam.newStackDepth = newStackDepth;
|
||||
taskModifyParam.sem = NULL;
|
||||
|
||||
vTaskSuspend(xTask);
|
||||
prvTaskModifyStackDepth(&taskModifyParam, 0);
|
||||
xReturn = taskModifyParam.uxResult;
|
||||
vTaskResume(xTask);
|
||||
} else {
|
||||
SemaphoreHandle_t sem;
|
||||
struct prvTaskModifyParam *taskModifyParam;
|
||||
|
||||
if (xTimerGetTimerDaemonTaskHandle() == xTask) {
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
sem = xSemaphoreCreateBinary();
|
||||
if (!sem) {
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
taskModifyParam = pvPortMalloc(sizeof(struct prvTaskModifyParam));
|
||||
if (!taskModifyParam) {
|
||||
vSemaphoreDelete(sem);
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
taskModifyParam->pxTCB = prvGetTCBFromHandle(xTask);
|
||||
taskModifyParam->newStackDepth = newStackDepth;
|
||||
taskModifyParam->sem = sem;
|
||||
|
||||
xReturn = xTimerPendFunctionCall(prvTaskModifyStackDepth, taskModifyParam, 0, portMAX_DELAY);
|
||||
if (xReturn == pdPASS) {
|
||||
xSemaphoreTake(sem, portMAX_DELAY);
|
||||
xReturn = taskModifyParam->uxResult;
|
||||
}
|
||||
|
||||
vSemaphoreDelete(sem);
|
||||
vPortFree(taskModifyParam);
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
#endif /* configENABLE_TASK_MODIFY_STACK_DEPTH == 1 */
|
||||
|
||||
|
@ -146,6 +146,16 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
*/
|
||||
int xPortInIsrContext(void);
|
||||
|
||||
/**
|
||||
* @brief Copy thread context from old thread stack to new thread stack and
|
||||
* then reset the SP.
|
||||
*
|
||||
* @param newStackTop new thread stack pointer
|
||||
* @param oldStackTop old thread stack pointer
|
||||
* @param stackSize stack size
|
||||
*/
|
||||
void vPortInitContextFromOldStack(StackType_t *newStackTop, StackType_t *oldStackTop, UBaseType_t stackSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -2383,6 +2383,16 @@ typedef struct xTASK_SNAPSHOT
|
||||
*/
|
||||
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz );
|
||||
|
||||
/**
|
||||
* @brief Modify task stack size dynamically.
|
||||
*
|
||||
* @param xTask task handle which created by xTaskCreate.
|
||||
* @param newStackDepth task' new stack size.
|
||||
*
|
||||
* @return pdPASS if success or others if failed
|
||||
*/
|
||||
BaseType_t vTaskModifyStackDepth(TaskHandle_t xTask, const configSTACK_DEPTH_TYPE newStackDepth);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -194,5 +194,9 @@ uint32_t esp_get_time(void);
|
||||
#define configENABLE_TASK_SNAPSHOT 1
|
||||
#endif
|
||||
|
||||
#ifndef configENABLE_TASK_MODIFY_STACK_DEPTH
|
||||
#define configENABLE_TASK_MODIFY_STACK_DEPTH 1
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
/* Scheduler includes. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <xtensa/config/core.h>
|
||||
#include <xtensa/tie/xt_interrupt.h>
|
||||
@ -218,6 +219,15 @@ portBASE_TYPE xPortStartScheduler(void)
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
void vPortInitContextFromOldStack(StackType_t *newStackTop, StackType_t *oldStackTop, UBaseType_t stackSize)
|
||||
{
|
||||
uintptr_t *sp;
|
||||
|
||||
memcpy(newStackTop, oldStackTop, stackSize);
|
||||
sp = (uintptr_t *)newStackTop;
|
||||
sp[XT_STK_A1 / sizeof(uintptr_t)] = (uintptr_t)sp + XT_STK_FRMSZ;
|
||||
}
|
||||
|
||||
void vPortEndScheduler(void)
|
||||
{
|
||||
/* It is unlikely that the CM3 port will require this function as there
|
||||
|
113
components/freertos/test/test_freertos_task_modify_stack_depth.c
Normal file
113
components/freertos/test/test_freertos_task_modify_stack_depth.c
Normal file
@ -0,0 +1,113 @@
|
||||
/* FreeRTOS timer tests
|
||||
*/
|
||||
//#define LOG_LOCAL_LEVEL 5
|
||||
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#define TASK_DEPTH_SIZE 8192
|
||||
#define TAG "test_modify_stack_depth"
|
||||
|
||||
static SemaphoreHandle_t s_main_sem, s_sync_sem[3];
|
||||
static TaskHandle_t s_task_handle[3];
|
||||
|
||||
static void test_thread_1(void *p)
|
||||
{
|
||||
for (int i = 0; i < 16; i++) {
|
||||
ESP_LOGD(TAG, "Modify tasks' stack depth to be %u", TASK_DEPTH_SIZE - i * 128);
|
||||
|
||||
vTaskModifyStackDepth(NULL, TASK_DEPTH_SIZE - i * 128);
|
||||
}
|
||||
|
||||
xSemaphoreGive(s_main_sem);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_thread_2(void *p)
|
||||
{
|
||||
for (int i = 0; i < 10; i++) {
|
||||
vTaskPrioritySet(NULL, 5);
|
||||
|
||||
ESP_LOGD(TAG, "Modify tasks' stack depth to be %u", TASK_DEPTH_SIZE - i * 128);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
vTaskModifyStackDepth(s_task_handle[j], TASK_DEPTH_SIZE - i * 128);
|
||||
xSemaphoreGive(s_sync_sem[j]);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Modify successfully");
|
||||
|
||||
vTaskPrioritySet(NULL, 3);
|
||||
}
|
||||
|
||||
xSemaphoreGive(s_main_sem);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_thread_3(void *p)
|
||||
{
|
||||
int count = 10;
|
||||
int num = (int)p;
|
||||
|
||||
while (count--) {
|
||||
TEST_ASSERT(xSemaphoreTake(s_sync_sem[num], portMAX_DELAY) == pdTRUE);
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test task modifies itself's stack depth", "[freertos]")
|
||||
{
|
||||
TEST_ASSERT(s_main_sem = xSemaphoreCreateBinary());
|
||||
|
||||
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_1, "thread_1", TASK_DEPTH_SIZE, NULL, 5, NULL, 0) == pdTRUE);
|
||||
|
||||
TEST_ASSERT(xSemaphoreTake(s_main_sem, portMAX_DELAY) == pdTRUE);
|
||||
|
||||
vQueueDelete(s_main_sem);
|
||||
s_main_sem = NULL;
|
||||
|
||||
vTaskDelay(5);
|
||||
}
|
||||
|
||||
TEST_CASE("Test task modifies other tasks' stack depth", "[freertos]")
|
||||
{
|
||||
ESP_LOGD(TAG, "before heap is %u", esp_get_free_heap_size());
|
||||
|
||||
TEST_ASSERT(s_main_sem = xSemaphoreCreateBinary());
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
TEST_ASSERT(s_sync_sem[i] = xSemaphoreCreateBinary());
|
||||
}
|
||||
|
||||
vTaskSuspendAll();
|
||||
|
||||
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_2, "thread_2", TASK_DEPTH_SIZE, NULL, 5, NULL, 0) == pdTRUE);
|
||||
|
||||
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_4", TASK_DEPTH_SIZE, (void *)0, 4, &s_task_handle[0], 0) == pdTRUE);
|
||||
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_5", TASK_DEPTH_SIZE, (void *)1, 5, &s_task_handle[1], 0) == pdTRUE);
|
||||
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_6", TASK_DEPTH_SIZE, (void *)2, 6, &s_task_handle[2], 0) == pdTRUE);
|
||||
|
||||
xTaskResumeAll();
|
||||
|
||||
TEST_ASSERT(xSemaphoreTake(s_main_sem, portMAX_DELAY) == pdTRUE);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
vQueueDelete(s_sync_sem[i]);
|
||||
s_sync_sem[i] = NULL;
|
||||
}
|
||||
|
||||
vQueueDelete(s_main_sem);
|
||||
s_main_sem = NULL;
|
||||
|
||||
vTaskDelay(5);
|
||||
|
||||
ESP_LOGD(TAG, "after heap is %u", esp_get_free_heap_size());
|
||||
}
|
@ -139,6 +139,12 @@ static void openssl_task(void *p)
|
||||
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
#if configENABLE_TASK_MODIFY_STACK_DEPTH == 1
|
||||
ESP_LOGI(TAG, "Before modification stack depth of this thread, free heap size is %u", esp_get_free_heap_size());
|
||||
vTaskModifyStackDepth(NULL, 2048);
|
||||
ESP_LOGI(TAG, "After modification stack depth of this thread, free heap size is %u", esp_get_free_heap_size());
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "send request to %s port %d ......", OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT);
|
||||
ret = SSL_write(ssl, send_data, send_bytes);
|
||||
|
||||
|
Reference in New Issue
Block a user