1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: 18: 19: 20:
21:
22: #include "kernel.h"
23: #include "task.h"
24: #include "wait.h"
25: #include "check.h"
26: #include <sys/rominfo.h>
27:
28: #ifdef NUM_FLGID
29:
30: EXPORT ID max_flgid;
31:
32: 33: 34:
35: typedef struct eventflag_control_block {
36: QUEUE wait_queue;
37: ID flgid;
38: void *exinf;
39: ATR flgatr;
40: UINT flgptn;
41: #if USE_OBJECT_NAME
42: UB name[OBJECT_NAME_LENGTH];
43: #endif
44: } FLGCB;
45:
46: LOCAL FLGCB *flgcb_table;
47: LOCAL QUEUE free_flgcb;
48:
49: #define get_flgcb(id) ( &flgcb_table[INDEX_FLG(id)] )
50:
51:
52: 53: 54:
55: EXPORT ER eventflag_initialize( void )
56: {
57: FLGCB *flgcb, *end;
58: W n;
59:
60:
61: n = _tk_get_cfn(SCTAG_TMAXFLGID, &max_flgid, 1);
62: if ( n < 1 || NUM_FLGID < 1 ) {
63: return E_SYS;
64: }
65:
66:
67: flgcb_table = Imalloc((UINT)NUM_FLGID * sizeof(FLGCB));
68: if ( flgcb_table == NULL ) {
69: return E_NOMEM;
70: }
71:
72:
73: QueInit(&free_flgcb);
74: end = flgcb_table + NUM_FLGID;
75: for ( flgcb = flgcb_table; flgcb < end; flgcb++ ) {
76: flgcb->flgid = 0;
77: QueInsert(&flgcb->wait_queue, &free_flgcb);
78: }
79:
80: return E_OK;
81: }
82:
83: 84: 85:
86: Inline BOOL eventflag_cond( FLGCB *flgcb, UINT waiptn, UINT wfmode )
87: {
88: if ( (wfmode & TWF_ORW) != 0 ) {
89: return ( (flgcb->flgptn & waiptn) != 0 );
90: } else {
91: return ( (flgcb->flgptn & waiptn) == waiptn );
92: }
93: }
94:
95: 96: 97:
98: LOCAL void flg_chg_pri( TCB *tcb, INT oldpri )
99: {
100: FLGCB *flgcb;
101:
102: flgcb = get_flgcb(tcb->wid);
103: gcb_change_priority((GCB*)flgcb, tcb);
104: }
105:
106: 107: 108:
109: LOCAL CONST WSPEC wspec_flg_tfifo = { TTW_FLG, NULL, NULL };
110: LOCAL CONST WSPEC wspec_flg_tpri = { TTW_FLG, flg_chg_pri, NULL };
111:
112:
113: 114: 115:
116: SYSCALL ID _tk_cre_flg( CONST T_CFLG *pk_cflg )
117: {
118: #if CHK_RSATR
119: const ATR VALID_FLGATR = {
120: TA_TPRI
121: |TA_WMUL
122: |TA_NODISWAI
123: #if USE_OBJECT_NAME
124: |TA_DSNAME
125: #endif
126: };
127: #endif
128: FLGCB *flgcb;
129: ID flgid;
130: ER ercd;
131:
132: CHECK_RSATR(pk_cflg->flgatr, VALID_FLGATR);
133:
134: BEGIN_CRITICAL_SECTION;
135:
136: flgcb = (FLGCB*)QueRemoveNext(&free_flgcb);
137: if ( flgcb == NULL ) {
138: ercd = E_LIMIT;
139: } else {
140: flgid = ID_FLG(flgcb - flgcb_table);
141:
142:
143: QueInit(&flgcb->wait_queue);
144: flgcb->flgid = flgid;
145: flgcb->exinf = pk_cflg->exinf;
146: flgcb->flgatr = pk_cflg->flgatr;
147: flgcb->flgptn = pk_cflg->iflgptn;
148: #if USE_OBJECT_NAME
149: if ( (pk_cflg->flgatr & TA_DSNAME) != 0 ) {
150: STRNCPY((char*)flgcb->name, (char*)pk_cflg->dsname,
151: OBJECT_NAME_LENGTH);
152: }
153: #endif
154: ercd = flgid;
155: }
156: END_CRITICAL_SECTION;
157:
158: return ercd;
159: }
160:
161: 162: 163:
164: SYSCALL ER _tk_del_flg( ID flgid )
165: {
166: FLGCB *flgcb;
167: ER ercd = E_OK;
168:
169: CHECK_FLGID(flgid);
170:
171: flgcb = get_flgcb(flgid);
172:
173: BEGIN_CRITICAL_SECTION;
174: if ( flgcb->flgid == 0 ) {
175: ercd = E_NOEXS;
176: } else {
177:
178: wait_delete(&flgcb->wait_queue);
179:
180:
181: QueInsert(&flgcb->wait_queue, &free_flgcb);
182: flgcb->flgid = 0;
183: }
184: END_CRITICAL_SECTION;
185:
186: return ercd;
187: }
188:
189: 190: 191:
192: SYSCALL ER _tk_set_flg( ID flgid, UINT setptn )
193: {
194: FLGCB *flgcb;
195: TCB *tcb;
196: QUEUE *queue;
197: UINT wfmode, waiptn;
198: ER ercd = E_OK;
199:
200: CHECK_FLGID(flgid);
201:
202: flgcb = get_flgcb(flgid);
203:
204: BEGIN_CRITICAL_SECTION;
205: if ( flgcb->flgid == 0 ) {
206: ercd = E_NOEXS;
207: goto error_exit;
208: }
209:
210:
211: flgcb->flgptn |= setptn;
212:
213:
214: queue = flgcb->wait_queue.next;
215: while ( queue != &flgcb->wait_queue ) {
216: tcb = (TCB*)queue;
217: queue = queue->next;
218:
219:
220: waiptn = tcb->winfo.flg.waiptn;
221: wfmode = tcb->winfo.flg.wfmode;
222: if ( eventflag_cond(flgcb, waiptn, wfmode) ) {
223:
224:
225: *tcb->winfo.flg.p_flgptn = flgcb->flgptn;
226: wait_release_ok(tcb);
227:
228:
229: if ( (wfmode & TWF_BITCLR) != 0 ) {
230: if ( (flgcb->flgptn &= ~waiptn) == 0 ) {
231: break;
232: }
233: }
234: if ( (wfmode & TWF_CLR) != 0 ) {
235: flgcb->flgptn = 0;
236: break;
237: }
238: }
239: }
240:
241: error_exit:
242: END_CRITICAL_SECTION;
243:
244: return ercd;
245: }
246:
247: 248: 249:
250: SYSCALL ER _tk_clr_flg( ID flgid, UINT clrptn )
251: {
252: FLGCB *flgcb;
253: ER ercd = E_OK;
254:
255: CHECK_FLGID(flgid);
256:
257: flgcb = get_flgcb(flgid);
258:
259: BEGIN_CRITICAL_SECTION;
260: if ( flgcb->flgid == 0 ) {
261: ercd = E_NOEXS;
262: } else {
263: flgcb->flgptn &= clrptn;
264: }
265: END_CRITICAL_SECTION;
266:
267: return ercd;
268: }
269:
270: 271: 272:
273: SYSCALL ER _tk_wai_flg( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn, TMO tmout )
274: {
275: return _tk_wai_flg_u(flgid, waiptn, wfmode, p_flgptn, to_usec_tmo(tmout));
276: }
277:
278: SYSCALL ER _tk_wai_flg_u( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn, TMO_U tmout )
279: {
280: FLGCB *flgcb;
281: ER ercd = E_OK;
282:
283: CHECK_FLGID(flgid);
284: CHECK_PAR(waiptn != 0);
285: CHECK_PAR((wfmode & ~(TWF_ORW|TWF_CLR|TWF_BITCLR)) == 0);
286: CHECK_TMOUT(tmout);
287: CHECK_DISPATCH();
288:
289: flgcb = get_flgcb(flgid);
290:
291: BEGIN_CRITICAL_SECTION;
292: if ( flgcb->flgid == 0 ) {
293: ercd = E_NOEXS;
294: goto error_exit;
295: }
296: if ( (flgcb->flgatr & TA_WMUL) == 0 && !isQueEmpty(&flgcb->wait_queue) ) {
297:
298: ercd = E_OBJ;
299: goto error_exit;
300: }
301:
302:
303: if ( is_diswai((GCB*)flgcb, ctxtsk, TTW_FLG) ) {
304: ercd = E_DISWAI;
305: goto error_exit;
306: }
307:
308:
309: if ( eventflag_cond(flgcb, waiptn, wfmode) ) {
310: *p_flgptn = flgcb->flgptn;
311:
312:
313: if ( (wfmode & TWF_BITCLR) != 0 ) {
314: flgcb->flgptn &= ~waiptn;
315: }
316: if ( (wfmode & TWF_CLR) != 0 ) {
317: flgcb->flgptn = 0;
318: }
319: } else {
320:
321: ctxtsk->wspec = ( (flgcb->flgatr & TA_TPRI) != 0 )?
322: &wspec_flg_tpri: &wspec_flg_tfifo;
323: ctxtsk->wercd = &ercd;
324: ctxtsk->winfo.flg.waiptn = waiptn;
325: ctxtsk->winfo.flg.wfmode = wfmode;
326: ctxtsk->winfo.flg.p_flgptn = p_flgptn;
327: gcb_make_wait_with_diswai((GCB*)flgcb, tmout);
328: }
329:
330: error_exit:
331: END_CRITICAL_SECTION;
332:
333: return ercd;
334: }
335:
336: 337: 338:
339: SYSCALL ER _tk_ref_flg( ID flgid, T_RFLG *pk_rflg )
340: {
341: FLGCB *flgcb;
342: ER ercd = E_OK;
343:
344: CHECK_FLGID(flgid);
345:
346: flgcb = get_flgcb(flgid);
347:
348: BEGIN_CRITICAL_SECTION;
349: if ( flgcb->flgid == 0 ) {
350: ercd = E_NOEXS;
351: } else {
352: pk_rflg->exinf = flgcb->exinf;
353: pk_rflg->wtsk = wait_tskid(&flgcb->wait_queue);
354: pk_rflg->flgptn = flgcb->flgptn;
355: }
356: END_CRITICAL_SECTION;
357:
358: return ercd;
359: }
360:
361:
362: 363: 364:
365: #if USE_DBGSPT
366:
367: 368: 369:
370: #if USE_OBJECT_NAME
371: EXPORT ER eventflag_getname(ID id, UB **name)
372: {
373: FLGCB *flgcb;
374: ER ercd = E_OK;
375:
376: CHECK_FLGID(id);
377:
378: BEGIN_DISABLE_INTERRUPT;
379: flgcb = get_flgcb(id);
380: if ( flgcb->flgid == 0 ) {
381: ercd = E_NOEXS;
382: goto error_exit;
383: }
384: if ( (flgcb->flgatr & TA_DSNAME) == 0 ) {
385: ercd = E_OBJ;
386: goto error_exit;
387: }
388: *name = flgcb->name;
389:
390: error_exit:
391: END_DISABLE_INTERRUPT;
392:
393: return ercd;
394: }
395: #endif
396:
397: 398: 399:
400: SYSCALL INT _td_lst_flg( ID list[], INT nent )
401: {
402: FLGCB *flgcb, *end;
403: INT n = 0;
404:
405: BEGIN_DISABLE_INTERRUPT;
406: end = flgcb_table + NUM_FLGID;
407: for ( flgcb = flgcb_table; flgcb < end; flgcb++ ) {
408: if ( flgcb->flgid == 0 ) {
409: continue;
410: }
411:
412: if ( n++ < nent ) {
413: *list++ = flgcb->flgid;
414: }
415: }
416: END_DISABLE_INTERRUPT;
417:
418: return n;
419: }
420:
421: 422: 423:
424: SYSCALL ER _td_ref_flg( ID flgid, TD_RFLG *pk_rflg )
425: {
426: FLGCB *flgcb;
427: ER ercd = E_OK;
428:
429: CHECK_FLGID(flgid);
430:
431: flgcb = get_flgcb(flgid);
432:
433: BEGIN_DISABLE_INTERRUPT;
434: if ( flgcb->flgid == 0 ) {
435: ercd = E_NOEXS;
436: } else {
437: pk_rflg->exinf = flgcb->exinf;
438: pk_rflg->wtsk = wait_tskid(&flgcb->wait_queue);
439: pk_rflg->flgptn = flgcb->flgptn;
440: }
441: END_DISABLE_INTERRUPT;
442:
443: return ercd;
444: }
445:
446: 447: 448:
449: SYSCALL INT _td_flg_que( ID flgid, ID list[], INT nent )
450: {
451: FLGCB *flgcb;
452: QUEUE *q;
453: ER ercd = E_OK;
454:
455: CHECK_FLGID(flgid);
456:
457: flgcb = get_flgcb(flgid);
458:
459: BEGIN_DISABLE_INTERRUPT;
460: if ( flgcb->flgid == 0 ) {
461: ercd = E_NOEXS;
462: } else {
463: INT n = 0;
464: for ( q = flgcb->wait_queue.next; q != &flgcb->wait_queue; q = q->next ) {
465: if ( n++ < nent ) {
466: *list++ = ((TCB*)q)->tskid;
467: }
468: }
469: ercd = n;
470: }
471: END_DISABLE_INTERRUPT;
472:
473: return ercd;
474: }
475:
476: #endif
477: #endif