1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17:
18:
19: #include "kernel.h"
20: #include "wait.h"
21: #include "check.h"
22: #include "messagebuf.h"
23:
24: #if USE_MESSAGEBUFFER == 1
25:
26:
27: Noinit(EXPORT MBFCB knl_mbfcb_table[NUM_MBFID]);
28: Noinit(EXPORT QUEUE knl_free_mbfcb);
29:
30:
31: 32: 33:
34: EXPORT ER knl_messagebuffer_initialize( void )
35: {
36: MBFCB *mbfcb, *end;
37:
38:
39: if ( NUM_MBFID < 1 ) {
40: return E_SYS;
41: }
42:
43:
44: QueInit(&knl_free_mbfcb);
45: end = knl_mbfcb_table + NUM_MBFID;
46: for ( mbfcb = knl_mbfcb_table; mbfcb < end; mbfcb++ ) {
47: mbfcb->mbfid = 0;
48: QueInsert(&mbfcb->send_queue, &knl_free_mbfcb);
49: }
50:
51: return E_OK;
52: }
53:
54:
55:
56: 57: 58:
59: LOCAL void knl_msg_to_mbf( MBFCB *mbfcb, CONST void *msg, INT msgsz )
60: {
61: W tail = mbfcb->tail;
62: VB *buffer = mbfcb->buffer;
63: W remsz;
64:
65: mbfcb->frbufsz -= (W)(HEADERSZ + ROUNDSZ(msgsz));
66:
67: *(HEADER*)&buffer[tail] = msgsz;
68: tail += HEADERSZ;
69: if ( tail >= mbfcb->bufsz ) {
70: tail = 0;
71: }
72:
73: if ( (remsz = mbfcb->bufsz - tail) < (W)msgsz ) {
74: knl_memcpy(&buffer[tail], msg, (SZ)remsz);
75: msg = (VB*)msg + remsz;
76: msgsz -= (INT)remsz;
77: tail = 0;
78: }
79: knl_memcpy(&buffer[tail], msg, (SZ)msgsz);
80: tail += (W)ROUNDSZ(msgsz);
81: if ( tail >= mbfcb->bufsz ) {
82: tail = 0;
83: }
84:
85: mbfcb->tail = tail;
86: }
87:
88:
89:
90: 91: 92: 93:
94: LOCAL void knl_mbf_wakeup( MBFCB *mbfcb )
95: {
96: TCB *top;
97: INT msgsz;
98:
99: while ( !isQueEmpty(&mbfcb->send_queue) ) {
100: top = (TCB*)mbfcb->send_queue.next;
101: msgsz = top->winfo.smbf.msgsz;
102: if ( !knl_mbf_free(mbfcb, msgsz) ) {
103: break;
104: }
105:
106:
107: knl_msg_to_mbf(mbfcb, top->winfo.smbf.msg, msgsz);
108: knl_wait_release_ok(top);
109: }
110: }
111:
112:
113: 114: 115:
116: SYSCALL ID tk_cre_mbf( CONST T_CMBF *pk_cmbf )
117: {
118: #if CHK_RSATR
119: const ATR VALID_MBFATR = {
120: TA_TPRI
121: |TA_USERBUF
122: #if USE_OBJECT_NAME
123: |TA_DSNAME
124: #endif
125: };
126: #endif
127: MBFCB *mbfcb;
128: ID mbfid;
129: W bufsz;
130: VB *msgbuf;
131: ER ercd;
132:
133: CHECK_RSATR(pk_cmbf->mbfatr, VALID_MBFATR);
134: CHECK_PAR(pk_cmbf->bufsz >= 0);
135: CHECK_PAR(pk_cmbf->maxmsz > 0);
136: #if !USE_IMALLOC
137:
138: CHECK_PAR((pk_cmbf->mbfatr & TA_USERBUF) != 0);
139: #endif
140: bufsz = (W)ROUNDSZ(pk_cmbf->bufsz);
141:
142: if ( bufsz > 0 ) {
143: #if USE_IMALLOC
144: if ( (pk_cmbf->mbfatr & TA_USERBUF) != 0 ) {
145:
146: if ( bufsz != pk_cmbf->bufsz ) {
147: return E_PAR;
148: }
149:
150: msgbuf = (VB*) pk_cmbf->bufptr;
151: } else {
152:
153: msgbuf = knl_Imalloc((UW)bufsz);
154: if ( msgbuf == NULL ) {
155: return E_NOMEM;
156: }
157: }
158: #else
159:
160: if ( bufsz != pk_cmbf->bufsz ) {
161: return E_PAR;
162: }
163:
164: msgbuf = (VB*) pk_cmbf->bufptr;
165: #endif
166: } else {
167: msgbuf = NULL;
168: }
169:
170: BEGIN_CRITICAL_SECTION;
171:
172: mbfcb = (MBFCB*)QueRemoveNext(&knl_free_mbfcb);
173: if ( mbfcb == NULL ) {
174: ercd = E_LIMIT;
175: } else {
176: mbfid = ID_MBF(mbfcb - knl_mbfcb_table);
177:
178:
179: QueInit(&mbfcb->send_queue);
180: mbfcb->mbfid = mbfid;
181: mbfcb->exinf = pk_cmbf->exinf;
182: mbfcb->mbfatr = pk_cmbf->mbfatr;
183: QueInit(&mbfcb->recv_queue);
184: mbfcb->buffer = msgbuf;
185: mbfcb->bufsz = mbfcb->frbufsz = bufsz;
186: mbfcb->maxmsz = pk_cmbf->maxmsz;
187: mbfcb->head = mbfcb->tail = 0;
188: #if USE_OBJECT_NAME
189: if ( (pk_cmbf->mbfatr & TA_DSNAME) != 0 ) {
190: knl_strncpy((char*)mbfcb->name, (char*)pk_cmbf->dsname,
191: OBJECT_NAME_LENGTH);
192: }
193: #endif
194: ercd = mbfid;
195: }
196: END_CRITICAL_SECTION;
197:
198: #if USE_IMALLOC
199: if ( (ercd < E_OK) && (msgbuf != NULL) && ((pk_cmbf->mbfatr & TA_USERBUF) == 0 ) ) {
200: knl_Ifree(msgbuf);
201: }
202: #endif
203:
204: return ercd;
205: }
206:
207: #ifdef USE_FUNC_TK_DEL_MBF
208: 209: 210:
211: SYSCALL ER tk_del_mbf( ID mbfid )
212: {
213: MBFCB *mbfcb;
214: VB *msgbuf = NULL;
215: ER ercd = E_OK;
216:
217: CHECK_MBFID(mbfid);
218:
219: mbfcb = get_mbfcb(mbfid);
220:
221: BEGIN_CRITICAL_SECTION;
222: if ( mbfcb->mbfid == 0 ) {
223: ercd = E_NOEXS;
224: } else {
225: msgbuf = mbfcb->buffer;
226:
227:
228: knl_wait_delete(&mbfcb->recv_queue);
229: knl_wait_delete(&mbfcb->send_queue);
230:
231:
232: QueInsert(&mbfcb->send_queue, &knl_free_mbfcb);
233: mbfcb->mbfid = 0;
234: }
235: END_CRITICAL_SECTION;
236:
237: #if USE_IMALLOC
238: if ( msgbuf != NULL && ((mbfcb->mbfatr & TA_USERBUF) == 0 ) ) {
239: knl_Ifree(msgbuf);
240: }
241: #endif
242:
243: return ercd;
244: }
245: #endif
246:
247: 248: 249:
250: LOCAL void knl_mbf_chg_pri( TCB *tcb, INT oldpri )
251: {
252: MBFCB *mbfcb;
253:
254: mbfcb = get_mbfcb(tcb->wid);
255: if ( oldpri >= 0 ) {
256:
257: knl_gcb_change_priority((GCB*)mbfcb, tcb);
258: }
259:
260: 261:
262: knl_mbf_wakeup(mbfcb);
263: }
264:
265: 266: 267:
268: LOCAL void knl_mbf_rel_wai( TCB *tcb )
269: {
270: knl_mbf_chg_pri(tcb, -1);
271: }
272:
273: 274: 275:
276: LOCAL CONST WSPEC knl_wspec_smbf_tfifo = { TTW_SMBF, NULL, knl_mbf_rel_wai };
277: LOCAL CONST WSPEC knl_wspec_smbf_tpri = { TTW_SMBF, knl_mbf_chg_pri, knl_mbf_rel_wai };
278:
279: 280: 281:
282: SYSCALL ER tk_snd_mbf( ID mbfid, CONST void *msg, INT msgsz, TMO tmout )
283: {
284: MBFCB *mbfcb;
285: TCB *tcb;
286: ER ercd = E_OK;
287:
288: CHECK_MBFID(mbfid);
289: CHECK_PAR(msgsz > 0);
290: CHECK_TMOUT(tmout);
291: CHECK_DISPATCH_POL(tmout);
292:
293: mbfcb = get_mbfcb(mbfid);
294:
295: BEGIN_CRITICAL_SECTION;
296: if ( mbfcb->mbfid == 0 ) {
297: ercd = E_NOEXS;
298: goto error_exit;
299: }
300: #if CHK_PAR
301: if ( msgsz > mbfcb->maxmsz ) {
302: ercd = E_PAR;
303: goto error_exit;
304: }
305: #endif
306:
307: if ( !isQueEmpty(&mbfcb->recv_queue) ) {
308:
309: tcb = (TCB*)mbfcb->recv_queue.next;
310: knl_memcpy(tcb->winfo.rmbf.msg, msg, (SZ)msgsz);
311: *tcb->winfo.rmbf.p_msgsz = msgsz;
312: knl_wait_release_ok(tcb);
313:
314: } else if ( (in_indp() || knl_gcb_top_of_wait_queue((GCB*)mbfcb, knl_ctxtsk) == knl_ctxtsk)
315: &&(knl_mbf_free(mbfcb, msgsz)) ) {
316:
317: knl_msg_to_mbf(mbfcb, msg, msgsz);
318:
319: } else {
320: ercd = E_TMOUT;
321: if ( tmout != TMO_POL ) {
322:
323: knl_ctxtsk->wspec = ( (mbfcb->mbfatr & TA_TPRI) != 0 )?
324: &knl_wspec_smbf_tpri: &knl_wspec_smbf_tfifo;
325: knl_ctxtsk->wercd = &ercd;
326: knl_ctxtsk->winfo.smbf.msg = msg;
327: knl_ctxtsk->winfo.smbf.msgsz = msgsz;
328: knl_gcb_make_wait((GCB*)mbfcb, tmout);
329: }
330: }
331:
332: error_exit:
333: END_CRITICAL_SECTION;
334:
335: return ercd;
336: }
337:
338:
339: LOCAL CONST WSPEC knl_wspec_rmbf = { TTW_RMBF, NULL, NULL };
340:
341: 342: 343: 344:
345: LOCAL INT knl_mbf_to_msg( MBFCB *mbfcb, void *msg )
346: {
347: W head = mbfcb->head;
348: VB *buffer = mbfcb->buffer;
349: INT msgsz, actsz;
350: W remsz;
351:
352: actsz = msgsz = *(HEADER*)&buffer[head];
353: mbfcb->frbufsz += (W)(HEADERSZ + ROUNDSZ(msgsz));
354:
355: head += (W)HEADERSZ;
356: if ( head >= mbfcb->bufsz ) {
357: head = 0;
358: }
359:
360: if ( (remsz = mbfcb->bufsz - head) < (W)msgsz ) {
361: knl_memcpy(msg, &buffer[head], (SZ)remsz);
362: msg = (VB*)msg + remsz;
363: msgsz -= (INT)remsz;
364: head = 0;
365: }
366: knl_memcpy(msg, &buffer[head], (SZ)msgsz);
367: head += (INT)ROUNDSZ(msgsz);
368: if ( head >= mbfcb->bufsz ) {
369: head = 0;
370: }
371:
372: mbfcb->head = head;
373:
374: return actsz;
375: }
376:
377: 378: 379:
380: SYSCALL INT tk_rcv_mbf( ID mbfid, void *msg, TMO tmout )
381: {
382: MBFCB *mbfcb;
383: TCB *tcb;
384: INT rcvsz;
385: ER ercd = E_OK;
386:
387: CHECK_MBFID(mbfid);
388: CHECK_TMOUT(tmout);
389: CHECK_DISPATCH();
390:
391: mbfcb = get_mbfcb(mbfid);
392:
393: BEGIN_CRITICAL_SECTION;
394: if (mbfcb->mbfid == 0) {
395: ercd = E_NOEXS;
396: goto error_exit;
397: }
398:
399: if ( !knl_mbf_empty(mbfcb) ) {
400:
401: rcvsz = knl_mbf_to_msg(mbfcb, msg);
402:
403:
404: knl_mbf_wakeup(mbfcb);
405:
406: } else if ( !isQueEmpty(&mbfcb->send_queue) ) {
407:
408: tcb = (TCB*)mbfcb->send_queue.next;
409: rcvsz = tcb->winfo.smbf.msgsz;
410: knl_memcpy(msg, tcb->winfo.smbf.msg, (SZ)rcvsz);
411: knl_wait_release_ok(tcb);
412: knl_mbf_wakeup(mbfcb);
413: } else {
414: ercd = E_TMOUT;
415: if ( tmout != TMO_POL ) {
416:
417: knl_ctxtsk->wspec = &knl_wspec_rmbf;
418: knl_ctxtsk->wid = mbfid;
419: knl_ctxtsk->wercd = &ercd;
420: knl_ctxtsk->winfo.rmbf.msg = msg;
421: knl_ctxtsk->winfo.rmbf.p_msgsz = &rcvsz;
422: knl_make_wait(tmout, mbfcb->mbfatr);
423: QueInsert(&knl_ctxtsk->tskque, &mbfcb->recv_queue);
424: }
425: }
426:
427: error_exit:
428: END_CRITICAL_SECTION;
429:
430: return ( ercd < E_OK )? ercd: rcvsz;
431: }
432:
433: #ifdef USE_FUNC_TK_REF_MBF
434: 435: 436:
437: SYSCALL ER tk_ref_mbf( ID mbfid, T_RMBF *pk_rmbf )
438: {
439: MBFCB *mbfcb;
440: TCB *tcb;
441: ER ercd = E_OK;
442:
443: CHECK_MBFID(mbfid);
444:
445: mbfcb = get_mbfcb(mbfid);
446:
447: BEGIN_CRITICAL_SECTION;
448: if ( mbfcb->mbfid == 0 ) {
449: ercd = E_NOEXS;
450: } else {
451: pk_rmbf->exinf = mbfcb->exinf;
452: pk_rmbf->wtsk = knl_wait_tskid(&mbfcb->recv_queue);
453: pk_rmbf->stsk = knl_wait_tskid(&mbfcb->send_queue);
454: if ( !knl_mbf_empty(mbfcb) ) {
455: pk_rmbf->msgsz = *(HEADER*)&mbfcb->buffer[mbfcb->head];
456: } else {
457: if ( !isQueEmpty(&mbfcb->send_queue) ) {
458: tcb = (TCB*)mbfcb->send_queue.next;
459: pk_rmbf->msgsz = tcb->winfo.smbf.msgsz;
460: } else {
461: pk_rmbf->msgsz = 0;
462: }
463: }
464: pk_rmbf->frbufsz = mbfcb->frbufsz;
465: pk_rmbf->maxmsz = mbfcb->maxmsz;
466: }
467: END_CRITICAL_SECTION;
468:
469: return ercd;
470: }
471: #endif
472:
473:
474: 475: 476:
477: #if USE_DBGSPT
478:
479: #if USE_OBJECT_NAME
480: 481: 482:
483: EXPORT ER knl_messagebuffer_getname(ID id, UB **name)
484: {
485: MBFCB *mbfcb;
486: ER ercd = E_OK;
487:
488: CHECK_MBFID(id);
489:
490: BEGIN_DISABLE_INTERRUPT;
491: mbfcb = get_mbfcb(id);
492: if ( mbfcb->mbfid == 0 ) {
493: ercd = E_NOEXS;
494: goto error_exit;
495: }
496: if ( (mbfcb->mbfatr & TA_DSNAME) == 0 ) {
497: ercd = E_OBJ;
498: goto error_exit;
499: }
500: *name = mbfcb->name;
501:
502: error_exit:
503: END_DISABLE_INTERRUPT;
504:
505: return ercd;
506: }
507: #endif
508:
509: #ifdef USE_FUNC_TD_LST_MBF
510: 511: 512:
513: SYSCALL INT td_lst_mbf( ID list[], INT nent )
514: {
515: MBFCB *mbfcb, *end;
516: INT n = 0;
517:
518: BEGIN_DISABLE_INTERRUPT;
519: end = knl_mbfcb_table + NUM_MBFID;
520: for ( mbfcb = knl_mbfcb_table; mbfcb < end; mbfcb++ ) {
521: if ( mbfcb->mbfid == 0 ) {
522: continue;
523: }
524:
525: if ( n++ < nent ) {
526: *list++ = mbfcb->mbfid;
527: }
528: }
529: END_DISABLE_INTERRUPT;
530:
531: return n;
532: }
533: #endif
534:
535: #ifdef USE_FUNC_TD_REF_MBF
536: 537: 538:
539: SYSCALL ER td_ref_mbf( ID mbfid, TD_RMBF *pk_rmbf )
540: {
541: MBFCB *mbfcb;
542: TCB *tcb;
543: ER ercd = E_OK;
544:
545: CHECK_MBFID(mbfid);
546:
547: mbfcb = get_mbfcb(mbfid);
548:
549: BEGIN_DISABLE_INTERRUPT;
550: if ( mbfcb->mbfid == 0 ) {
551: ercd = E_NOEXS;
552: } else {
553: pk_rmbf->exinf = mbfcb->exinf;
554: pk_rmbf->wtsk = knl_wait_tskid(&mbfcb->recv_queue);
555: pk_rmbf->stsk = knl_wait_tskid(&mbfcb->send_queue);
556: if ( !knl_mbf_empty(mbfcb) ) {
557: pk_rmbf->msgsz = *(HEADER*)&mbfcb->buffer[mbfcb->head];
558: } else {
559: if ( !isQueEmpty(&mbfcb->send_queue) ) {
560: tcb = (TCB*)mbfcb->send_queue.next;
561: pk_rmbf->msgsz = tcb->winfo.smbf.msgsz;
562: } else {
563: pk_rmbf->msgsz = 0;
564: }
565: }
566: pk_rmbf->frbufsz = mbfcb->frbufsz;
567: pk_rmbf->maxmsz = mbfcb->maxmsz;
568: }
569: END_DISABLE_INTERRUPT;
570:
571: return ercd;
572: }
573: #endif
574:
575: #ifdef USE_FUNC_TD_SMBF_QUE
576: 577: 578:
579: SYSCALL INT td_smbf_que( ID mbfid, ID list[], INT nent )
580: {
581: MBFCB *mbfcb;
582: QUEUE *q;
583: ER ercd = E_OK;
584:
585: CHECK_MBFID(mbfid);
586:
587: mbfcb = get_mbfcb(mbfid);
588:
589: BEGIN_DISABLE_INTERRUPT;
590: if ( mbfcb->mbfid == 0 ) {
591: ercd = E_NOEXS;
592: } else {
593: INT n = 0;
594: for ( q = mbfcb->send_queue.next; q != &mbfcb->send_queue; q = q->next ) {
595: if ( n++ < nent ) {
596: *list++ = ((TCB*)q)->tskid;
597: }
598: }
599: ercd = n;
600: }
601: END_DISABLE_INTERRUPT;
602:
603: return ercd;
604: }
605: #endif
606:
607: #ifdef USE_FUNC_TD_RMBF_QUE
608: 609: 610:
611: SYSCALL INT td_rmbf_que( ID mbfid, ID list[], INT nent )
612: {
613: MBFCB *mbfcb;
614: QUEUE *q;
615: ER ercd = E_OK;
616:
617: CHECK_MBFID(mbfid);
618:
619: mbfcb = get_mbfcb(mbfid);
620:
621: BEGIN_DISABLE_INTERRUPT;
622: if ( mbfcb->mbfid == 0 ) {
623: ercd = E_NOEXS;
624: } else {
625: INT n = 0;
626: for ( q = mbfcb->recv_queue.next; q != &mbfcb->recv_queue; q = q->next ) {
627: if ( n++ < nent ) {
628: *list++ = ((TCB*)q)->tskid;
629: }
630: }
631: ercd = n;
632: }
633: END_DISABLE_INTERRUPT;
634:
635: return ercd;
636: }
637: #endif
638:
639: #endif
640: #endif