278 lines
7.2 KiB
C
Executable File
278 lines
7.2 KiB
C
Executable File
#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,
|
|
0);
|
|
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;
|
|
}
|
|
}
|