第17回 slp_tsk函数功能的介绍

 slp_tsk函数功能的介绍

原文地址:http://www.nces.is.nagoya-u.ac.jp/NEXCESS/blog/index.php?catid=26&blogid=4

首先在μITRON4.0的式样书中,关于slp_tsk()的使用先确认一下.


【C言語API】
ER ercd = slp_tsk();
ER ercd = tslp_tsk(TMO tmout);

【参数】
TMO tmout 时间片终了的指定(只有tslp_tsk才有)

【返回值】
ER ercd 正常終了(E_OK)或者是ErrorCode

【ErrorCode】
E_PAR 参数错误(tmout不正确;只有tslp_tsk才有)
E_RLWAI 等待状态的强制解除(在等待中的时候rel_wai函数的返回值)
E_TMOUT 轮询失败或者超时(只有tslp_tsk才有)


【機能】
使本任务进入到唤醒等待状态. 但是相对于本任务进入到了排队状态时的场合,具体来说就是任务的唤醒要求队列的个数如果是1以上的情况下,那么从唤醒要求队列中数量减去1,本任务不进入任务等待状态,而就这样继续实行.tslp_tsk是在函数slp_tsk的基础上加上业务调用的函数. 参数tmout里面,不但能够设定正确的时间片终了的时间,还可以设定参数为:TMO_POL(=0)と,TMO_FEVR(=-1).


【補足説明】
关于这个函数的调用,在本任务进入到了排队状态时,本任务并不进入到等待状态,因此本任务的优先级是不会变的.也没有被准备slp_tsk函数里面轮询处理后的调用.

接下来我们来看看slp_tsk()函数的代码把

/kernel/task_sync.c

57 ER
58 slp_tsk(void)
59 {
60     WINFO   winfo;  
61     ER      ercd;
62 
63     LOG_SLP_TSK_ENTER();
64     CHECK_DISPATCH(); 
65 
66     t_lock_cpu();
67     if (p_runtsk->wupque) {  
68         p_runtsk->wupque = FALSE; 
69         ercd = E_OK;
70     }
71     else {
72         p_runtsk->tstat = (TS_WAITING | TS_WAIT_SLP);  
73         make_wait(&winfo); 
74         LOG_TSKSTAT(p_runtsk);
75         dispatch(); 
76         ercd = winfo.wercd;
77     }
78     t_unlock_cpu();
79 
80   error_exit:
81     LOG_SLP_TSK_LEAVE(ercd);
82     return(ercd);
83 }


【図17-2】是slp_tsk函数的処理概要.



【図17-2 slp_tsk的概要】
第60行:winfo(等待情报管理区域)作为本地变量在定义.函数的本地变量在着个函数被调用的时候在任务的栈内存中保存,直到函数终了为止.因此winfo的信息所对应的内存都在slp_tsk函数调用的时候得到了确保.上几章已经对winfo的结构进行了剖析,因为winfo只有在等待状态下才会用到的结构体,所以在设计的时候已经从TCB中分离了开来,像这样如果在不进入等待状态的情况下,也就不用去保证winfo的内容,在一定的程度上控制了RAM的大小.在这里只是确保了内存的申请,还没有和TCB进行连接.

第67行:当前的任务在唤醒等待队列中如果是TRUE的场合,也就是在排队的时候,

第68行:当前的任务在唤醒等待队列中如果是FALSE的场合,当前的任务继续保持执行状态

第69行:无法进入等待状态的情况下,只有在这里返回一个E_OK.

第71行:当前的任务没有进入到唤醒等待队列中排队的场合.

第72行:当前任务的TCB的tstat设置为唤醒状态,唤醒等待状态包括:任务等待状态(TS_WAITING)和(TS_WAIT_SLP)两个定义中的一个得到满足的情况下.(具体看16章)

第73行:调用make_wait()函数,具体在之后说明.

第75行:现在正在执行的任务进入到了唤醒等待状态的缘故,一定要调用dispatch这个操作.在这里调用了dispatch操作.

第76行:这个处理相对于唤醒等待状态的任务来说,是在dispatch函数调用以后被执行.wup_tsk函数的处理中,当前任务的winfo的wercd成员变量中加入了E_OK返回结果.在这里是把这个值作为ErrorCode来管理.

详细的例子请看下面


  

在初始化以后,优先度高的任务A在执行状态,任务B在执行可能的状态中. 在任务A中调用slp_tsk这个函数,slp_tsk函数的处理中,一旦75行的dispatch调用后,任务B就进入了执行状态.在任务B这边,wup_tsk(TASKA)调用后,在wup_tsk() 函数里面,把任务A的winfoのwercd设定为E_OK.  之后也调用dispatch函数,再让任务A回到执行状态.在这个时候,在任务A中的slp_tsk函数中的76行下面的代码继续运行. 在这里,使用了刚刚在wup_tsk函数中设定的wercd值.(【図17-3】)



【図17-3 ErrorCode设定的时间点】
为什么向winfo.wercd里面登陆的Error在slp_tsk側没有执行,而在wup_tsk側执行了呢. 唤醒等待的任务有等待解除的可能性,tslp_tsk调用后除去TimeOut情况下还有两种情况, 分别是wup_tsk被调用或者rel_wai函数被调用.(【図17-4】)



【図17-4 唤醒等待解除的业务调用】

※rel_wai(等待状态的强制解除)业务调用的概要

ER ercd = rel_wai(ID tskid)

通过tskid而指定的任务在等待状态的场合,就强制的把等待状态解除.也就是在对象任务等待状态的时候,向执行可能状态迁移.或者在双重等待的状态下向强制等待状态迁移.

换句话说就是在slp_tsk的第76行,不光是调用wup_tsk函数,函数rel_wai被调用的可能性也是有的.因此到底会调用哪个函数而进入到执行状态呢,为了区别这个,在wup_tsk的返回值中设定为E_OK,在rel_wai的返回值中设定为E_RLWAI,这也就是为什么不在slp_tsk中设定ErrorCode的原因.
接下来我们来看看make_wait()的结构.make_wait()是在函数slp_tsk的第73行被调用. 调用了这个函数以后,就进入到了等待状态了.
/kernel/wait.h

81 Inline void
82 make_wait(WINFO *p_winfo)
83 {
84     (void) make_non_runnable(p_runtsk); 
85     p_runtsk->p_winfo = p_winfo; 
86     p_winfo->p_tmevtb = NULL;
87 }


第84行:调用了make_non_runnable()函数.make_non_runnable()函数的作用是把在等待队列的任务从结构体TCB中取出来.然后更新p_schedtsk的内容,是否需要dispatch则根据返回值来决定.(这个已经在第十三章中得到了讲解). 但是这次是当前正在执行中的任务调用了slp_tsk函数,从而进入到了唤醒等待状态,所以在这种情况下dispatch是充分必要的. 因此在这里就不用判断函数make_non_runnable()的返回值了(在这里把返回值强制转化为了void).
85行目:winfo和TCB在这里连接.図17-5 ①)
86行目:因为没有TimeOut, 在这里把winfo结构体中的p_tmevtb设定为NULL.(図17-5 ②)



【図17-5 make_wait概要】
在前面已经学习过了,WINFO的构造让我们再来复习一下.

/kernel/task.h

157 typedef union waiting_information {
158 ER wercd; /* 待ち解除時のエラーコード */
159 TMEVTB *p_tmevtb; /* 待ち状態用のタイムイベントブロック */
160 } WINFO;


在这个结构体中,保存了每个进入等待状态的任务的各种管理情报.在这个结构体中保存的管理信息有:等待解除时的ErrorCode(wercd)和等待状态用的指向时间事件区域的指针(p_tmevtb). 因为在成员变量wercd中加入了等待解除后的ErrorCode,所以这块空间只有在等待解除以后才可能需要用到. 与此对应的p_tmevtb指针所指向的内容在等待解除以后就不用了,所以在WINFO中定义了两个联合体,通过这样来控制RAM的使用量. 在make_wait函数的第86行,这个结构体的指针p_tmevtb这个里面,保存了指向时间事件区域的指针.这次因为没有TimeOut,时间事件区域(TMEVTB)就不使用而定义为了NULL. 像这样把TMEVTB的结构从WINFO结构中分开来,像在slp_tsk这种不用TimeOut的时候是可以有效控制RAM的使用量的. 在RTOS中,为了控制RAM的容量,在代码中像这样做了很多的优化处理.

在下一章,我们将看到在时间片终了的情况下是如何调用tslp_tsk函数的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值