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_MBFID
29:
30: EXPORT ID max_mbfid;
31:
32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
42: typedef struct messagebuffer_control_block {
43: QUEUE send_queue;
44: ID mbfid;
45: void *exinf;
46: ATR mbfatr;
47: QUEUE recv_queue;
48: INT bufsz;
49: INT maxmsz;
50: INT frbufsz;
51: INT head;
52: INT tail;
53: VB *buffer;
54: #if USE_OBJECT_NAME
55: UB name[OBJECT_NAME_LENGTH];
56: #endif
57: } MBFCB;
58:
59: LOCAL MBFCB *mbfcb_table;
60: LOCAL QUEUE free_mbfcb;
61:
62: #define get_mbfcb(id) ( &mbfcb_table[INDEX_MBF(id)] )
63:
64:
65: 66: 67:
68: EXPORT ER messagebuffer_initialize( void )
69: {
70: MBFCB *mbfcb, *end;
71: W n;
72:
73:
74: n = _tk_get_cfn(SCTAG_TMAXMBFID, &max_mbfid, 1);
75: if ( n < 1 || NUM_MBFID < 1 ) {
76: return E_SYS;
77: }
78:
79:
80: mbfcb_table = Imalloc((UINT)NUM_MBFID * sizeof(MBFCB));
81: if ( mbfcb_table == NULL ) {
82: return E_NOMEM;
83: }
84:
85:
86: QueInit(&free_mbfcb);
87: end = mbfcb_table + NUM_MBFID;
88: for ( mbfcb = mbfcb_table; mbfcb < end; mbfcb++ ) {
89: mbfcb->mbfid = 0;
90: QueInsert(&mbfcb->send_queue, &free_mbfcb);
91: }
92:
93: return E_OK;
94: }
95:
96:
97:
98: 99: 100:
101: typedef INT HEADER;
102: #define HEADERSZ (sizeof(HEADER))
103:
104: #define ROUNDSIZE (sizeof(HEADER))
105: #define ROUNDSZ(sz) (((UINT)(sz) + (ROUNDSIZE-1)) & ~(ROUNDSIZE-1))
106:
107: 108: 109: 110:
111: Inline BOOL mbf_free( MBFCB *mbfcb, INT msgsz )
112: {
113: return ( HEADERSZ + (UINT)msgsz <= (UINT)mbfcb->frbufsz );
114: }
115:
116: 117: 118:
119: Inline BOOL mbf_empty( MBFCB *mbfcb )
120: {
121: return ( mbfcb->frbufsz == mbfcb->bufsz );
122: }
123:
124: 125: 126:
127: LOCAL void msg_to_mbf( MBFCB *mbfcb, CONST void *msg, INT msgsz )
128: {
129: INT tail = mbfcb->tail;
130: VB *buffer = mbfcb->buffer;
131: INT remsz;
132:
133: mbfcb->frbufsz -= (INT)(HEADERSZ + ROUNDSZ(msgsz));
134:
135: *(HEADER*)&buffer[tail] = msgsz;
136: tail += HEADERSZ;
137: if ( tail >= mbfcb->bufsz ) {
138: tail = 0;
139: }
140:
141: if ( (remsz = mbfcb->bufsz - tail) < msgsz ) {
142: MEMCPY(&buffer[tail], msg, (UINT)remsz);
143: msg = (VB*)msg + remsz;
144: msgsz -= remsz;
145: tail = 0;
146: }
147: MEMCPY(&buffer[tail], msg, (UINT)msgsz);
148: tail += (INT)ROUNDSZ(msgsz);
149: if ( tail >= mbfcb->bufsz ) {
150: tail = 0;
151: }
152:
153: mbfcb->tail = tail;
154: }
155:
156: 157: 158: 159:
160: LOCAL INT mbf_to_msg( MBFCB *mbfcb, void *msg )
161: {
162: INT head = mbfcb->head;
163: VB *buffer = mbfcb->buffer;
164: INT msgsz, actsz;
165: INT remsz;
166:
167: actsz = msgsz = *(HEADER*)&buffer[head];
168: mbfcb->frbufsz += (INT)(HEADERSZ + ROUNDSZ(msgsz));
169:
170: head += (INT)HEADERSZ;
171: if ( head >= mbfcb->bufsz ) {
172: head = 0;
173: }
174:
175: if ( (remsz = mbfcb->bufsz - head) < msgsz ) {
176: MEMCPY(msg, &buffer[head], (UINT)remsz);
177: msg = (VB*)msg + remsz;
178: msgsz -= remsz;
179: head = 0;
180: }
181: MEMCPY(msg, &buffer[head], (UINT)msgsz);
182: head += (INT)ROUNDSZ(msgsz);
183: if ( head >= mbfcb->bufsz ) {
184: head = 0;
185: }
186:
187: mbfcb->head = head;
188:
189: return actsz;
190: }
191:
192:
193:
194: 195: 196: 197:
198: LOCAL void mbf_wakeup( MBFCB *mbfcb )
199: {
200: TCB *top;
201: INT msgsz;
202:
203: while ( !isQueEmpty(&mbfcb->send_queue) ) {
204: top = (TCB*)mbfcb->send_queue.next;
205: msgsz = top->winfo.smbf.msgsz;
206: if ( !mbf_free(mbfcb, msgsz) ) {
207: break;
208: }
209:
210:
211: msg_to_mbf(mbfcb, top->winfo.smbf.msg, msgsz);
212: wait_release_ok(top);
213: }
214: }
215:
216: 217: 218:
219: LOCAL void mbf_chg_pri( TCB *tcb, INT oldpri )
220: {
221: MBFCB *mbfcb;
222:
223: mbfcb = get_mbfcb(tcb->wid);
224: if ( oldpri >= 0 ) {
225:
226: gcb_change_priority((GCB*)mbfcb, tcb);
227: }
228:
229: 230:
231: mbf_wakeup(mbfcb);
232: }
233:
234: 235: 236:
237: LOCAL void mbf_rel_wai( TCB *tcb )
238: {
239: mbf_chg_pri(tcb, -1);
240: }
241:
242: 243: 244:
245: LOCAL CONST WSPEC wspec_smbf_tfifo = { TTW_SMBF, NULL, mbf_rel_wai };
246: LOCAL CONST WSPEC wspec_smbf_tpri = { TTW_SMBF, mbf_chg_pri, mbf_rel_wai };
247: LOCAL CONST WSPEC wspec_rmbf = { TTW_RMBF, NULL, NULL };
248:
249:
250: 251: 252:
253: SYSCALL ID _tk_cre_mbf( CONST T_CMBF *pk_cmbf )
254: {
255: #if CHK_RSATR
256: const ATR VALID_MBFATR = {
257: TA_TPRI
258: |TA_NODISWAI
259: #if USE_OBJECT_NAME
260: |TA_DSNAME
261: #endif
262: };
263: #endif
264: MBFCB *mbfcb;
265: ID mbfid;
266: INT bufsz;
267: VB *msgbuf;
268: ER ercd;
269:
270: CHECK_RSATR(pk_cmbf->mbfatr, VALID_MBFATR);
271: CHECK_PAR(pk_cmbf->bufsz >= 0);
272: CHECK_PAR(pk_cmbf->maxmsz > 0);
273: bufsz = (INT)ROUNDSZ(pk_cmbf->bufsz);
274:
275: if ( bufsz > 0 ) {
276: msgbuf = Imalloc((UINT)bufsz);
277: if ( msgbuf == NULL ) {
278: return E_NOMEM;
279: }
280: } else {
281: msgbuf = NULL;
282: }
283:
284: BEGIN_CRITICAL_SECTION;
285:
286: mbfcb = (MBFCB*)QueRemoveNext(&free_mbfcb);
287: if ( mbfcb == NULL ) {
288: ercd = E_LIMIT;
289: } else {
290: mbfid = ID_MBF(mbfcb - mbfcb_table);
291:
292:
293: QueInit(&mbfcb->send_queue);
294: mbfcb->mbfid = mbfid;
295: mbfcb->exinf = pk_cmbf->exinf;
296: mbfcb->mbfatr = pk_cmbf->mbfatr;
297: QueInit(&mbfcb->recv_queue);
298: mbfcb->buffer = msgbuf;
299: mbfcb->bufsz = mbfcb->frbufsz = bufsz;
300: mbfcb->maxmsz = pk_cmbf->maxmsz;
301: mbfcb->head = mbfcb->tail = 0;
302: #if USE_OBJECT_NAME
303: if ( (pk_cmbf->mbfatr & TA_DSNAME) != 0 ) {
304: STRNCPY((char*)mbfcb->name, (char*)pk_cmbf->dsname,
305: OBJECT_NAME_LENGTH);
306: }
307: #endif
308: ercd = mbfid;
309: }
310: END_CRITICAL_SECTION;
311:
312: if ( ercd < E_OK && msgbuf != NULL ) {
313: Ifree(msgbuf);
314: }
315:
316: return ercd;
317: }
318:
319: 320: 321:
322: SYSCALL ER _tk_del_mbf( ID mbfid )
323: {
324: MBFCB *mbfcb;
325: VB *msgbuf = NULL;
326: ER ercd = E_OK;
327:
328: CHECK_MBFID(mbfid);
329:
330: mbfcb = get_mbfcb(mbfid);
331:
332: BEGIN_CRITICAL_SECTION;
333: if ( mbfcb->mbfid == 0 ) {
334: ercd = E_NOEXS;
335: } else {
336: msgbuf = mbfcb->buffer;
337:
338:
339: wait_delete(&mbfcb->recv_queue);
340: wait_delete(&mbfcb->send_queue);
341:
342:
343: QueInsert(&mbfcb->send_queue, &free_mbfcb);
344: mbfcb->mbfid = 0;
345: }
346: END_CRITICAL_SECTION;
347:
348: if ( msgbuf != NULL ) {
349: Ifree(msgbuf);
350: }
351:
352: return ercd;
353: }
354:
355: 356: 357:
358: SYSCALL ER _tk_snd_mbf( ID mbfid, CONST void *msg, INT msgsz, TMO tmout )
359: {
360: return _tk_snd_mbf_u(mbfid, msg, msgsz, to_usec_tmo(tmout));
361: }
362:
363: SYSCALL ER _tk_snd_mbf_u( ID mbfid, CONST void *msg, INT msgsz, TMO_U tmout )
364: {
365: MBFCB *mbfcb;
366: TCB *tcb;
367: ER ercd = E_OK;
368:
369: CHECK_MBFID(mbfid);
370: CHECK_PAR(msgsz > 0);
371: CHECK_TMOUT(tmout);
372: CHECK_DISPATCH_POL(tmout);
373:
374: mbfcb = get_mbfcb(mbfid);
375:
376: BEGIN_CRITICAL_SECTION;
377: if ( mbfcb->mbfid == 0 ) {
378: ercd = E_NOEXS;
379: goto error_exit;
380: }
381: #if CHK_PAR
382: if ( msgsz > mbfcb->maxmsz ) {
383: ercd = E_PAR;
384: goto error_exit;
385: }
386: #endif
387:
388:
389: if ( !in_indp() && is_diswai((GCB*)mbfcb, ctxtsk, TTW_SMBF) ) {
390: ercd = E_DISWAI;
391: goto error_exit;
392: }
393:
394: if ( !isQueEmpty(&mbfcb->recv_queue) ) {
395:
396: tcb = (TCB*)mbfcb->recv_queue.next;
397: MEMCPY(tcb->winfo.rmbf.msg, msg, (UINT)msgsz);
398: *tcb->winfo.rmbf.p_msgsz = msgsz;
399: wait_release_ok(tcb);
400:
401: } else if ( (in_indp() || gcb_top_of_wait_queue((GCB*)mbfcb, ctxtsk) == ctxtsk)
402: &&(mbf_free(mbfcb, msgsz)) ) {
403:
404: msg_to_mbf(mbfcb, msg, msgsz);
405:
406: } else {
407: ercd = E_TMOUT;
408: if ( tmout != TMO_POL ) {
409:
410: ctxtsk->wspec = ( (mbfcb->mbfatr & TA_TPRI) != 0 )?
411: &wspec_smbf_tpri: &wspec_smbf_tfifo;
412: ctxtsk->wercd = &ercd;
413: ctxtsk->winfo.smbf.msg = msg;
414: ctxtsk->winfo.smbf.msgsz = msgsz;
415: gcb_make_wait_with_diswai((GCB*)mbfcb, tmout);
416: }
417: }
418:
419: error_exit:
420: END_CRITICAL_SECTION;
421:
422: return ercd;
423: }
424:
425: 426: 427:
428: SYSCALL INT _tk_rcv_mbf( ID mbfid, void *msg, TMO tmout )
429: {
430: return _tk_rcv_mbf_u(mbfid, msg, to_usec_tmo(tmout));
431: }
432:
433: SYSCALL INT _tk_rcv_mbf_u( ID mbfid, void *msg, TMO_U tmout )
434: {
435: MBFCB *mbfcb;
436: TCB *tcb;
437: INT rcvsz;
438: ER ercd = E_OK;
439:
440: CHECK_MBFID(mbfid);
441: CHECK_TMOUT(tmout);
442: CHECK_DISPATCH();
443:
444: mbfcb = get_mbfcb(mbfid);
445:
446: BEGIN_CRITICAL_SECTION;
447: if (mbfcb->mbfid == 0) {
448: ercd = E_NOEXS;
449: goto error_exit;
450: }
451:
452:
453: if ( is_diswai((GCB*)mbfcb, ctxtsk, TTW_RMBF) ) {
454: ercd = E_DISWAI;
455: goto error_exit;
456: }
457:
458: if ( !mbf_empty(mbfcb) ) {
459:
460: rcvsz = mbf_to_msg(mbfcb, msg);
461:
462:
463: mbf_wakeup(mbfcb);
464:
465: } else if ( !isQueEmpty(&mbfcb->send_queue) ) {
466:
467: tcb = (TCB*)mbfcb->send_queue.next;
468: rcvsz = tcb->winfo.smbf.msgsz;
469: MEMCPY(msg, tcb->winfo.smbf.msg, (UINT)rcvsz);
470: wait_release_ok(tcb);
471: mbf_wakeup(mbfcb);
472: } else {
473: ercd = E_TMOUT;
474: if ( tmout != TMO_POL ) {
475:
476: ctxtsk->wspec = &wspec_rmbf;
477: ctxtsk->wid = mbfid;
478: ctxtsk->wercd = &ercd;
479: ctxtsk->winfo.rmbf.msg = msg;
480: ctxtsk->winfo.rmbf.p_msgsz = &rcvsz;
481: make_wait(tmout, mbfcb->mbfatr);
482: QueInsert(&ctxtsk->tskque, &mbfcb->recv_queue);
483: }
484: }
485:
486: error_exit:
487: END_CRITICAL_SECTION;
488:
489: return ( ercd < E_OK )? ercd: rcvsz;
490: }
491:
492: 493: 494:
495: SYSCALL ER _tk_ref_mbf( ID mbfid, T_RMBF *pk_rmbf )
496: {
497: MBFCB *mbfcb;
498: TCB *tcb;
499: ER ercd = E_OK;
500:
501: CHECK_MBFID(mbfid);
502:
503: mbfcb = get_mbfcb(mbfid);
504:
505: BEGIN_CRITICAL_SECTION;
506: if ( mbfcb->mbfid == 0 ) {
507: ercd = E_NOEXS;
508: } else {
509: pk_rmbf->exinf = mbfcb->exinf;
510: pk_rmbf->wtsk = wait_tskid(&mbfcb->recv_queue);
511: pk_rmbf->stsk = wait_tskid(&mbfcb->send_queue);
512: if ( !mbf_empty(mbfcb) ) {
513: pk_rmbf->msgsz = *(HEADER*)&mbfcb->buffer[mbfcb->head];
514: } else {
515: if ( !isQueEmpty(&mbfcb->send_queue) ) {
516: tcb = (TCB*)mbfcb->send_queue.next;
517: pk_rmbf->msgsz = tcb->winfo.smbf.msgsz;
518: } else {
519: pk_rmbf->msgsz = 0;
520: }
521: }
522: pk_rmbf->frbufsz = mbfcb->frbufsz;
523: pk_rmbf->maxmsz = mbfcb->maxmsz;
524: }
525: END_CRITICAL_SECTION;
526:
527: return ercd;
528: }
529:
530:
531: 532: 533:
534: #if USE_DBGSPT
535:
536: 537: 538:
539: #if USE_OBJECT_NAME
540: EXPORT ER messagebuffer_getname(ID id, UB **name)
541: {
542: MBFCB *mbfcb;
543: ER ercd = E_OK;
544:
545: CHECK_MBFID(id);
546:
547: BEGIN_DISABLE_INTERRUPT;
548: mbfcb = get_mbfcb(id);
549: if ( mbfcb->mbfid == 0 ) {
550: ercd = E_NOEXS;
551: goto error_exit;
552: }
553: if ( (mbfcb->mbfatr & TA_DSNAME) == 0 ) {
554: ercd = E_OBJ;
555: goto error_exit;
556: }
557: *name = mbfcb->name;
558:
559: error_exit:
560: END_DISABLE_INTERRUPT;
561:
562: return ercd;
563: }
564: #endif
565:
566: 567: 568:
569: SYSCALL INT _td_lst_mbf( ID list[], INT nent )
570: {
571: MBFCB *mbfcb, *end;
572: INT n = 0;
573:
574: BEGIN_DISABLE_INTERRUPT;
575: end = mbfcb_table + NUM_MBFID;
576: for ( mbfcb = mbfcb_table; mbfcb < end; mbfcb++ ) {
577: if ( mbfcb->mbfid == 0 ) {
578: continue;
579: }
580:
581: if ( n++ < nent ) {
582: *list++ = mbfcb->mbfid;
583: }
584: }
585: END_DISABLE_INTERRUPT;
586:
587: return n;
588: }
589:
590: 591: 592:
593: SYSCALL ER _td_ref_mbf( ID mbfid, TD_RMBF *pk_rmbf )
594: {
595: MBFCB *mbfcb;
596: TCB *tcb;
597: ER ercd = E_OK;
598:
599: CHECK_MBFID(mbfid);
600:
601: mbfcb = get_mbfcb(mbfid);
602:
603: BEGIN_DISABLE_INTERRUPT;
604: if ( mbfcb->mbfid == 0 ) {
605: ercd = E_NOEXS;
606: } else {
607: pk_rmbf->exinf = mbfcb->exinf;
608: pk_rmbf->wtsk = wait_tskid(&mbfcb->recv_queue);
609: pk_rmbf->stsk = wait_tskid(&mbfcb->send_queue);
610: if ( !mbf_empty(mbfcb) ) {
611: pk_rmbf->msgsz = *(HEADER*)&mbfcb->buffer[mbfcb->head];
612: } else {
613: if ( !isQueEmpty(&mbfcb->send_queue) ) {
614: tcb = (TCB*)mbfcb->send_queue.next;
615: pk_rmbf->msgsz = tcb->winfo.smbf.msgsz;
616: } else {
617: pk_rmbf->msgsz = 0;
618: }
619: }
620: pk_rmbf->frbufsz = mbfcb->frbufsz;
621: pk_rmbf->maxmsz = mbfcb->maxmsz;
622: }
623: END_DISABLE_INTERRUPT;
624:
625: return ercd;
626: }
627:
628: 629: 630:
631: SYSCALL INT _td_smbf_que( ID mbfid, ID list[], INT nent )
632: {
633: MBFCB *mbfcb;
634: QUEUE *q;
635: ER ercd = E_OK;
636:
637: CHECK_MBFID(mbfid);
638:
639: mbfcb = get_mbfcb(mbfid);
640:
641: BEGIN_DISABLE_INTERRUPT;
642: if ( mbfcb->mbfid == 0 ) {
643: ercd = E_NOEXS;
644: } else {
645: INT n = 0;
646: for ( q = mbfcb->send_queue.next; q != &mbfcb->send_queue; q = q->next ) {
647: if ( n++ < nent ) {
648: *list++ = ((TCB*)q)->tskid;
649: }
650: }
651: ercd = n;
652: }
653: END_DISABLE_INTERRUPT;
654:
655: return ercd;
656: }
657:
658: 659: 660:
661: SYSCALL INT _td_rmbf_que( ID mbfid, ID list[], INT nent )
662: {
663: MBFCB *mbfcb;
664: QUEUE *q;
665: ER ercd = E_OK;
666:
667: CHECK_MBFID(mbfid);
668:
669: mbfcb = get_mbfcb(mbfid);
670:
671: BEGIN_DISABLE_INTERRUPT;
672: if ( mbfcb->mbfid == 0 ) {
673: ercd = E_NOEXS;
674: } else {
675: INT n = 0;
676: for ( q = mbfcb->recv_queue.next; q != &mbfcb->recv_queue; q = q->next ) {
677: if ( n++ < nent ) {
678: *list++ = ((TCB*)q)->tskid;
679: }
680: }
681: ercd = n;
682: }
683: END_DISABLE_INTERRUPT;
684:
685: return ercd;
686: }
687:
688: #endif
689: #endif