Raw-OS源码分析之任务挂起与唤醒

来源:互联网 发布:免费建造师做题软件 编辑:程序博客网 时间:2024/06/07 02:45

        分析的内核版本截止到2014-04-15,基于1.05正式版,blogs会及时跟进最新版本的内核开发进度,若源码注释出现”???”字样,则是未深究理解部分。

        Raw-OS官方网站:http://www.raw-os.org/

        Raw-OS托管地址:https://github.com/jorya/raw-os/


        这节讨论一下Raw-OS中的任务挂起操作的实现,但是系统对于任务挂起操作的情况是很多的,就绪任务可以被挂起,休眠的任务可以被挂起,等待任务可以被挂起,已经被挂起的任务也可以再次被挂起,这里仅仅给出就绪任务被挂起的情况,先看挂起操作的流程:


        就绪任务的挂起:找到任务所属的就绪链表的位置,然后执行list_remove()操作,这个操作在之前讨论过,那么通过list_enrty宏设置任务控制块中的任务指示标志位为suspended状态,从就绪队列删除这个任务信息即可,具体代码:

RAW_U16 raw_task_suspend(RAW_TASK_OBJ *task_ptr){#if (RAW_TASK_FUNCTION_CHECK > 0)/* 检查任务控制块是否为空,为空即任务不存在,无所谓挂不挂起 */if (task_ptr == 0) {return RAW_NULL_OBJECT;}#endif/* 检查任务优先级,这里检查是否是IDEL任务优先级,即IDEL任务不能被挂起??? */if (task_ptr->priority == IDLE_PRIORITY) {return RAW_SUSPEND_TASK_NOT_ALLOWED;}#if (CONFIG_RAW_TASK_0 > 0)/* 检查任务优先级,开启Task 0任务相关宏后,同样task 0不能被挂起??? */if (task_ptr->priority == 0) {return RAW_SUSPEND_TASK_NOT_ALLOWED;}#endif#if (CONFIG_RAW_ZERO_INTERRUPT > 0)/* 开启0中断特性后,任务挂起消息通过task 0转发??? */if (raw_int_nesting) {/* ??? */return int_msg_post(RAW_TYPE_SUSPEND, task_ptr, 0, 0, 0, 0);}#endif/* 挂起任务操作 */return task_suspend(task_ptr);}/* 挂起任务操作 */RAW_U16 task_suspend(RAW_TASK_OBJ *task_ptr){RAW_SR_ALLOC();/* * 这个宏跟是否实现0中断特性有关,按照之前的配置,不实现0中断特性 * 因为没研究过,不好解释,后续分析再不上 * * 不实现0中断特性,这个宏就是简单禁止CPU中断,然后把状态字保存起来 */RAW_CRITICAL_ENTER();/* 如果挂起的是当前系统运行中的任务,必须先给系统解锁,开放系统调度??? */if (task_ptr == raw_task_active) {SYSTEM_LOCK_PROCESS();}/* 读取被挂起任务的任务状态 */switch (task_ptr->task_state) {/* 任务为就绪态时 */case RAW_RDY:/* 任务挂起次数=1 */task_ptr->suspend_count = 1;/* 挂起后,设置任务状态为挂起态 */task_ptr->task_state  =  RAW_SUSPENDED;/* 把就绪任务从就绪队列中删除 */remove_ready_list(&raw_ready_queue, task_ptr);break;/* 任务为休眠状态 */case RAW_DLY:task_ptr->suspend_count = 1;/* 挂起后,变为休眠挂起状态 */task_ptr->task_state  = RAW_DLY_SUSPENDED;break;/* 任务为阻塞状态 */case RAW_PEND:task_ptr->suspend_count = 1;/* 挂起后,设置任务状态为阻塞挂起态 */task_ptr->task_state  = RAW_PEND_SUSPENDED;break;/* 任务为阻塞超时状态 */case RAW_PEND_TIMEOUT:task_ptr->suspend_count = 1;/* 挂起后,设置任务状态为阻塞超时挂起态 */task_ptr->task_state  = RAW_PEND_TIMEOUT_SUSPENDED;break;/* 下面的是已经被挂起的状态,在Raw-OS中允许挂起的任务再一次被挂起 */case RAW_SUSPENDED:case RAW_DLY_SUSPENDED:case RAW_PEND_SUSPENDED:case RAW_PEND_TIMEOUT_SUSPENDED:/* 再次被挂起的任务在挂起嵌套层变量++ */task_ptr->suspend_count++;/* 可以看出允许任务重复挂起249次,谁那么无聊会挂起这么多次??? */if (task_ptr->suspend_count >= 250u) {RAW_CRITICAL_EXIT();return RAW_SUSPENDED_COUNT_OVERFLOWED;}break;default:RAW_CRITICAL_EXIT();return RAW_STATE_UNKNOWN;}RAW_CRITICAL_EXIT();/* 又是trace调试系统??? */TRACE_TASK_SUSPEND(raw_task_active, task_ptr);/* 这里就是系统调度,任务挂起后会马上执行任务调度 */raw_sched();/* 函数没有检查中断嵌套的情况,那么在中断是可以执行任务挂起操作的 */return RAW_SUCCESS;}


        那么对于唤醒一个仅仅是简单挂起状态的任务,就是唤醒任务的逆操作,什么是简单挂起,开始的时候说明过,任务挂起的状态是可以叠加的,休眠的任务可以被挂起,等待任务可以被挂起,已经被挂起的任务也可以再次被挂起,这是我个人理解的非简单挂起,那么对于简单挂起的唤醒操作,流程是这样的:



        唤醒操作,先设置任务TCB里面的任务状态标志为ready,然后通过TCB中的tasklist信息加入到就绪队列的适当位置,至于就绪队列的insert操作,在系统初始化阶段讨论过,可参考之前的blog,那么内核实现的代码是:

RAW_U16 raw_task_resume(RAW_TASK_OBJ *task_ptr){#if (RAW_TASK_FUNCTION_CHECK > 0)/* 检查任务控制块是否为空,为空即任务不存在,无所谓唤不唤醒 */if (task_ptr == 0) {return RAW_NULL_OBJECT;}#endif#if (CONFIG_RAW_ZERO_INTERRUPT > 0)/* 开启0中断特性后,系统处理中断或调度被上锁时,唤醒操作通过task 0 转发??? */if (raw_int_nesting && raw_sched_lock) {return int_msg_post(RAW_TYPE_RESUME, task_ptr, 0, 0, 0, 0);}#endif/* 唤醒任务 */return task_resume(task_ptr);}RAW_U16 task_resume(RAW_TASK_OBJ *task_ptr){/* task 0不实现时,保存CPU状态字,禁止CPU中断 */RAW_SR_ALLOC();RAW_CRITICAL_ENTER();/* 检查被唤醒任务状态 */switch (task_ptr->task_state) {/* 就绪,睡眠,阻塞,阻塞超时状态不是挂起状态,所以无所谓唤不唤醒 */case RAW_RDY:case RAW_DLY:case RAW_PEND:case RAW_PEND_TIMEOUT:/* 使能CPU中断后返回 */RAW_CRITICAL_EXIT();return HAS_NOT_SUSPENDED;/* 如果当前任务为挂起态 */case RAW_SUSPENDED:/* 之前讲过Raw-OS允许任务挂起嵌套的,这里嵌套层数-1 */task_ptr->suspend_count--;/* 当被唤醒任务嵌套挂起计数器=0时,唤醒任务 */if (task_ptr->suspend_count == 0) {/* 更改任务状态为就绪态 */task_ptr->task_state = RAW_RDY;/* 调度到就绪队列,等待系统调度 */add_ready_list(&raw_ready_queue, task_ptr);}break;/* 如果当前任务为休眠挂起态 */case RAW_DLY_SUSPENDED:/* 这里嵌套层数-1 */task_ptr->suspend_count--;if (task_ptr->suspend_count == 0) {/* 更改任务状态为休眠态 */task_ptr->task_state = RAW_DLY;}break;/* 如果当前任务为阻塞挂起态 */case RAW_PEND_SUSPENDED:/* 这里嵌套层数-1 */task_ptr->suspend_count--;if (task_ptr->suspend_count == 0) {/* 更改任务状态为阻塞态 */task_ptr->task_state = RAW_PEND;}break;/* 如果当前任务为阻塞超时挂起态 */case RAW_PEND_TIMEOUT_SUSPENDED:/* 这里嵌套层数-1 */task_ptr->suspend_count--;if (task_ptr->suspend_count == 0) {/* 更改任务状态为阻塞超时态 */task_ptr->task_state = RAW_PEND_TIMEOUT;}break;default:RAW_CRITICAL_EXIT();return RAW_STATE_UNKNOWN;}RAW_CRITICAL_EXIT();/* 又是trace调试系统??? */TRACE_TASK_RESUME(raw_task_active, task_ptr);/* 执行系统调度了,那么任务唤醒操作时会进行系统调度 */raw_sched();return RAW_SUCCESS;}


        那么需要注意的一点是,讨论中是Raw-OS的配置头文件是不涉及CONFIG_RAW_ZERO_INTERRUPT宏和CONFIG_RAW_TASK_0的实现的,以后会另外讨论系统task 0和0中断特性的作用。

1 0
原创粉丝点击