OSDN Git Service

ae314c309d127e440cbcabf72807478153ee030c
[trx-305dsp/dsp.git] / trx305 / kernel / kernel / eventflag.c
1 /*
2  *  TOPPERS/JSP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Just Standard Profile Kernel
5  * 
6  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  * 
9  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
10  *  によって公表されている GNU General Public License の Version 2 に記
11  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
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  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
35  * 
36  *  @(#) $Id: eventflag.c,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39 /*
40  *  イベントフラグ機能
41  */
42
43 #include "jsp_kernel.h"
44 #include "check.h"
45 #include "task.h"
46 #include "wait.h"
47 #include "eventflag.h"
48
49 /*
50  *  イベントフラグIDの最大値(kernel_cfg.c)
51  */
52 extern const ID tmax_flgid;
53
54 /*
55  *  イベントフラグ初期化ブロックのエリア(kernel_cfg.c)
56  */
57 extern const FLGINIB    flginib_table[];
58
59 /*
60  *  イベントフラグ管理ブロックのエリア(kernel_cfg.c)
61  */
62 extern FLGCB    flgcb_table[];
63
64 /*
65  *  イベントフラグの数
66  */
67 #define TNUM_FLG    ((UINT)(tmax_flgid - TMIN_FLGID + 1))
68
69 /*
70  *  イベントフラグIDからイベントフラグ管理ブロックを取り出すためのマクロ
71  */
72 #define INDEX_FLG(flgid)    ((UINT)((flgid) - TMIN_FLGID))
73 #define get_flgcb(flgid)    (&(flgcb_table[INDEX_FLG(flgid)]))
74
75 /*
76  *  イベントフラグ待ち情報ブロックの定義
77  *
78  *  flgptn は,waiptn および wfmode と同時に使うことはないため,union 
79  *  を使えばメモリを節約することが可能である.
80  */
81 typedef struct eventflag_waiting_information {
82     WINFO   winfo;      /* 標準の待ち情報ブロック */
83     WOBJCB  *wobjcb;    /* 待ちオブジェクトの管理ブロック */
84     FLGPTN  waiptn;     /* 待ちパターン */
85     MODE    wfmode;     /* 待ちモード */
86     FLGPTN  flgptn;     /* 待ち解除時のパターン */
87 } WINFO_FLG;
88
89 /*
90  *  イベントフラグ機能の初期化
91  */
92 #ifdef __flgini
93
94 void
95 eventflag_initialize(void)
96 {
97     UINT    i;
98     FLGCB   *flgcb;
99
100     for (flgcb = flgcb_table, i = 0; i < TNUM_FLG; flgcb++, i++) {
101         queue_initialize(&(flgcb->wait_queue));
102         flgcb->flginib = &(flginib_table[i]);
103         flgcb->flgptn = flgcb->flginib->iflgptn;
104     }
105 }
106
107 #endif /* __flgini */
108
109 /*
110  *  イベントフラグ待ち解除条件のチェック
111  */
112 #ifdef __flgcnd
113
114 BOOL
115 eventflag_cond(FLGCB *flgcb, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
116 {
117     if ((wfmode & TWF_ORW) != 0 ? (flgcb->flgptn & waiptn) != 0
118                 : (flgcb->flgptn & waiptn) == waiptn) {
119         *p_flgptn = flgcb->flgptn;
120         if ((flgcb->flginib->flgatr & TA_CLR) != 0) {
121             flgcb->flgptn = 0;
122         }
123         return(TRUE);
124     }
125     return(FALSE);
126 }
127
128 #endif /* __flgcnd */
129
130 /*
131  *  イベントフラグのセット
132  */
133 #ifdef __set_flg
134
135 SYSCALL ER
136 set_flg(ID flgid, FLGPTN setptn)
137 {
138     FLGCB   *flgcb;
139     TCB *tcb;
140     WINFO_FLG *winfo;
141     ER  ercd;
142
143     LOG_SET_FLG_ENTER(flgid, setptn);
144     CHECK_TSKCTX_UNL();
145     CHECK_FLGID(flgid);
146     flgcb = get_flgcb(flgid);
147
148     t_lock_cpu();
149     flgcb->flgptn |= setptn;
150     if (!(queue_empty(&(flgcb->wait_queue)))) {
151         tcb = (TCB *)(flgcb->wait_queue.next);
152         winfo = (WINFO_FLG *)(tcb->winfo);
153         if (eventflag_cond(flgcb, winfo->waiptn,
154                     winfo->wfmode, &(winfo->flgptn))) {
155             queue_delete(&(tcb->task_queue));
156             if (wait_complete(tcb)) {
157                 dispatch();
158             }
159         }
160     }
161     ercd = E_OK;
162     t_unlock_cpu();
163
164     exit:
165     LOG_SET_FLG_LEAVE(ercd);
166     return(ercd);
167 }
168
169 #endif /* __set_flg */
170
171 /*
172  *  イベントフラグのセット(非タスクコンテキスト用)
173  */
174 #ifdef __iset_flg
175
176 SYSCALL ER
177 iset_flg(ID flgid, FLGPTN setptn)
178 {
179     FLGCB   *flgcb;
180     TCB *tcb;
181     WINFO_FLG *winfo;
182     ER  ercd;
183
184     LOG_ISET_FLG_ENTER(flgid, setptn);
185     CHECK_INTCTX_UNL();
186     CHECK_FLGID(flgid);
187     flgcb = get_flgcb(flgid);
188
189     i_lock_cpu();
190     flgcb->flgptn |= setptn;
191     if (!(queue_empty(&(flgcb->wait_queue)))) {
192         tcb = (TCB *)(flgcb->wait_queue.next);
193         winfo = (WINFO_FLG *)(tcb->winfo);
194         if (eventflag_cond(flgcb, winfo->waiptn,
195                     winfo->wfmode, &(winfo->flgptn))) {
196             queue_delete(&(tcb->task_queue));
197             if (wait_complete(tcb)) {
198                 reqflg = TRUE;
199             }
200         }
201     }
202     ercd = E_OK;
203     i_unlock_cpu();
204
205     exit:
206     LOG_ISET_FLG_LEAVE(ercd);
207     return(ercd);
208 }
209
210 #endif /* __iset_flg */
211
212 /*
213  *  イベントフラグのクリア
214  */
215 #ifdef __clr_flg
216
217 SYSCALL ER
218 clr_flg(ID flgid, FLGPTN clrptn)
219 {
220     FLGCB   *flgcb;
221     ER  ercd;
222
223     LOG_CLR_FLG_ENTER(flgid, clrptn);
224     CHECK_TSKCTX_UNL();
225     CHECK_FLGID(flgid);
226     flgcb = get_flgcb(flgid);
227
228     t_lock_cpu();
229     flgcb->flgptn &= clrptn; 
230     ercd = E_OK;
231     t_unlock_cpu();
232
233     exit:
234     LOG_CLR_FLG_LEAVE(ercd);
235     return(ercd);
236 }
237
238 #endif /* __clr_flg */
239
240 /*
241  *  イベントフラグ待ち
242  */
243 #ifdef __wai_flg
244
245 SYSCALL ER
246 wai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
247 {
248     FLGCB   *flgcb;
249     WINFO_FLG winfo;
250     ER  ercd;
251
252     LOG_WAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn);
253     CHECK_DISPATCH();
254     CHECK_FLGID(flgid);
255     CHECK_PAR(waiptn != 0);
256     CHECK_PAR((wfmode & ~TWF_ORW) == 0);
257     flgcb = get_flgcb(flgid);
258
259     t_lock_cpu();
260     if (!(queue_empty(&(flgcb->wait_queue)))) {
261         ercd = E_ILUSE;
262     }
263     else if (eventflag_cond(flgcb, waiptn, wfmode, p_flgptn)) {
264         ercd = E_OK;
265     }
266     else {
267         winfo.waiptn = waiptn;
268         winfo.wfmode = wfmode;
269         wobj_make_wait((WOBJCB *) flgcb, (WINFO_WOBJ *) &winfo);
270         dispatch();
271         ercd = winfo.winfo.wercd;
272         if (ercd == E_OK) {
273             *p_flgptn = winfo.flgptn;
274         }
275     }
276     t_unlock_cpu();
277
278     exit:
279     LOG_WAI_FLG_LEAVE(ercd, *p_flgptn);
280     return(ercd);
281 }
282
283 #endif /* __wai_flg */
284
285 /*
286  *  イベントフラグ待ち(ポーリング)
287  */
288 #ifdef __pol_flg
289
290 SYSCALL ER
291 pol_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
292 {
293     FLGCB   *flgcb;
294     ER  ercd;
295
296     LOG_POL_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn);
297     CHECK_TSKCTX_UNL();
298     CHECK_FLGID(flgid);
299     CHECK_PAR(waiptn != 0);
300     CHECK_PAR((wfmode & ~TWF_ORW) == 0);
301     flgcb = get_flgcb(flgid);
302
303     t_lock_cpu();
304     if (!(queue_empty(&(flgcb->wait_queue)))) {
305         ercd = E_ILUSE;
306     }
307     else if (eventflag_cond(flgcb, waiptn, wfmode, p_flgptn)) {
308         ercd = E_OK;
309     }
310     else {
311         ercd = E_TMOUT;
312     }
313     t_unlock_cpu();
314
315     exit:
316     LOG_POL_FLG_LEAVE(ercd, *p_flgptn);
317     return(ercd);
318 }
319
320 #endif /* __pol_flg */
321
322 /*
323  *  イベントフラグ待ち(タイムアウトあり)
324  */
325 #ifdef __twai_flg
326
327 SYSCALL ER
328 twai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn, TMO tmout)
329 {
330     FLGCB   *flgcb;
331     WINFO_FLG winfo;
332     TMEVTB  tmevtb;
333     ER  ercd;
334
335     LOG_TWAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn, tmout);
336     CHECK_DISPATCH();
337     CHECK_FLGID(flgid);
338     CHECK_PAR(waiptn != 0);
339     CHECK_PAR((wfmode & ~TWF_ORW) == 0);
340     CHECK_TMOUT(tmout);
341     flgcb = get_flgcb(flgid);
342
343     t_lock_cpu();
344     if (!(queue_empty(&(flgcb->wait_queue)))) {
345         ercd = E_ILUSE;
346     }
347     else if (eventflag_cond(flgcb, waiptn, wfmode, p_flgptn)) {
348         ercd = E_OK;
349     }
350     else if (tmout == TMO_POL) {
351         ercd = E_TMOUT;
352     }
353     else {
354         winfo.waiptn = waiptn;
355         winfo.wfmode = wfmode;
356         wobj_make_wait_tmout((WOBJCB *) flgcb, (WINFO_WOBJ *) &winfo,
357                         &tmevtb, tmout);
358         dispatch();
359         ercd = winfo.winfo.wercd;
360         if (ercd == E_OK) {
361             *p_flgptn = winfo.flgptn;
362         }
363     }
364     t_unlock_cpu();
365
366     exit:
367     LOG_TWAI_FLG_LEAVE(ercd, *p_flgptn);
368     return(ercd);
369 }
370
371 #endif /* __twai_flg */