OSDN Git Service

カーネルのターゲット非依存部1.7.0およびCFGをマージ
[toppersasp4lpc/asp.git] / asp / kernel / mailbox.c
1 /*
2  *  TOPPERS/ASP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Advanced Standard Profile Kernel
5  * 
6  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
9  *              Graduate School of Information Science, Nagoya Univ., JAPAN
10  * 
11  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
12  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32  *      免責すること.
33  * 
34  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38  *  の責任を負わない.
39  * 
40  *  @(#) $Id: mailbox.c 748 2008-03-07 17:18:06Z hiro $
41  */
42
43 /*
44  *              メールボックス機能
45  */
46
47 #include "kernel_impl.h"
48 #include "check.h"
49 #include "task.h"
50 #include "wait.h"
51 #include "mailbox.h"
52
53 /*
54  *  トレースログマクロのデフォルト定義
55  */
56 #ifndef LOG_SND_MBX_ENTER
57 #define LOG_SND_MBX_ENTER(mbxid, pk_msg)
58 #endif /* LOG_SND_MBX_ENTER */
59
60 #ifndef LOG_SND_MBX_LEAVE
61 #define LOG_SND_MBX_LEAVE(ercd)
62 #endif /* LOG_SND_MBX_LEAVE */
63
64 #ifndef LOG_RCV_MBX_ENTER
65 #define LOG_RCV_MBX_ENTER(mbxid, ppk_msg)
66 #endif /* LOG_RCV_MBX_ENTER */
67
68 #ifndef LOG_RCV_MBX_LEAVE
69 #define LOG_RCV_MBX_LEAVE(ercd, pk_msg)
70 #endif /* LOG_RCV_MBX_LEAVE */
71
72 #ifndef LOG_PRCV_MBX_ENTER
73 #define LOG_PRCV_MBX_ENTER(mbxid, ppk_msg)
74 #endif /* LOG_PRCV_MBX_ENTER */
75
76 #ifndef LOG_PRCV_MBX_LEAVE
77 #define LOG_PRCV_MBX_LEAVE(ercd, pk_msg)
78 #endif /* LOG_PRCV_MBX_LEAVE */
79
80 #ifndef LOG_TRCV_MBX_ENTER
81 #define LOG_TRCV_MBX_ENTER(mbxid, ppk_msg, tmout)
82 #endif /* LOG_TRCV_MBX_ENTER */
83
84 #ifndef LOG_TRCV_MBX_LEAVE
85 #define LOG_TRCV_MBX_LEAVE(ercd, pk_msg)
86 #endif /* LOG_TRCV_MBX_LEAVE */
87
88 #ifndef LOG_INI_MBX_ENTER
89 #define LOG_INI_MBX_ENTER(mbxid)
90 #endif /* LOG_INI_MBX_ENTER */
91
92 #ifndef LOG_INI_MBX_LEAVE
93 #define LOG_INI_MBX_LEAVE(ercd)
94 #endif /* LOG_INI_MBX_LEAVE */
95
96 #ifndef LOG_REF_MBX_ENTER
97 #define LOG_REF_MBX_ENTER(mbxid, pk_rmbx)
98 #endif /* LOG_REF_MBX_ENTER */
99
100 #ifndef LOG_REF_MBX_LEAVE
101 #define LOG_REF_MBX_LEAVE(ercd, pk_rmbx)
102 #endif /* LOG_REF_MBX_LEAVE */
103
104 /*
105  *  メールボックスの数
106  */
107 #define tnum_mbx        ((uint_t)(tmax_mbxid - TMIN_MBXID + 1))
108
109 /*
110  *  メールボックスIDからメールボックス管理ブロックを取り出すためのマクロ
111  */
112 #define INDEX_MBX(mbxid)        ((uint_t)((mbxid) - TMIN_MBXID))
113 #define get_mbxcb(mbxid)        (&(mbxcb_table[INDEX_MBX(mbxid)]))
114
115 /* 
116  *  メールボックス機能の初期化
117  */
118 #ifdef TOPPERS_mbxini
119
120 void
121 initialize_mailbox(void)
122 {
123         uint_t  i;
124         MBXCB   *p_mbxcb;
125
126         for (p_mbxcb = mbxcb_table, i = 0; i < tnum_mbx; p_mbxcb++, i++) {
127                 queue_initialize(&(p_mbxcb->wait_queue));
128                 p_mbxcb->p_mbxinib = &(mbxinib_table[i]);
129                 p_mbxcb->pk_head = NULL;
130         }
131 }
132
133 #endif /* TOPPERS_mbxini */
134
135 /*
136  *  メッセージ優先度の取出し
137  */
138 #define MSGPRI(pk_msg)  (((T_MSG_PRI *) pk_msg)->msgpri)
139
140 /*
141  *  優先度順メッセージキューへの挿入
142  */
143 Inline void
144 enqueue_msg_pri(T_MSG **ppk_prevmsg_next, T_MSG *pk_msg)
145 {
146         T_MSG   *pk_nextmsg;
147
148         while ((pk_nextmsg = *ppk_prevmsg_next) != NULL) {
149                 if (MSGPRI(pk_nextmsg) > MSGPRI(pk_msg)) {
150                         break;
151                 }
152                 ppk_prevmsg_next = &(pk_nextmsg->pk_next);
153         }
154         pk_msg->pk_next = pk_nextmsg;
155         *ppk_prevmsg_next = pk_msg;
156 }
157
158 /*
159  *  メールボックスへの送信
160  */
161 #ifdef TOPPERS_snd_mbx
162
163 ER
164 snd_mbx(ID mbxid, T_MSG *pk_msg)
165 {
166         MBXCB   *p_mbxcb;
167         TCB             *p_tcb;
168         ER              ercd;
169     
170         LOG_SND_MBX_ENTER(mbxid, pk_msg);
171         CHECK_TSKCTX_UNL();
172         CHECK_MBXID(mbxid);
173         p_mbxcb = get_mbxcb(mbxid);
174         CHECK_PAR((p_mbxcb->p_mbxinib->mbxatr & TA_MPRI) == 0U
175                                 || (TMIN_MPRI <= MSGPRI(pk_msg)
176                                         && MSGPRI(pk_msg) <= p_mbxcb->p_mbxinib->maxmpri));
177
178         t_lock_cpu();
179         if (!queue_empty(&(p_mbxcb->wait_queue))) {
180                 p_tcb = (TCB *) queue_delete_next(&(p_mbxcb->wait_queue));
181                 ((WINFO_MBX *)(p_tcb->p_winfo))->pk_msg = pk_msg;
182                 if (wait_complete(p_tcb)) {
183                         dispatch();
184                 }
185                 ercd = E_OK;
186         }
187         else if ((p_mbxcb->p_mbxinib->mbxatr & TA_MPRI) != 0U) {
188                 enqueue_msg_pri(&(p_mbxcb->pk_head), pk_msg);
189                 ercd = E_OK;
190         }
191         else {
192                 pk_msg->pk_next = NULL;
193                 if (p_mbxcb->pk_head != NULL) {
194                         p_mbxcb->pk_last->pk_next = pk_msg;
195                 }
196                 else {
197                         p_mbxcb->pk_head = pk_msg;
198                 }
199                 p_mbxcb->pk_last = pk_msg;
200                 ercd = E_OK;
201         }
202         t_unlock_cpu();
203
204   error_exit:
205         LOG_SND_MBX_LEAVE(ercd);
206         return(ercd);
207 }
208
209 #endif /* TOPPERS_snd_mbx */
210
211 /*
212  *  メールボックスからの受信
213  */
214 #ifdef TOPPERS_rcv_mbx
215
216 ER
217 rcv_mbx(ID mbxid, T_MSG **ppk_msg)
218 {
219         MBXCB   *p_mbxcb;
220         WINFO_MBX winfo_mbx;
221         ER              ercd;
222     
223         LOG_RCV_MBX_ENTER(mbxid, ppk_msg);
224         CHECK_DISPATCH();
225         CHECK_MBXID(mbxid);
226         p_mbxcb = get_mbxcb(mbxid);
227     
228         t_lock_cpu();
229         if (p_mbxcb->pk_head != NULL) {
230                 *ppk_msg = p_mbxcb->pk_head;
231                 p_mbxcb->pk_head = (*ppk_msg)->pk_next;
232                 ercd = E_OK;
233         }
234         else {
235                 p_runtsk->tstat = (TS_WAITING | TS_WAIT_MBX);
236                 wobj_make_wait((WOBJCB *) p_mbxcb, (WINFO_WOBJ *) &winfo_mbx);
237                 dispatch();
238                 ercd = winfo_mbx.winfo.wercd;
239                 if (ercd == E_OK) {
240                         *ppk_msg = winfo_mbx.pk_msg;
241                 }
242         }
243         t_unlock_cpu();
244
245   error_exit:
246         LOG_RCV_MBX_LEAVE(ercd, *ppk_msg);
247         return(ercd);
248 }
249
250 #endif /* TOPPERS_rcv_mbx */
251
252 /*
253  *  メールボックスからの受信(ポーリング)
254  */
255 #ifdef TOPPERS_prcv_mbx
256
257 ER
258 prcv_mbx(ID mbxid, T_MSG **ppk_msg)
259 {
260         MBXCB   *p_mbxcb;
261         ER              ercd;
262     
263         LOG_PRCV_MBX_ENTER(mbxid, ppk_msg);
264         CHECK_TSKCTX_UNL();
265         CHECK_MBXID(mbxid);
266         p_mbxcb = get_mbxcb(mbxid);
267     
268         t_lock_cpu();
269         if (p_mbxcb->pk_head != NULL) {
270                 *ppk_msg = p_mbxcb->pk_head;
271                 p_mbxcb->pk_head = (*ppk_msg)->pk_next;
272                 ercd = E_OK;
273         }
274         else {
275                 ercd = E_TMOUT;
276         }
277         t_unlock_cpu();
278
279   error_exit:
280         LOG_PRCV_MBX_LEAVE(ercd, *ppk_msg);
281         return(ercd);
282 }
283
284 #endif /* TOPPERS_prcv_mbx */
285
286 /*
287  *  メールボックスからの受信(タイムアウトあり)
288  */
289 #ifdef TOPPERS_trcv_mbx
290
291 ER
292 trcv_mbx(ID mbxid, T_MSG **ppk_msg, TMO tmout)
293 {
294         MBXCB   *p_mbxcb;
295         WINFO_MBX winfo_mbx;
296         TMEVTB  tmevtb;
297         ER              ercd;
298     
299         LOG_TRCV_MBX_ENTER(mbxid, ppk_msg, tmout);
300         CHECK_DISPATCH();
301         CHECK_MBXID(mbxid);
302         CHECK_TMOUT(tmout);
303         p_mbxcb = get_mbxcb(mbxid);
304     
305         t_lock_cpu();
306         if (p_mbxcb->pk_head != NULL) {
307                 *ppk_msg = p_mbxcb->pk_head;
308                 p_mbxcb->pk_head = (*ppk_msg)->pk_next;
309                 ercd = E_OK;
310         }
311         else if (tmout == TMO_POL) {
312                 ercd = E_TMOUT;
313         }
314         else {
315                 p_runtsk->tstat = (TS_WAITING | TS_WAIT_MBX);
316                 wobj_make_wait_tmout((WOBJCB *) p_mbxcb, (WINFO_WOBJ *) &winfo_mbx,
317                                                                                                                 &tmevtb, tmout);
318                 dispatch();
319                 ercd = winfo_mbx.winfo.wercd;
320                 if (ercd == E_OK) {
321                         *ppk_msg = winfo_mbx.pk_msg;
322                 }
323         }
324         t_unlock_cpu();
325
326   error_exit:
327         LOG_TRCV_MBX_LEAVE(ercd, *ppk_msg);
328         return(ercd);
329 }
330
331 #endif /* TOPPERS_trcv_mbx */
332
333 /*
334  *  メールボックスの再初期化
335  */
336 #ifdef TOPPERS_ini_mbx
337
338 ER
339 ini_mbx(ID mbxid)
340 {
341         MBXCB   *p_mbxcb;
342         bool_t  dspreq;
343         ER              ercd;
344     
345         LOG_INI_MBX_ENTER(mbxid);
346         CHECK_TSKCTX_UNL();
347         CHECK_MBXID(mbxid);
348         p_mbxcb = get_mbxcb(mbxid);
349
350         t_lock_cpu();
351         dspreq = init_wait_queue(&(p_mbxcb->wait_queue));
352         p_mbxcb->pk_head = NULL;
353         if (dspreq) {
354                 dispatch();
355         }
356         ercd = E_OK;
357         t_unlock_cpu();
358
359   error_exit:
360         LOG_INI_MBX_LEAVE(ercd);
361         return(ercd);
362 }
363
364 #endif /* TOPPERS_ini_mbx */
365
366 /*
367  *  メールボックスの状態参照
368  */
369 #ifdef TOPPERS_ref_mbx
370
371 ER
372 ref_mbx(ID mbxid, T_RMBX *pk_rmbx)
373 {
374         MBXCB   *p_mbxcb;
375         ER              ercd;
376     
377         LOG_REF_MBX_ENTER(mbxid, pk_rmbx);
378         CHECK_TSKCTX_UNL();
379         CHECK_MBXID(mbxid);
380         p_mbxcb = get_mbxcb(mbxid);
381
382         t_lock_cpu();
383         pk_rmbx->wtskid = wait_tskid(&(p_mbxcb->wait_queue));
384         pk_rmbx->pk_msg = p_mbxcb->pk_head;
385         ercd = E_OK;
386         t_unlock_cpu();
387
388   error_exit:
389         LOG_REF_MBX_LEAVE(ercd, pk_rmbx);
390         return(ercd);
391 }
392
393 #endif /* TOPPERS_ref_mbx */