/**************************************************************************//** * @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 /** @} */