/**************************************************************************//**
* @item CosyOS-III Kernel
* @file sv_task.c
* @brief 任务服务
* @details 仅在任务中调用并执行。
* @author 迟凯峰
* @version v3.0.0
* @date 2026.07.21
******************************************************************************/
#include "os_var.h"
#include "os_api.h"
#include "sv_com.h"
#include "sv_task.h"
/**
@addtogroup 任务服务
@{
*/
/** 调度解锁(退出嵌套任务临界区)*/
void su_schedule_unlocks(void)
{
s_schedulelock_counter--;
if(!s_schedulelock_counter){
#if (SYSCFG_KERNELLOCKNESTING == __ENABLED__)
if(!s_sign_schedule.every[1] && !s_kernellock_counter){
#else
if(!s_sign_schedule.every[1]){
#endif
s_sign_schedule.every[0] = false;
__mx_MMB();
mPendSV_Set();
while(!s_sign_schedule.every[1]);
}
else{
s_sign_schedule.every[0] = false;
}
}
}
/** 内核解锁(退出嵌套服务层临界区)*/
void su_kernel_unlocks(void)
{
#if (SYSCFG_KERNELLOCKNESTING == __ENABLED__)
s_kernellock_counter--;
if(s_kernellock_counter) return;
#endif
if(!s_sign_schedule.total){
mPendSV_Set();
mSysIRQ_Enable();
OS_NOP(1);
while(!s_sign_schedule.every[1]);
}
else{
mSysIRQ_Enable();
}
}
/** 内核解锁(退出非嵌套服务层临界区)并触发任务调度 */
void su_kernel_unlock0_psv(void)
{
s_sign_schedule.every[1] = false;
mPendSV_Set();
mSysIRQ_Enable();
OS_NOP(1);
while(!s_sign_schedule.every[1]);
}
#if defined ( __C51__ ) || defined ( __C251__ )
/** 调度上锁(进入嵌套任务临界区)*/
void su_schedule_locks(void)
{
s_sign_schedule.every[0] = true;
__mx_MMB();
s_schedulelock_counter++;
}
/** 内核上锁(进入非嵌套服务层临界区)*/
void su_kernel_lock0(void)
{
mSysIRQ_Disable();
}
/** 内核解锁(退出非嵌套服务层临界区)*//*
void su_kernel_unlock0(void)
{
mSysIRQ_Enable();
}*/
/** 内核上锁(进入嵌套服务层临界区)*/
#if (SYSCFG_KERNELLOCKNESTING == __ENABLED__)
void su_kernel_locks(void)
{
mSysIRQ_Disable();
s_kernellock_counter++;
}
#endif
/** 内核解锁(退出嵌套服务层临界区)并返回(s_ecode_t) */
s_ecode_t su_kernel_unlocks_rec(s_ecode_t e)
{
su_kernel_unlocks();
return e;
}
/** 内核解锁(退出嵌套服务层临界区)并返回(void *) */
void *su_kernel_unlocks_rvp(void *p)
{
su_kernel_unlocks();
return p;
}
#endif
/*
* 操作任务
*/
/**
\brief 启动任务
\param[in] hload 任务装载块句柄
\param[in] status 任务初始状态
\return 错误码
*/
s_ecode_t su_startup_task_0(s_taskload_tsp hload, s_u8_t status)
{
s_task_starter.hload = hload;
s_task_starter.status = status;
s_sign_startup = false;
mPendSV_Set();
mSysIRQ_Enable();
OS_NOP(1);
while(!s_sign_startup);
return s_task_starter._ecode;
}
/**
\brief 启动任务
\param[in] hload 任务装载块句柄
\param[in] status 任务初始状态
\param[in] entry 任务函数入口
\return 错误码
*/
s_ecode_t su_startup_task_1(s_taskload_tsp hload, s_u8_t status, s_voidvoid_tfp entry)
{
hload->entry = entry;
return su_startup_task_0(hload, status);
}
/**
\brief 恢复指定任务并挂起自身任务
\param[in] htask 任务句柄
\return 错误码
*/
s_ecode_t su_resume_suspend(s_taskctrl_tsp htask)
{
s_ecode_t _ecode = sc_resume_task(htask);
if(_ecode == OS_ECODE_NOERROR || htask->status == OS_STATUS_READY){
sa_suspend_task(s_task_current);
return OS_ECODE_NOERROR;
}
else{
return _ecode;
}
}
#if (SYSCFG_SAMEPRISCHEDULE)
/**
\brief 禅让任务
\param 无
\return 无
*/
void su_yield_tasking(void)
{
su_kernel_locks();
#if (SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__)
s_task_current->yield = true;
#elif (SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__)
s_task_current->tc_counter = ~0;
#endif
s_sign_schedule.every[1] = false;
su_kernel_unlocks();
}
#endif
/**
\brief 自身任务延时
\param[in] tick 滴答周期(延时时间)
+0:非法
~0:无限延时
\return 无
*/
void su_delay(s_delay_t tick)
{
if(~tick) sa_insert_timerlist(s_task_current, tick);
if(!s_sign_schedule.every[0]){ /* 阻塞延时 */
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
su_kernel_unlock0_psv();
}
else{ /* 就绪延时 */
s_sign_delay = true;
mSysIRQ_Enable();
while(s_sign_delay);
}
}
/*
* 互斥信号量
*/
#if (SYSCFG_MUTEX == __ENABLED__)
/**
\brief 获取互斥信号量
\param[in] hmut 互斥信号量句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_take_mutex(s_mutex_tsp hmut, s_delay_t tick)
{
if(!hmut->mutex) goto __RET_TRUE1;
if(s_task_current == hmut->otask) goto __RET_TRUE2;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&hmut->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_MUTEX;
if(s_task_current->pri > hmut->otask->pri){
#if (SYSCFG_SAMEPRISCHEDULE)
s_taskctrl_tsp link = hmut->otask;
s_task_current->link = link;
do{
sa_set_taskpri(link, s_task_current->pri);
link = link->link;
}while(link != OS_NULL);
#else
sa_set_taskpri(hmut->otask, s_taskpri_ceiling++);
#endif
}
s_task_current->handle = hmut;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hmut = (s_mutex_tsp)s_task_current->handle;
#endif
if(!hmut->mutex) goto __RET_TRUE1;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE1:
if(hmut->htask != OS_NULL){
sa_float_to_block(hmut->htask);
}
hmut->otask = s_task_current;
hmut->opri = s_task_current->pri;
__RET_TRUE2:
hmut->mutex++;
mSysIRQ_Enable();
return true;
}
/**
\brief 归还互斥信号量
\param[in] hmut 互斥信号量句柄
\return 无
*/
void su_back_mutex(s_mutex_tsp hmut)
{
if(!hmut->mutex);
else if(s_task_current == hmut->otask){
hmut->mutex--;
if(!hmut->mutex){
if(s_task_current->pri > hmut->opri){
sa_set_taskpri(s_task_current, hmut->opri);
#if (!SYSCFG_SAMEPRISCHEDULE)
s_taskpri_ceiling--;
#endif
}
if(hmut->htask != OS_NULL){
sa_block_to_float(hmut->htask);
}
}
}
su_kernel_unlocks();
}
#endif
/*
* 二值信号量
*/
#if (SYSCFG_BINARY == __ENABLED__)
/**
\brief 等待二值信号量
\param[in] hbin 二值信号量句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_binary(s_binary_tsp hbin, s_delay_t tick)
{
if(hbin->binary) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&hbin->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_BINARY;
s_task_current->handle = hbin;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hbin = (s_binary_tsp)s_task_current->handle;
#endif
if(hbin->binary) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
mSysIRQ_Enable();
return true;
}
/**
\brief 获取二值信号量
\param[in] hbin 二值信号量句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_take_binary(s_binary_tsp hbin, s_delay_t tick)
{
if(hbin->binary) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&hbin->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_BINARY;
s_task_current->handle = hbin;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hbin = (s_binary_tsp)s_task_current->handle;
#endif
if(hbin->binary) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
if(hbin->htask != OS_NULL){
sa_float_to_block(hbin->htask);
}
hbin->binary = false;
mSysIRQ_Enable();
return true;
}
#endif
/*
* 计数信号量
*/
#if (SYSCFG_SEMAPHORE == __ENABLED__)
/**
\brief 获取计数信号量
\param[in] hsem 计数信号量句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_take_semaph(s_semaph_tsp hsem, s_delay_t tick)
{
s_semaph_t counter;
counter = hsem->counter;
if(counter) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&hsem->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_SEMAPHORE;
s_task_current->handle = hsem;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hsem = (s_semaph_tsp)s_task_current->handle;
#endif
counter = hsem->counter;
if(counter) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
counter--;
if(!counter && hsem->htask != OS_NULL){
sa_float_to_block(hsem->htask);
}
hsem->counter = counter;
mSysIRQ_Enable();
return true;
}
#endif
/*
* 私信
*/
#if (SYSCFG_TASKMSG == __ENABLED__)
/**
\brief 接收私信
\param[in] tmrf 私信标志
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_recv_taskmsg(s_u8_t volatile _STATIC_MEM_ *tmrf, s_delay_t tick)
{
if(*tmrf) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_TASKMSG;
#if defined ( __C51__ )
s_task_current->handle = (void *)tmrf;
#endif
su_kernel_unlock0_psv();
#if defined ( __C51__ )
tmrf = (s_u8_t volatile _STATIC_MEM_ *)s_task_current->handle;
#endif
if(*tmrf) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
*tmrf = 2;
(*s_task_current->entry)();
mSysIRQ_Enable();
return true;
}
#endif
/*
* 飞信
*/
#if (SYSCFG_FETION == __ENABLED__)
/**
\brief 退出非嵌套服务层临界区并返回飞信
\param[in] htbox 信箱句柄
\return 飞信
*/
__STATIC_FORCEINLINE m_fetion_t _unlock0_rfet_(s_tionbox_tsp htbox)
{
m_fetion_t tion = htbox->tion;
htbox->tion = false;
mSysIRQ_Enable();
return tion;
}
/**
\brief 接收飞信
\param[in] htbox 信箱句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 飞信
\retval false 失败
*/
m_fetion_t su_recv_fetion(s_tionbox_tsp htbox, s_delay_t tick)
{
if(htbox->tion) goto __RET_TION;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&htbox->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_FETION;
s_task_current->handle = htbox;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
htbox = (s_tionbox_tsp)s_task_current->handle;
#endif
__RET_TION:
return _unlock0_rfet_(htbox);
__RET_FALSE:
mSysIRQ_Enable();
return false;
}
#endif
/** 退出非嵌套服务层临界区并返回(void *) */
#if (SYSCFG_MAILBOX == __ENABLED__ || SYSCFG_MSGQUEUE == __ENABLED__)
__STATIC_FORCEINLINE void *_unlock0_rvp_(void *p)
{
mSysIRQ_Enable();
return p;
}
#endif
/*
* 邮箱
*/
#if (SYSCFG_MAILBOX == __ENABLED__)
/**
\brief 接收邮件
\param[in] hmbox 邮箱句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 邮件指针
\retval NULL 失败
*/
void *su_recv_mail(s_mailbox_tsp hmbox, s_delay_t tick)
{
if(hmbox->flag) goto __RET_MAIL;
if(!tick) goto __RET_NULL;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&hmbox->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_MAIL;
s_task_current->handle = hmbox;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hmbox = (s_mailbox_tsp)s_task_current->handle;
#endif
if(hmbox->flag) goto __RET_MAIL;
__RET_NULL:
mSysIRQ_Enable();
return OS_NULL;
__RET_MAIL:
hmbox->flag = false;
return _unlock0_rvp_(hmbox->mail);
}
#endif
/*
* 消息队列
*/
#if (SYSCFG_MSGQUEUE == __ENABLED__)
/**
\brief 接收消息
\param[in] hque 队列句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 消息指针
\retval NULL 失败
*/
void *su_recv_msg(s_msgque_tsp hque, s_delay_t tick)
{
void *msg;
#if (SYSCFG_MSGQUEUE_INTRECV == __ENABLED__)
hque->lock = false;
__mx_MMB();
#endif
if(hque->counter) goto __RECV_MSG;
if(!tick) goto __RET_NULL;
#if (SYSCFG_MSGQUEUE_INTRECV == __ENABLED__)
__mx_MMB();
hque->lock = true;
#endif
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_insert_blocklist(&hque->htask);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = OS_BLOCKED_MSG;
s_task_current->handle = hque;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hque = (s_msgque_tsp)s_task_current->handle;
#endif
#if (SYSCFG_MSGQUEUE_INTRECV == __ENABLED__)
hque->lock = false;
__mx_MMB();
#endif
if(!hque->counter) goto __RET_NULL;
__RECV_MSG:
if(hque->type == __DYNAMIC__){
msg = sc_recv_msg_dynque((s_dynque_tsp)hque);
}
else{
msg = sc_recv_msg_staque((s_staque_tsp)hque);
}
#if (SYSCFG_MSGQUEUE_INTRECV == __ENABLED__)
__mx_MMB();
hque->lock = true;
#endif
return _unlock0_rvp_(msg);
__RET_NULL:
#if (SYSCFG_MSGQUEUE_INTRECV == __ENABLED__)
__mx_MMB();
hque->lock = true;
#endif
mSysIRQ_Enable();
return OS_NULL;
}
#endif
/*
* 事件标志组
*/
#if (SYSCFG_FLAGGROUP == __ENABLED__)
/**
\brief 查询标志组
\param[in] hgrp 标志组句柄
\param[in] size sizeof(group)
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_query_group(void volatile _STATIC_MEM_ *hgrp, s_u8_t size)
{
switch(size){
case 1: if(*(s_u8_t *)hgrp) goto __RET_TRUE; break;
case 2: if(*(s_u16_t *)hgrp) goto __RET_TRUE; break;
case 4: if(*(s_u32_t *)hgrp) goto __RET_TRUE; break;
}
su_kernel_unlocks();
return false;
__RET_TRUE:
su_kernel_unlocks();
return true;
}
/**
\brief 等待标志组_1
\param[in] hgrp 标志组句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_group_1(s_u8_t volatile _STATIC_MEM_ *hgrp, s_delay_t tick)
{
if(*hgrp) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = 1;
s_task_current->handle = (void *)hgrp;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hgrp = (s_u8_t volatile _STATIC_MEM_ *)s_task_current->handle;
#endif
if(*hgrp) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
mSysIRQ_Enable();
return true;
}
/**
\brief 等待标志组_2
\param[in] hgrp 标志组句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_group_2(s_u16_t volatile _STATIC_MEM_ *hgrp, s_delay_t tick)
{
if(*hgrp) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = 2;
s_task_current->handle = (void *)hgrp;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hgrp = (s_u16_t volatile _STATIC_MEM_ *)s_task_current->handle;
#endif
if(*hgrp) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
mSysIRQ_Enable();
return true;
}
/**
\brief 等待标志组_4
\param[in] hgrp 标志组句柄
\param[in] tick 滴答周期(超时时间)
+0:立即返回
~0:无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_group_4(s_u32_t volatile _STATIC_MEM_ *hgrp, s_delay_t tick)
{
if(*hgrp) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist(s_task_current, tick);
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = 4;
s_task_current->handle = (void *)hgrp;
su_kernel_unlock0_psv();
#if defined ( __C51__ )
hgrp = (s_u32_t volatile _STATIC_MEM_ *)s_task_current->handle;
#endif
if(*hgrp) goto __RET_TRUE;
__RET_FALSE:
mSysIRQ_Enable();
return false;
__RET_TRUE:
mSysIRQ_Enable();
return true;
}
#endif
/*
* 动态内存
*/
#if (SYSCFG_DYNMEMMGE == __ENABLED__)
/**
\brief uxalloc
\param[in] p
\return 指针
\retval NULL 失败
*/
void _MALLOC_MEM_ *su_xalloc(void _MALLOC_MEM_ *p)
{
su_kernel_unlocks();
return p;
}
/**
\brief 初始化线程内存池
\param[in] hmem 线程内存句柄
\param[in] size 内存池大小
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_init_mempool(s_thrmem_tsp hmem, size_t size)
{
hmem->head = hmem->move = (void _MALLOC_MEM_ *)s_malloc(size);
if(hmem->head == OS_NULL){
su_kernel_unlocks();
return false;
}
else{
hmem->size = size;
su_kernel_unlocks();
return true;
}
}
/**
\brief 线程内存分配
\param[in] hmem 线程内存句柄
\param[in] size 内存块大小
\return 指针
\retval NULL 失败
*/
void _MALLOC_MEM_ *su_talloc(s_thrmem_tsp hmem, size_t size)
{
if(hmem->head == OS_NULL || (size_t)hmem->move - (size_t)hmem->head + size > hmem->size){
return OS_NULL;
}
else{
void _MALLOC_MEM_ *r = hmem->move;
hmem->move = (s_u8_t _MALLOC_MEM_ *)hmem->move + size;
return r;
}
}
#endif
/** @} */