1.概要
关于任务A和任务B的动作在下面解说.
关于任务A,内核, 任务B的动作,请看下图
【図4-1 各个任务和内核的处理流程】
现在我们来看看相对在任务A中,函数slp_tsk()调用等待后, 任务B中在函数wup_tsk调用,在回去通知任务A之前的内核的处理.也就是上图中标记颜色的部分.这次我们以掌握主要的流程为目的进行学习.
【図4-2 wup_tsk(任务A)发行后内核的处理流程】
2.wup_tsk()函数调用
132 ER
133 wup_tsk(ID tskid)
134 {
135 TCB *p_tcb;
136 ER ercd;
137
138 LOG_WUP_TSK_ENTER(tskid); //ログをとるためのマクロ
139 CHECK_TSKCTX_UNL(); //CPUロック状態でないかどうかをチェック
140 CHECK_TSKID_SELF(tskid); //タスクIDのチェック
141 p_tcb = get_tcb_self(tskid); //TCBへのポインタを取り出す ⇒ ①
142
143 t_lock_cpu(); //CPUロック状態へ ⇒ ②
144 if (TSTAT_DORMANT(p_tcb->tstat)) { //そのタスクが休止状態かどうか ⇒ ③
145 ercd = E_OBJ;
146 }
147 else if (TSTAT_WAIT_SLP(p_tcb->tstat)) { //対象タスクが起床待ち状態かどうか ⇒ ④
148 if (wait_complete(p_tcb)) { //戻り値は,ディスパッチが必要かどうか ⇒ ⑤
149 dispatch(); //ディスパッチを行う関数 ⇒ ⑥
150 }
151 ercd = E_OK;
152 }
153 else if (!(p_tcb->wupque)) {
154 p_tcb->wupque = TRUE;
155 ercd = E_OK;
156 }
157 else {
158 ercd = E_QOVR;
159 }
160 t_unlock_cpu();
161
162 error_exit:
163 LOG_WUP_TSK_LEAVE(ercd);
164 return(ercd);
165 }
在函数wup_tsk()中,对象任务的ID通过参数tskid来传入.
函数wup_tsk()在调用过程中,会把唤醒等待状态的任务变成等待解除状态.如果对象任务是未登陆状态或者休止状态的话,就出现ERROR.这次,对象任务A是在唤醒等待状态,所以让我们来看看唤醒等待状态.
③144行目 在TCB中,根据保存任务的状态的地方(p_tcb->tstat)的值的不同,在这里判断是否解除等待,如果是休止状态的话,就返回ERROR.
3.wait_complete()函数
107 wait_complete(TCB *p_tcb)
108 {
109 wait_dequeue_tmevtb(p_tcb);
110 p_tcb->p_winfo->wercd = E_OK; // ⇒ ①
111 return(make_non_wait(p_tcb)); // ⇒ ②
4.make_non_wait()函数
80 Inline BOOL
81 make_non_wait(TCB *p_tcb)
82 {
83 assert(TSTAT_WAITING(p_tcb->tstat)); //待ち状態もしくは,二重待ち状態か ⇒ ①
84
85 if (!TSTAT_SUSPENDED(p_tcb->tstat)) { //二重待ち状態でなければ(つまり待ち状態)⇒ ②
86 /*
87 * 待ち状態から実行できる状態への遷移
88 */
89 return(make_runnable(p_tcb)); // ⇒ ③
90 }
91 else {
92 /*
93 * 二重待ち状態から強制待ち状態への遷移
94 */
95 p_tcb->tstat = TS_SUSPENDED;
96 LOG_TSKSTAT(p_tcb);
97 return(FALSE);
98 }
99 }
①83行目 在这里确认是等待状态还是双重等待状态
②85行目 确认对象任务A 在单纯的等待状态而非强制等待状态下, 变成执行可能状态.
③89行目 转变成执行可能状态.详细请参照 make_runnable() .
5.make_runnable()
变成执行可能的状态.
232 BOOL
233 make_runnable(TCB *p_tcb)
234 {
235 uint_t pri = p_tcb->priority;
236
237 p_tcb->tstat = TS_RUNNABLE; //対象タスクTCBの現在の状態を「実行できる状態」へ ⇒ ①
238 LOG_TSKSTAT(p_tcb);
239 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
240 primap_set(pri);
241
242 if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) { //⇒ ②
243 p_schedtsk = p_tcb; //⇒ ③
244 return(dspflg); //⇒ ④
245 }
246 return(FALSE);
247 }
重要!
为了妥善管理好任务队列,在等待队列中把拥有最高的优先顺序的任务通过变量:p_schedtsdk来进行管理.
②242行目
1.目前没有执行可能的任务
p_schedtsk == (TCB *) NULL
2.对象任务A的优先度比现在最高优先度的任务还要高的时候
pri < p_schedtsk->priority (优先度值越小越优先)
③243行目 满足条件的时候,使p_schedtsk指向对象任务A.
这次,以函数wup_tsk()为例子,对RTOS中的一小部分的代码完成了解析.想深入学习的还要知道一些对象结构的相关知识.接下来的一章中,我们就来看看SH3结构.
3817



被折叠的 条评论
为什么被折叠?



