OSDN Git Service

First commitment for the BlackTank LPC1769.
[blacktank/blacktank.git] / kernel / extension / mutex / test / bit_mutex.c
1 /*
2  *  TOPPERS/ASP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      High Reliable system Profile Kernel
5  * 
6  *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
7  *              Graduate School of Information Science, Nagoya Univ., JAPAN
8  * 
9  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
10  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14  *      スコード中に含まれていること.
15  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18  *      の無保証規定を掲載すること.
19  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
21  *      と.
22  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
24  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
25  *        報告すること.
26  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
30  *      免責すること.
31  * 
32  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
36  *  の責任を負わない.
37  * 
38  *  @(#) $Id: bit_mutex.c 762 2008-03-07 23:51:41Z hiro $
39  */
40
41 /*
42  *              ミューテックス機能の整合性検査
43  */
44
45 #include "kernel/kernel_impl.h"
46 #include "kernel/task.h"
47 #include "kernel/mutex.h"
48
49 /*
50  *  ミューテックスIDからミューテックス管理ブロックを取り出すためのマク
51  *  ロ(mutex.cより)
52  */
53 #define INDEX_MTX(mtxid)        ((uint_t)((mtxid) - TMIN_MTXID))
54 #define get_mtxcb(mtxid)        (&(mtxcb_table[INDEX_MTX(mtxid)]))
55
56 /*
57  *  ミューテックス管理ブロック中のmutex_queueへのポインタから,ミューテッ
58  *  クス管理ブロックへのポインタを取り出すためのマクロ(mutex.cより)
59  */
60 #define MTXCB_QUEUE(p_queue) \
61                         ((MTXCB *)(((char *) p_queue) - offsetof(MTXCB, mutex_queue)))
62
63 /*
64  *  ミューテックスのプロトコルを判断するマクロ(mutex.cより)
65  */
66 #define MTXPROTO_MASK                   0x03U
67 #define MTXPROTO(p_mtxcb)               ((p_mtxcb)->p_mtxinib->mtxatr & MTXPROTO_MASK)
68 #define MTX_CEILING(p_mtxcb)    (MTXPROTO(p_mtxcb) == TA_CEILING)
69
70 /*
71  *   エラーコードの定義
72  */
73 #define E_SYS_LINENO    ERCD(E_SYS, -(__LINE__))
74
75 /*
76  *  管理ブロックのアドレスの正当性のチェック
77  */
78 #define VALID_TCB(p_tcb) \
79                 ((((char *) p_tcb) - ((char *) tcb_table)) % sizeof(TCB) == 0 \
80                         && TMIN_TSKID <= TSKID(p_tcb) && TSKID(p_tcb) <= tmax_tskid)
81
82 #define VALID_MTXCB(p_mtxcb) \
83                 ((((char *) p_mtxcb) - ((char *) mtxcb_table)) % sizeof(MTXCB) == 0 \
84                         && TMIN_MTXID <= MTXID(p_mtxcb) && MTXID(p_mtxcb) <= tmax_mtxid)
85                                 
86 /*
87  *  キューのチェックのための関数
88  *
89  *  p_queueにp_entryが含まれているかを調べる.含まれていればtrue,含ま
90  *  れていない場合にはfalseを返す.ダブルリンクの不整合の場合にも,
91  *  falseを返す.
92  */
93 static bool_t
94 in_queue(QUEUE *p_queue, QUEUE *p_entry)
95 {
96         QUEUE   *p_current, *p_next;
97
98         p_current = p_queue->p_next;
99         if (p_current->p_prev != p_queue) {
100                 return(false);                                  /* ダブルリンクの不整合 */
101         }
102         while (p_current != p_queue) {
103                 if (p_current == p_entry) {
104                         return(true);                           /* p_entryが含まれていた */
105                 }
106
107                 /*
108                  *  キューの次の要素に進む
109                  */
110                 p_next = p_current->p_next;
111                 if (p_next->p_prev != p_current) {
112                         return(false);                           /* ダブルリンクの不整合 */
113                 }
114                 p_current = p_next;
115         }
116         return(false);
117 }
118
119 /*
120  *  タスク毎の検査
121  */
122 static ER
123 bit_mutex_task(ID tskid)
124 {
125         TCB                     *p_tcb;
126         MTXCB           *p_mtxcb;
127         QUEUE           *p_queue, *p_next;
128         uint_t          priority;
129
130         if (!(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)) {
131                 return(E_ID);
132         }
133         p_tcb = get_tcb(tskid);
134         priority = p_tcb->bpriority;
135
136         /*
137          *  タスクがロックしているミューテックスのキューの検査
138          */
139         p_queue = p_tcb->mutex_queue.p_next;
140         if (p_queue->p_prev != &(p_tcb->mutex_queue)) {
141                 return(E_SYS_LINENO);
142         }
143         while (p_queue != &(p_tcb->mutex_queue)) {
144                 p_mtxcb = MTXCB_QUEUE(p_queue);
145                 if (!VALID_MTXCB(p_mtxcb)) {
146                         return(E_SYS_LINENO);
147                 }
148
149                 /*
150                  *  ミューテックスをロックしているタスクのチェック
151                  */
152                 if (p_mtxcb->p_loctsk != p_tcb) {
153                         return(E_SYS_LINENO);
154                 }
155
156                 /*
157                  *  現在優先度の計算
158                  */
159                 if (MTXPROTO(p_mtxcb)) {
160                         if (p_mtxcb->p_mtxinib->ceilpri < priority) {
161                                 priority = p_mtxcb->p_mtxinib->ceilpri;
162                         }
163                 }
164
165                 /*
166                  *  キューの次の要素に進む
167                  */
168                 p_next = p_queue->p_next;
169                 if (p_next->p_prev != p_queue) {
170                         return(E_SYS_LINENO);
171                 }
172                 p_queue = p_next;
173         }
174
175         /*
176          *  現在優先度の検査
177          */
178         if (p_tcb->priority != p_tcb->priority) {
179                 return(E_SYS_LINENO);
180         }
181
182         /*
183          *  タスクが待っているミューテックスに関する検査
184          */
185         if (TSTAT_WAIT_MTX(p_tcb->tstat)) {
186                 p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb;
187                 if (!VALID_MTXCB(p_mtxcb)) {
188                         return(E_SYS_LINENO);
189                 }
190                 if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) {
191                         return(E_SYS_LINENO);
192                 }
193         }
194         return(E_OK);
195 }
196
197 /*
198  *  ミューテックス毎の検査
199  */
200 static ER
201 bit_mutex_mutex(ID mtxid)
202 {
203         MTXCB           *p_mtxcb;
204         TCB                     *p_tcb;
205         QUEUE           *p_queue, *p_next;
206         uint_t          priority;
207
208         if (!(TMIN_MTXID <= (mtxid) && (mtxid) <= tmax_mtxid)) {
209                 return(E_ID);
210         }
211         p_mtxcb = get_mtxcb(mtxid);
212
213         /*
214          *  初期化ブロックへのポインタの検査
215          */
216         if (p_mtxcb->p_mtxinib != &(mtxinib_table[INDEX_MTX(mtxid)])) {
217                 return(E_SYS_LINENO);
218         }
219
220         /*
221          *  ミューテックス待ちキューの検査
222          */
223         p_queue = p_mtxcb->wait_queue.p_next;
224         if (p_queue->p_prev != &(p_mtxcb->wait_queue)) {
225                 return(E_SYS_LINENO);
226         }
227         priority = TMIN_TPRI;
228         while (p_queue != &(p_mtxcb->wait_queue)) {
229                 p_tcb = (TCB *) p_queue;
230                 if (!VALID_TCB(p_tcb)) {
231                         return(E_SYS_LINENO);
232                 }
233
234                 /*
235                  *  キューがタスク優先度順になっているかの検査
236                  */
237                 if (MTXPROTO(p_mtxcb) != TA_NULL) {
238                         if (p_tcb->priority < priority) {
239                                 return(E_SYS_LINENO);
240                         }
241                 }
242                 priority = p_tcb->priority;
243
244                 /*
245                  *  タスク状態の検査
246                  *
247                  *  ミューテックス待ち状態のタスクの検査は,タスク毎の検査で行っ
248                  *  ているため,ここでは行わない.
249                  */
250                 if (!TSTAT_WAIT_MTX(p_tcb->tstat)) {
251                         return(E_SYS_LINENO);
252                 }
253
254                 /*
255                  *  優先度上限の検査
256                  */
257                 if (MTXPROTO(p_mtxcb) == TA_CEILING) {
258                         if (p_tcb->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
259                                 return(E_SYS_LINENO);
260                         }
261                 }
262
263                 /*
264                  *  キューの次の要素に進む
265                  */
266                 p_next = p_queue->p_next;
267                 if (p_next->p_prev != p_queue) {
268                         return(E_SYS_LINENO);
269                 }
270                 p_queue = p_next;
271         }
272
273         /*
274          *  ミューテックスをロックしているタスクの検査
275          */
276         p_tcb = p_mtxcb->p_loctsk;
277         if (p_tcb == NULL) {
278                 /*
279                  *  ミューテックスがロックされていない時
280                  */
281                 if (!queue_empty(&(p_mtxcb->wait_queue))) {
282                         return(E_SYS_LINENO);
283                 }
284         }
285         else {
286                 /*
287                  *  ミューテックスがロックされている時
288                  *
289                  *  ミューテックスをロックしているタスクの検査は,タスク毎の検
290                  *  査で行っているため,ここでは行わない.
291                  */
292                 if (!VALID_TCB(p_tcb)) {
293                         return(E_SYS_LINENO);
294                 }
295                 if (!in_queue(&(p_tcb->mutex_queue), &(p_mtxcb->mutex_queue))) {
296                         return(E_SYS_LINENO);
297                 }
298
299                 /*
300                  *  優先度上限の検査
301                  */
302                 if (MTXPROTO(p_mtxcb) == TA_CEILING) {
303                         if (p_tcb->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
304                                 return(E_SYS_LINENO);
305                         }
306                 }
307         }
308         return(E_OK);
309 }
310
311 /*
312  *  整合性検査ルーチン本体
313  */
314 ER
315 bit_mutex(void)
316 {
317         ID              tskid, mtxid;
318         ER              ercd;
319
320         /*
321          *  タスク毎の検査
322          */
323         for (tskid = TMIN_TSKID; tskid <= tmax_tskid; tskid++) {
324                 ercd = bit_mutex_task(tskid);
325                 if (ercd != E_OK) {
326                         return(ercd);
327                 }
328         }
329
330         /*
331          *  ミューテックス毎の検査
332          */
333         for (mtxid = TMIN_MTXID; mtxid <= tmax_mtxid; mtxid++) {
334                 ercd = bit_mutex_mutex(mtxid);
335                 if (ercd != E_OK) {
336                         return(ercd);
337                 }
338         }
339         return(E_OK);
340 }