Files
ESPC3-wireless/sal/esp32/kernel/os_thread.c

278 lines
7.2 KiB
C
Raw Normal View History

2024-03-28 12:19:52 +08:00
#include "os/os.h"
#include "os_util.h"
#include "task.h"
#include "list/slist.h"
/* Macro used to convert os_priority to the kernel's real priority */
#define OS_KERNEL_PRIO(prio) (prio)
static slist_t s_thread_list;
static void _os_delete(struct os_thread_handle *thread_handle)
{
os_scheduler_suspend();
slist_remove(&s_thread_list, &thread_handle->node);
thread_handle->thread->handle = NULL;
if (thread_handle->flag_free)
{
os_free(thread_handle->thread);
}
os_free(thread_handle);
os_scheduler_resume();
}
static void _os_thread_start(void *arg)
{
struct os_thread_handle *thread_handle = arg;
thread_handle->entry(thread_handle->arg);
_os_delete(thread_handle);
vTaskDelete(NULL);
}
os_state os_thread_init(os_thread_t *thread,
const char *name,
os_thread_entry_t entry,
void *arg,
void *stack_base,
size_t stack_size,
os_priority priority)
{
#if (configSUPPORT_STATIC_ALLOCATION == 1)
OS_ASS_HDL(!os_thread_is_valid(thread), thread->handle);
if (stack_size <= sizeof(struct os_thread_handle) + sizeof(StaticTask_t))
{
OS_ERR("err size: %d <= %d\r\n", stack_size, sizeof(struct os_thread_handle) + sizeof(StaticTask_t));
return OS_FAIL;
}
struct os_thread_handle *thread_handle = stack_base;
StaticTask_t *pxTaskBuffer = (StaticTask_t *)&thread_handle[1];
StackType_t *puxStackBuffer = (StackType_t *)&pxTaskBuffer[1];
thread_handle->thread = thread;
thread_handle->entry = entry;
thread_handle->arg = arg;
thread_handle->flag_free = 0;
thread_handle->pxCreatedTask = xTaskCreateStatic(_os_thread_start,
name,
stack_size / sizeof(StackType_t),
thread_handle,
OS_KERNEL_PRIO(priority),
puxStackBuffer,
pxTaskBuffer);
thread->handle = thread_handle;
return OS_OK;
#else
OS_ERR("err configSUPPORT_STATIC_ALLOCATION != 1\r\n");
return OS_FAIL;
#endif
}
os_state os_thread_create(os_thread_t *thread,
const char *name,
os_thread_entry_t entry,
void *arg,
size_t stack_size,
os_priority priority)
{
int ret;
if (thread)
{
OS_ASS_HDL(!os_thread_is_valid(thread), thread->handle);
}
struct os_thread_handle *thread_handle = os_malloc(sizeof(struct os_thread_handle));
if (thread_handle == NULL)
{
return OS_E_NOMEM;
}
if (thread == NULL)
{
thread = os_malloc(sizeof(os_thread_t));
if (thread == NULL)
{
os_free(thread_handle);
return OS_E_NOMEM;
}
memset(thread, 0, sizeof(os_thread_t));
thread_handle->flag_free = 1;
}
else
{
thread_handle->flag_free = 0;
}
thread->handle = thread_handle;
thread_handle->work_q_list = NULL;
thread_handle->thread = thread;
thread_handle->entry = entry;
thread_handle->arg = arg;
slist_init_node(&thread_handle->node);
os_scheduler_suspend();
slist_insert_tail(&s_thread_list, &thread_handle->node);
os_scheduler_resume();
ret = xTaskCreatePinnedToCore(_os_thread_start,
name,
stack_size / sizeof(StackType_t),
thread_handle,
OS_KERNEL_PRIO(priority),
&thread_handle->pxCreatedTask,
2025-02-13 17:17:07 +08:00
0);
2024-03-28 12:19:52 +08:00
if (ret != pdPASS)
{
OS_ERR("err %d\r\n", ret);
os_scheduler_suspend();
slist_remove(&s_thread_list, &thread_handle->node);
os_scheduler_resume();
if (thread_handle->flag_free == 0)
{
thread->handle = NULL;
}
if (thread_handle->thread)
{
os_free(thread_handle->thread);
}
os_free(thread_handle);
return OS_FAIL;
}
return OS_OK;
}
os_state os_thread_delete(os_thread_t *thread)
{
if (thread == NULL) /* delete self */
{
struct os_thread_handle *thread_handle = os_thread_get_self();
_os_delete(thread_handle);
vTaskDelete(NULL);
return OS_OK;
}
else
{
OS_ASS_HDL(os_thread_is_valid(thread), thread->handle);
struct os_thread_handle *thread_handle = thread->handle;
vTaskDelete(thread_handle->pxCreatedTask);
_os_delete(thread_handle);
return OS_OK;
}
}
void os_thread_sleep(os_time_t msec)
{
vTaskDelay((TickType_t)os_calc_msec_to_ticks(msec));
}
void os_thread_yield(void)
{
taskYIELD();
}
void os_thread_suspend(os_thread_t *thread)
{
if (thread)
{
OS_ASS_HDL(os_thread_is_valid(thread), thread->handle);
struct os_thread_handle *thread_handle = thread->handle;
vTaskSuspend(thread_handle->pxCreatedTask);
}
else
{
vTaskSuspend(NULL);
}
}
void os_thread_resume(os_thread_t *thread)
{
OS_ASS_HDL(os_thread_is_valid(thread), thread->handle);
struct os_thread_handle *thread_handle = thread->handle;
vTaskResume(thread_handle->pxCreatedTask);
}
os_thread_handle_t os_thread_get_self(void)
{
os_thread_handle_t ret = NULL;
os_scheduler_suspend();
TaskHandle_t xTask = xTaskGetCurrentTaskHandle();
struct os_thread_handle *thread_handle;
struct os_thread_handle *prev_handle = NULL;
int cnt = 0;
SLIST_FOR_EACH_CONTAINER(&s_thread_list, thread_handle, node)
{
if (thread_handle->pxCreatedTask == xTask)
{
ret = thread_handle->thread->handle;
break;
}
prev_handle = thread_handle;
cnt++;
}
if (cnt > 5)
{
slist_remove_next(&s_thread_list, &prev_handle->node, &thread_handle->node);
slist_insert_font(&s_thread_list, &thread_handle->node);
}
os_scheduler_resume();
SYS_ASSERT(ret, "xTask: %p", xTask);
return ret;
}
const char *os_thread_get_name(os_thread_t *thread)
{
struct os_thread_handle *thread_handle = thread->handle;
return pcTaskGetName(thread_handle->pxCreatedTask);
}
size_t os_thread_stack_min(os_thread_t *thread)
{
#if INCLUDE_uxTaskGetStackHighWaterMark
TaskHandle_t xTask;
if (thread != NULL)
{
if (os_thread_is_valid(thread))
{
struct os_thread_handle *thread_handle = thread->handle;
xTask = thread_handle->pxCreatedTask;
}
else
{
return 0;
}
}
else
{
xTask = NULL;
}
extern UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask);
return (uxTaskGetStackHighWaterMark(xTask) * sizeof(StackType_t));
#else
return 0;
#endif
}
bool os_thread_is_valid(os_thread_t *thread)
{
if (thread && thread->handle)
{
return true;
}
else
{
return false;
}
}