第16回 为了管理任务的等待状态而存在的数据结构

第16回 为了管理任务的等待状态而存在的数据结构

 

概要

在ASP内核的式样里面,整理出了各种不同类型的任务等待状态.(有可能任务等待状态发生的所有系统调用)
a. 唤醒等待状态(slp_tsk)
b. 时钟运行等待状态(dly_tsk)
c. 信号量资源获得等待状态(wai_sem等)
d. 事件标识等待状态(wai_flg等)
e. 向数据队列送信等待状态(snd_dtq等)
f. 从数据队列受信等待状态(rcv_dtq等)
g. 向优先度高的数据队列送信等待状态(snd_pdq等)
h. 从优先度高的数据队列等待受信的状态(rcv_pdq等)
i. 等待邮箱的受到信的状态(rcv_mbx等)
j. 等待获取固定长度内存的状态(get_mpf等)

在这些等待中,a,b的等待类型和c~j是完全不一样的.a,b的等待类型和对象是没有关系的,a,b的等待类型是为了等待状态而单独做成的.因为他们的性质不一样,所以要分开对待.
现在让我们来看看为了管理上面的等待状态而必须需要了解的信息.一共有两大块,一块是任务(TASK)侧的管理信息,一块是对象侧的管理信息.
首先是任务(TASK)侧的管理信息.
A-① 任务(TASK)有等待状态 
A-② 引起任务(TASK)有等待的原因 为什么要等待
A-③ 正在等待中的对象
A-④ 正在等待中的对象的附属信息(根据对象不同分必要的信息和非必要信息)
A-⑤ 当解除等待的时候错误编码返回时候的信息
A-⑥ 时间片运行结束的情报(时间片运行结束的时候,业务调用的场合)

接下来是等待对象侧的管理情报.
B-① 等待状态的任务队列(TASK QUEUE)
B-② 等待对象的状态(信号量的累计值,事件标志(EVENT FLAG)的位类型)
那么就让我们来看看等待状态是如何管理的吧.

A-①任务(TASK)有等待状态 
任务的状态是在TCB中的tstat成员变量中保存的.它没有区分执行状态和执行可能状态这两个状态.执行可能状态的定义是TS_RUNNABLE,休止状态是TS_DORMANT,等待状态的定义是TS_WAITING,强制等待状态的定义是TS_SUSPENDED,如果是双重等待的情况下,就可以用这样的方式来表示了,(TS_WAITING | TS_SUSPENDED).
 
/kernel/task.h
#define TS_DORMANT      0x00U           /* 休止状態 */
#define TS_RUNNABLE     0x01U           /* 実行できる状態 */
#define TS_WAITING      0x02U           /* 待ち状態 */
#define TS_SUSPENDED    0x04U           /* 強制待ち状態 */

接下来关于任务状态是如何判断的,在这里公开说明一下

/kernel/task.h

91 #define TSTAT_DORMANT(tstat)    ((tstat) == TS_DORMANT)
92 #define TSTAT_RUNNABLE(tstat)   (((tstat) & TS_RUNNABLE) != 0U)
93 #define TSTAT_WAITING(tstat)    (((tstat) & TS_WAITING) != 0U)
94 #define TSTAT_SUSPENDED(tstat)  (((tstat) & TS_SUSPENDED) != 0U)


也就是说,为了表示休止状态,执行可能状态,强制等待状态等,分别需要1bit的大小容量来表现..(【図16-1】)


【図16-1 任务(TASK)的各个位功能】

例如,执行可能的状态的时候,tstat的状态就和【図16-2】表示得一样.

【図16-2 执行可能状态下的tstat】
因此现在的任务(TASK)是否是执行可能的状态,可以通过判断TS_RUNNABLE位是否等于1来实现.(92行目)

同样的原理,等待状态的时候就和【図16-3】表示得一样.


【図16-3 等待状态的tstat】
双重等待的场合就和【図16-4】表示得一样


【図16-4 双重等待状态的tstat】
因此,TS_WAITING位如果是1的时候,就是等待状态,也有可能是双重等待状态.因此在第93行的这个宏,就是判断是否是这两个等待状态中的一个.
同样在94行上面的那个宏,也是用来判断是强制等待状态还是双重等待状态.

A-②到达等待状态的要因
到现在为止,任务的休止状态,执行可能状态,等待状态,强制等待状态,二重等待状态各种状态都区分说明完了.这些任务的状态都是在TCB的成员变量tstat中的三个BIT位来表现.
在TCB的成员变量tstat中,剩下的五位BIT中还使用了4位BIT来保存等待状态的时候的等待要因.这四位BIT只有在等待状态(包括双重等待状态)的情况下才使用.


上面所说的ASP内核中的10个等待要因的式样,分别在代码中定义为了下面的宏.
/kernel/task.h
72 #define TS_WAIT_DLY     (0x00U << 3)    /* 時間経過待ち */
73 #define TS_WAIT_SLP     (0x01U << 3)    /* 起床待ち */
74 #define TS_WAIT_RDTQ    (0x02U << 3)    /* データキューからの受信待ち */
75 #define TS_WAIT_RPDQ    (0x03U << 3)    /* 優先度データキューからの受信待ち */
76 #define TS_WAIT_SEM     (0x04U << 3)    /* セマフォ資源の獲得待ち */
77 #define TS_WAIT_FLG     (0x05U << 3)    /* イベントフラグ待ち */
78 #define TS_WAIT_SDTQ    (0x06U << 3)    /* データキューへの送信待ち */
79 #define TS_WAIT_SPDQ    (0x07U << 3)    /* 優先度データキューへの送信待ち */
80 #define TS_WAIT_MBX     (0x08U << 3)    /* メールボックスからの受信待ち */
81 #define TS_WAIT_MPF     (0x09U << 3)    /* 固定長メモリブロックの獲得待ち */

在下面,各种类型的等待要因(也就是TCB的tstat)状态在这里说明.
a. 时钟运行等待状态 TS_WAIT_DLY



b. 唤醒等待状态 TS_WAIT_SLP



c. 从数据队列受信等待状态 TS_WAIT_RDTQ



d.从优先度高的数据队列等待受信的状态 TS_WAIT_RPDQ



e. 信号量资源获得等待状态 TS_WAIT_SEM



f. 事件标志等待状态 TS_WAIT_FLG



g. 向数据队列送信等待状态 TS_WAIT_SDTQ



h. 向优先度高的数据队列送信等待状态 TS_WAIT_SPDQ



i. 等待邮箱的受到信的状态 TS_WAIT_MBX



j. 等待获取固定长度内存的状态 TS_WAIT_MPF

在这里,等待状态的排发顺序是有特别的意义的,这个在以后的章节中说明.

对象在非等待状态下的等待状态的管理方法

在这里说明一下和对象没有联系的场合,也就是关于任务(TASK)单独进入等待状态的管理方法.
在这个状态下有两种情况,如果调用slp_tsk函数就会到唤醒等待状态.如果调用dly_tsk就会到时钟运行等待状态


【図16-5 对象在非等待状态下的等待状态的管理方法】
在TCB的指针p_winfo(指向等待情报区域的指针)中,在管理这个任务的等待情报的结构体WINFO中就保存着等待情报的区域.

【WINFO型】
/kernel/task.h
157 typedef union waiting_information {
158     ER      wercd;          /* 待ち解除時のエラーコード */
159     TMEVTB  *p_tmevtb;      /* 待ち状態用のタイムイベントブロック */
160 } WINFO;
在WINFO(等待情报管理区域)中,插入等待解除时候的Error Code的wercd,时间片运转结束业务呼叫的场合,为了连接时间片结束队列有两个成员变量p_tmevtb和wercd. 这两个变量原本都应该设计到TCB里面去的,但是现在却和WINFO型的结构体中分离了开来.这两个成员变量都是在非等待的场合不必要的成员变量.也就是只有等待状态才需要使用的成员变量.因此才从TCB结构体中分离开来.只有在等待状态下面才确保其内存.所以也极大限度的减少了内存的使用量.再具体一点,就是在等待状态中的系统调用的本地变量中保存着.详细的说明在以后的章节中说明.
还有在时间片结束的时候连接时间事件队列的场合,指向TMEVTB(时间事件队列)的指针通过WINFO中的p_tmevtb来保存. 因为时间事件区域和时间片用完以外的情况下是不需要使用到的区域,所以RAM的使用量也可以得到有效地控制. WINFO的成员变量逐个看了以后,  在wercd中已经放入了等待解除以后的ErrorCode,这块空间只有在等待解除以后才需要用到. 相对于这个, p_tmevtb在等待解除以后就不会被再用到了,因此在WINFO中有这两个成员变量的缘故,RAM的使用量得到了一定的控制.
(→A-⑤为了返回等待解除时的ErrorCode情报,A-⑥关于时间片结束的情報)

相对与同期通信对象的等待状态的管理方法

关于相对与同期通信对象的等待状态的场合,我们在这里介绍一下信号量资源等待状态的管理方法.
首先,在这里说明一下关于相对与同期通信对象的等待状态中必要的并且是通用的结构体. 在同期通信对象等待的时候,是因为哪个对象而引起的等待呢,这个信息是十分必要的.
在刚刚上面所说的WINFO中,有结构体WINFO_WOBJ. 因为需要保存什么对象目前正在等待中,使用成员变量p_wobjcb是十分必要的.
(→A-③等待中的对象)

WINFO和WINFO_WOBJ都一样,都是等待状态任务(TASK)所需要的情报.

【WINFO-WOBJ型】
/kernel/wait.h
218 typedef struct wait_object_waiting_information {
219     WINFO   winfo;          /* 標準の待ち情報ブロック */
220     WOBJCB  *p_wobjcb;      /* 待ちオブジェクトの管理ブロック */
221 } WINFO_WOBJ

在指针p_wobjcb中,保存了指向等待对象的同期通信对象的管理区域. 指针p_wobjcb的类型是WOBJCB,对象等待中任务的队列
(→B-①等待状态的任务队列)和指向对象初始化区域的指针所构成.

【WOBJCB型】
/kernel/wait.h
206 typedef struct wait_object_control_block {
207     QUEUE       wait_queue;     /* 待ちキュー */
208     const WOBJINIB *p_wobjinib; /* 初期化ブロックへのポインタ */
209 } WOBJCB;



【図16-6 同期通信对象等待的管理方法(基本形)】

【図16-6】就是基本的关系图. TMEVTB是每个等待状态的任务的信息.相对的,WOBJCB是每个对象所持有的信息.在【図16-6】中,相对于一个对象来说,看起来一个任务在等待的样子,而其实却有多个任务在等待.(【図16-7】)



【図16-7 每个任务的管理情报和每个对象的管理情报的多重度】
在【図16-7】中,相对与一个对象,就有复数个任务与起关连,也就是说多个任务在等待中的可能性是肯定有的.
【図16-6】是基本图,如果有每个同期通信对象所必须的固定情报的场合,  就是WINFO_WOBJ,WOBJCB的定义了. 接下来我们以信号量为例来说明一下,
 
信号量资源获得等待状态

信号量管理区域(SEMCB)中, 算上同期通信对象的管理区域的基本结构体(WOBJCB),还需要记录信号量的现在使用总数. 这个是信号量对象所特有的信息. WINFO_SEM结构体中存的并不是各个任务(TASK)的管理情报,而是信号量的管理情报.因此代替对象管理情报结构体(WOBJCB)而定义了一个新的结构体(SEMCB).并且为了代替WINFO_OBJ而使用了定义为WINFO_SEM的结构体.
(→B-②等待对象的状态)

【WINFO_SEM型】
/kernel/semaphore.h
85 typedef struct semaphore_waiting_information {
86     WINFO   winfo;          /* 標準の待ち情報ブロック */
87     SEMCB   *p_semcb;       /* 待っているセマフォの管理ブロック */
88 } WINFO_SEM;

【SEMCB型】
/kernel/semaphore.h
72 typedef struct semaphore_control_block {
73     QUEUE       wait_queue;     /* セマフォ待ちキュー */
74     const SEMINIB *p_seminib;   /* 初期化ブロックへのポインタ */
75     uint_t      semcnt;         /* セマフォ現在カウント値 */
76 } SEMCB;



【図16-8 信号量等待状态的管理方法】

根据【図16-8】的构造,在信号量这边目前正在等哪个任务(TASK)这些信息都是记录在SEMCB结构体的wait_queue成员变量中,还有在TCB侧,目前在等待哪个信号量也可以通过这个结构来获得TCB→*p_winfo→p_semcb.
在信号量返回结果,任务的等待状态解除的场合,信号量侧有需要知道等待中的任务的必要性.还有在任务强制终了的场合,因为任务(TASK)有必要从信号量等待的状态中跳出,所以从任务这边(TASK)调用到信号量也是十分必要的.根据上面的构造,从TCB到SEMCB,从SEMCB到TCB的双方向调用都是能够实现的.

事件标记等待状态

在最后,由任务(TASK)侧管理的A-④等待中状态中必要的附属信息做为范例,来说明一下事件标志等待状态.
在事件标志管理区域(FLGCB)中,加上在同期通信对象的管理区域的结构体(WOBJCB),事件标志有记录的目前自身状态的需要. 这些情报包括事件标志对象所特有的信息,还有不是每个任务(TASK)的管理情报,而是事件标志的管理情报.因此作为替代对象管理情报WOBJCB,而定义了FLGCB,并且作为WINFO_OBJ的替代而定义了WINFO_FLG. 到这里为止都是和上面说的信号量是一样的.但是在事件标志的情况下,那个事件标志在对应的任务(TASK)中是如何等待的呢,关于这个问题在每个任务(TASK)中都有专门的管理情报.
关于事件标志,有三种等待类型分别是:对应的事件标志等待,还有等待解除的时候的设定.因此每个任务(TASK)的事件标志等待管理(WINFO_FLG)区域里面,有三个成员分别对应为:waiptn,wfmode,flgptn.
(A-④正在等待对象的附属情报)【図16-9】



【図16-9 事件标记状态的管理方法】

【WINFO_FLG型】
/kernel/eventflag.h
87 typedef struct eventflag_waiting_information {
88     WINFO       winfo;          /* 標準の待ち情報ブロック */
89     FLGCB       *p_flgcb;       /* 待っているイベントフラグの管理ブロック */
90     FLGPTN      waiptn;         /* 待ちパターン */
91     MODE        wfmode;         /* 待ちモード */
92     FLGPTN      flgptn;         /* 待ち解除時のパターン */
93 } WINFO_FLG;

【FLGCB型】
/kernel/eventflag.h
71 typedef struct eventflag_control_block {
72     QUEUE       wait_queue;     /* イベントフラグ待ちキュー */
73     const FLGINIB *p_flginib;   /* 初期化ブロックへのポインタ */
74     FLGPTN      flgptn;         /* イベントフラグ現在パターン */
75 } FLGCB;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值