Files
cosyos/System/sv_task.c
零中断延迟的RTOS a8bc5639e0 update System/sv_task.c.
Signed-off-by: 零中断延迟的RTOS <cosyos@139.com>
2025-08-08 11:32:42 +00:00

765 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**************************************************************************//**
* @item CosyOS-III Kernel
* @file sv_task.c
* @brief 任务服务
* @details 仅在任务中调用并执行。
* @author 迟凯峰
* @version V2.0.0
* @date 2025.08.04
******************************************************************************/
#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;
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();
#if (MCUCFG_ISA == __ARM__)
OS_NOP(1);
#endif
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();
#if (MCUCFG_ISA == __ARM__)
OS_NOP(1);
#endif
while(!s_sign_schedule.every[1]);
}
#if (MCUCFG_ISA != __ARM__)
/** 调度上锁(进入嵌套任务临界区)*/
void su_schedule_locks(void)
{
s_sign_schedule.every[0] = true;
s_schedulelock_counter++;
}
/** 内核上锁(进入非嵌套服务层临界区)*/
void su_kernel_lock0(void)
{
mSysIRQ_Disable();
}
/** 内核上锁(进入嵌套服务层临界区)*/
#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] hhand 任务HAND句柄
\param[in] status 任务初始状态
\return 错误码
*/
s_ecode_t su_startup_task(s_taskhand_tsp hhand, s_u8_t status)
{
s_task_status0 = status;
s_task_starter = hhand;
su_kernel_unlock0_psv();
return s_startup_ecode;
}
/**
\brief 恢复指定任务并挂起自身任务
\param[in] htask 任务句柄
\return 错误码
*/
s_ecode_t su_resume_suspend(s_tasknode_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 == __TIMESHARING__)
/**
\brief 禅让任务
\param 无
\return 无
*/
void su_yield_tasking(void)
{
su_kernel_locks();
s_task_current->tc_counter = ~0;
s_sign_schedule.every[1] = false;
su_kernel_unlocks();
}
#endif
/**
\brief 自身任务延时
\param[in] tick 滴答周期(延时时间)<br>
+0非法<br>
~0无限延时
\return 无
*/
void su_delay(s_delay_t tick)
{
s_task_current->timer = tick;
if(!s_sign_schedule.every[0]){ /* 阻塞延时 */
if(~tick) sa_insert_timerlist();
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 滴答周期(超时时间)<br>
+0立即返回<br>
~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();
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_tasknode_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->timer = tick;
s_task_current->handle = hmut;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
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 滴答周期(超时时间)<br>
+0立即返回<br>
~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();
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->timer = tick;
s_task_current->handle = hbin;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
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 滴答周期(超时时间)<br>
+0立即返回<br>
~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();
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->timer = tick;
s_task_current->handle = hbin;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
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 滴答周期(超时时间)<br>
+0立即返回<br>
~0无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_take_semaph(s_semaph_tsp hsem, s_delay_t tick)
{
s_semsize_t counter;
counter = hsem->counter;
if(counter) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist();
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->timer = tick;
s_task_current->handle = hsem;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
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_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 滴答周期(超时时间)<br>
+0立即返回<br>
~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();
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->timer = tick;
s_task_current->handle = htbox;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
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 滴答周期(超时时间)<br>
+0立即返回<br>
~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();
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->timer = tick;
s_task_current->handle = hmbox;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
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 滴答周期(超时时间)<br>
+0立即返回<br>
~0无限等待
\return 消息指针
\retval NULL 失败
*/
void *su_recv_msg(s_msgque_tsp hque, s_delay_t tick)
{
void *msg;
hque->mutex = false;
if(hque->counter) goto __RECV_MSG;
if(!tick) goto __RET_NULL;
hque->mutex = true;
if(~tick) sa_insert_timerlist();
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->timer = tick;
s_task_current->handle = hque;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
hque = (s_msgque_tsp)s_task_current->handle;
#endif
hque->mutex = false;
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);
}
hque->mutex = true;
return _unlock0_rvp_(msg);
__RET_NULL:
hque->mutex = true;
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(volatile void _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 滴答周期(超时时间)<br>
+0立即返回<br>
~0无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_group_1(volatile s_u8_t _STATIC_MEM_ *hgrp, s_delay_t tick)
{
if(*hgrp) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist();
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = 1;
s_task_current->timer = tick;
s_task_current->handle = (void *)hgrp;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
hgrp = (volatile s_u8_t _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 滴答周期(超时时间)<br>
+0立即返回<br>
~0无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_group_2(volatile s_u16_t _STATIC_MEM_ *hgrp, s_delay_t tick)
{
if(*hgrp) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist();
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = 2;
s_task_current->timer = tick;
s_task_current->handle = (void *)hgrp;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
hgrp = (volatile s_u16_t _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 滴答周期(超时时间)<br>
+0立即返回<br>
~0无限等待
\return 结果
\retval false 失败
\retval true 成功
*/
bool su_wait_group_4(volatile s_u32_t _STATIC_MEM_ *hgrp, s_delay_t tick)
{
if(*hgrp) goto __RET_TRUE;
if(!tick) goto __RET_FALSE;
if(~tick) sa_insert_timerlist();
sa_remove_ready(s_task_current);
s_task_current->status = OS_STATUS_BLOCKED;
s_task_current->blocktype = 4;
s_task_current->timer = tick;
s_task_current->handle = (void *)hgrp;
su_kernel_unlock0_psv();
#if (SYSCFG_MCUCORE == 8051)
hgrp = (volatile s_u32_t _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
/** @} */