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_PORID
29:
30: EXPORT ID max_porid;
31:
32: 33: 34:
35: typedef struct port_control_block {
36: QUEUE call_queue;
37: ID porid;
38: void *exinf;
39: ATR poratr;
40: QUEUE accept_queue;
41: INT maxcmsz;
42: INT maxrmsz;
43: #if USE_OBJECT_NAME
44: UB name[OBJECT_NAME_LENGTH];
45: #endif
46: } PORCB;
47:
48: LOCAL PORCB *porcb_table;
49: LOCAL QUEUE free_porcb;
50:
51: #define get_porcb(id) ( &porcb_table[INDEX_POR(id)] )
52:
53:
54: 55: 56:
57: EXPORT ER rendezvous_initialize( void )
58: {
59: PORCB *porcb, *end;
60: W n;
61:
62:
63: n = _tk_get_cfn(SCTAG_TMAXPORID, &max_porid, 1);
64: if ( n < 1 || NUM_PORID < 1 ) {
65: return E_SYS;
66: }
67:
68:
69: porcb_table = Imalloc((UINT)NUM_PORID * sizeof(PORCB));
70: if ( porcb_table == NULL ) {
71: return E_NOMEM;
72: }
73:
74:
75: QueInit(&free_porcb);
76: end = porcb_table + NUM_PORID;
77: for ( porcb = porcb_table; porcb < end; porcb++ ) {
78: porcb->porid = 0;
79: QueInsert(&porcb->call_queue, &free_porcb);
80: }
81:
82: return E_OK;
83: }
84:
85:
86: #define RDVNO_SHIFT 16
87:
88: 89: 90:
91: Inline RNO gen_rdvno( TCB *tcb )
92: {
93: RNO rdvno;
94:
95: rdvno = tcb->wrdvno;
96: tcb->wrdvno += (1 << RDVNO_SHIFT);
97:
98: return rdvno;
99: }
100:
101: 102: 103:
104: Inline ID get_tskid_rdvno( RNO rdvno )
105: {
106: return (ID)((UINT)rdvno & ((1 << RDVNO_SHIFT) - 1));
107: }
108:
109: 110: 111:
112: #define CHECK_RDVNO(rdvno) { \
113: if ( !CHK_TSKID(get_tskid_rdvno(rdvno)) ) { \
114: return E_OBJ; \
115: } \
116: }
117:
118:
119: 120: 121:
122: LOCAL void cal_chg_pri( TCB *tcb, INT oldpri )
123: {
124: PORCB *porcb;
125:
126: porcb = get_porcb(tcb->wid);
127: gcb_change_priority((GCB*)porcb, tcb);
128: }
129:
130: 131: 132:
133: LOCAL CONST WSPEC wspec_cal_tfifo = { TTW_CAL, NULL, NULL };
134: LOCAL CONST WSPEC wspec_cal_tpri = { TTW_CAL, cal_chg_pri, NULL };
135: LOCAL CONST WSPEC wspec_acp = { TTW_ACP, NULL, NULL };
136: LOCAL CONST WSPEC wspec_rdv = { TTW_RDV, NULL, NULL };
137:
138:
139: 140: 141:
142: SYSCALL ID _tk_cre_por( CONST T_CPOR *pk_cpor )
143: {
144: #if CHK_RSATR
145: const ATR VALID_PORATR = {
146: TA_TPRI
147: |TA_NODISWAI
148: #if USE_OBJECT_NAME
149: |TA_DSNAME
150: #endif
151: };
152: #endif
153: PORCB *porcb;
154: ID porid;
155: ER ercd;
156:
157: CHECK_RSATR(pk_cpor->poratr, VALID_PORATR);
158: CHECK_PAR(pk_cpor->maxcmsz >= 0);
159: CHECK_PAR(pk_cpor->maxrmsz >= 0);
160: CHECK_INTSK();
161:
162: BEGIN_CRITICAL_SECTION;
163:
164: porcb = (PORCB*)QueRemoveNext(&free_porcb);
165: if ( porcb == NULL ) {
166: ercd = E_LIMIT;
167: } else {
168: porid = ID_POR(porcb - porcb_table);
169:
170:
171: QueInit(&porcb->call_queue);
172: porcb->porid = porid;
173: porcb->exinf = pk_cpor->exinf;
174: porcb->poratr = pk_cpor->poratr;
175: QueInit(&porcb->accept_queue);
176: porcb->maxcmsz = pk_cpor->maxcmsz;
177: porcb->maxrmsz = pk_cpor->maxrmsz;
178: #if USE_OBJECT_NAME
179: if ( (pk_cpor->poratr & TA_DSNAME) != 0 ) {
180: STRNCPY((char*)porcb->name, (char*)pk_cpor->dsname,
181: OBJECT_NAME_LENGTH);
182: }
183: #endif
184: ercd = porid;
185: }
186: END_CRITICAL_SECTION;
187:
188: return ercd;
189: }
190:
191: 192: 193:
194: SYSCALL ER _tk_del_por( ID porid )
195: {
196: PORCB *porcb;
197: ER ercd = E_OK;
198:
199: CHECK_PORID(porid);
200: CHECK_INTSK();
201:
202: porcb = get_porcb(porid);
203:
204: BEGIN_CRITICAL_SECTION;
205: if ( porcb->porid == 0 ) {
206: ercd = E_NOEXS;
207: } else {
208:
209: wait_delete(&porcb->call_queue);
210: wait_delete(&porcb->accept_queue);
211:
212:
213: QueInsert(&porcb->call_queue, &free_porcb);
214: porcb->porid = 0;
215: }
216: END_CRITICAL_SECTION;
217:
218: return ercd;
219: }
220:
221: 222: 223:
224: SYSCALL INT _tk_cal_por( ID porid, UINT calptn, void *msg, INT cmsgsz, TMO tmout )
225: {
226: return _tk_cal_por_u(porid, calptn, msg, cmsgsz, to_usec_tmo(tmout));
227: }
228:
229: SYSCALL INT _tk_cal_por_u( ID porid, UINT calptn, void *msg, INT cmsgsz, TMO_U tmout )
230: {
231: PORCB *porcb;
232: TCB *tcb;
233: QUEUE *queue;
234: RNO rdvno;
235: INT rmsgsz;
236: ER ercd = E_OK;
237:
238: CHECK_PORID(porid);
239: CHECK_PAR(calptn != 0);
240: CHECK_PAR(cmsgsz >= 0);
241: CHECK_TMOUT(tmout);
242: CHECK_DISPATCH();
243:
244: porcb = get_porcb(porid);
245:
246: BEGIN_CRITICAL_SECTION;
247: if ( porcb->porid == 0 ) {
248: ercd = E_NOEXS;
249: goto error_exit;
250: }
251: #if CHK_PAR
252: if ( cmsgsz > porcb->maxcmsz ) {
253: ercd = E_PAR;
254: goto error_exit;
255: }
256: #endif
257:
258:
259: queue = porcb->accept_queue.next;
260: while ( queue != &porcb->accept_queue ) {
261: tcb = (TCB*)queue;
262: queue = queue->next;
263: if ( (calptn & tcb->winfo.acp.acpptn) == 0 ) {
264: continue;
265: }
266:
267:
268: if ( is_diswai((GCB*)porcb, ctxtsk, TTW_CAL) ) {
269: ercd = E_DISWAI;
270: goto error_exit;
271: }
272:
273:
274: rdvno = gen_rdvno(ctxtsk);
275: if ( cmsgsz > 0 ) {
276: MEMCPY(tcb->winfo.acp.msg, msg, (UINT)cmsgsz);
277: }
278: *tcb->winfo.acp.p_rdvno = rdvno;
279: *tcb->winfo.acp.p_cmsgsz = cmsgsz;
280: wait_release_ok(tcb);
281:
282:
283: if ( is_diswai((GCB*)porcb, ctxtsk, TTW_RDV) ) {
284: ercd = E_DISWAI;
285: goto error_exit;
286: }
287:
288:
289: ercd = E_TMOUT;
290: ctxtsk->wspec = &wspec_rdv;
291: ctxtsk->wid = 0;
292: ctxtsk->wercd = &ercd;
293: ctxtsk->winfo.rdv.rdvno = rdvno;
294: ctxtsk->winfo.rdv.msg = msg;
295: ctxtsk->winfo.rdv.maxrmsz = porcb->maxrmsz;
296: ctxtsk->winfo.rdv.p_rmsgsz = &rmsgsz;
297: make_wait(TMO_FEVR, porcb->poratr);
298: QueInit(&ctxtsk->tskque);
299:
300: goto error_exit;
301: }
302:
303:
304: ctxtsk->wspec = ( (porcb->poratr & TA_TPRI) != 0 )?
305: &wspec_cal_tpri: &wspec_cal_tfifo;
306: ctxtsk->wercd = &ercd;
307: ctxtsk->winfo.cal.calptn = calptn;
308: ctxtsk->winfo.cal.msg = msg;
309: ctxtsk->winfo.cal.cmsgsz = cmsgsz;
310: ctxtsk->winfo.cal.p_rmsgsz = &rmsgsz;
311: gcb_make_wait_with_diswai((GCB*)porcb, tmout);
312:
313: error_exit:
314: END_CRITICAL_SECTION;
315:
316: return ( ercd < E_OK )? ercd: rmsgsz;
317: }
318:
319: 320: 321:
322: SYSCALL INT _tk_acp_por( ID porid, UINT acpptn, RNO *p_rdvno, void *msg, TMO tmout )
323: {
324: return _tk_acp_por_u(porid, acpptn, p_rdvno, msg, to_usec_tmo(tmout));
325: }
326:
327: SYSCALL INT _tk_acp_por_u( ID porid, UINT acpptn, RNO *p_rdvno, void *msg, TMO_U tmout )
328: {
329: PORCB *porcb;
330: TCB *tcb;
331: QUEUE *queue;
332: RNO rdvno;
333: INT cmsgsz;
334: ER ercd = E_OK;
335:
336: CHECK_PORID(porid);
337: CHECK_PAR(acpptn != 0);
338: CHECK_TMOUT(tmout);
339: CHECK_DISPATCH();
340:
341: porcb = get_porcb(porid);
342:
343: BEGIN_CRITICAL_SECTION;
344: if ( porcb->porid == 0 ) {
345: ercd = E_NOEXS;
346: goto error_exit;
347: }
348:
349:
350: queue = porcb->call_queue.next;
351: while ( queue != &porcb->call_queue ) {
352: tcb = (TCB*)queue;
353: queue = queue->next;
354: if ( (acpptn & tcb->winfo.cal.calptn) == 0 ) {
355: continue;
356: }
357:
358:
359: if ( is_diswai((GCB*)porcb, ctxtsk, TTW_ACP) ) {
360: ercd = E_DISWAI;
361: goto error_exit;
362: }
363:
364:
365: *p_rdvno = rdvno = gen_rdvno(tcb);
366: cmsgsz = tcb->winfo.cal.cmsgsz;
367: if ( cmsgsz > 0 ) {
368: MEMCPY(msg, tcb->winfo.cal.msg, (UINT)cmsgsz);
369: }
370:
371:
372: if ( is_diswai((GCB*)porcb, tcb, TTW_RDV) ) {
373: wait_release_ng(tcb, E_DISWAI);
374: goto error_exit;
375: }
376: wait_cancel(tcb);
377:
378:
379: tcb->wspec = &wspec_rdv;
380: tcb->wid = 0;
381: tcb->winfo.rdv.rdvno = rdvno;
382: tcb->winfo.rdv.msg = tcb->winfo.cal.msg;
383: tcb->winfo.rdv.maxrmsz = porcb->maxrmsz;
384: tcb->winfo.rdv.p_rmsgsz = tcb->winfo.cal.p_rmsgsz;
385: timer_insert(&tcb->wtmeb, TMO_FEVR,
386: (CBACK)wait_release_tmout, tcb);
387: QueInit(&tcb->tskque);
388:
389: goto error_exit;
390: }
391:
392:
393: if ( is_diswai((GCB*)porcb, ctxtsk, TTW_ACP) ) {
394: ercd = E_DISWAI;
395: goto error_exit;
396: }
397:
398: ercd = E_TMOUT;
399: if ( tmout != TMO_POL ) {
400:
401: ctxtsk->wspec = &wspec_acp;
402: ctxtsk->wid = porid;
403: ctxtsk->wercd = &ercd;
404: ctxtsk->winfo.acp.acpptn = acpptn;
405: ctxtsk->winfo.acp.msg = msg;
406: ctxtsk->winfo.acp.p_rdvno = p_rdvno;
407: ctxtsk->winfo.acp.p_cmsgsz = &cmsgsz;
408: make_wait(tmout, porcb->poratr);
409: QueInsert(&ctxtsk->tskque, &porcb->accept_queue);
410: }
411:
412: error_exit:
413: END_CRITICAL_SECTION;
414:
415: return ( ercd < E_OK )? ercd: cmsgsz;
416: }
417:
418: 419: 420:
421: SYSCALL ER _tk_fwd_por( ID porid, UINT calptn, RNO rdvno, CONST void *msg, INT cmsgsz )
422: {
423: PORCB *porcb;
424: TCB *caltcb, *tcb;
425: QUEUE *queue;
426: RNO new_rdvno;
427: ER ercd = E_OK;
428:
429: CHECK_PORID(porid);
430: CHECK_PAR(calptn != 0);
431: CHECK_RDVNO(rdvno);
432: CHECK_PAR(cmsgsz >= 0);
433: CHECK_INTSK();
434:
435: porcb = get_porcb(porid);
436: caltcb = get_tcb(get_tskid_rdvno(rdvno));
437:
438: BEGIN_CRITICAL_SECTION;
439: if ( porcb->porid == 0 ) {
440: ercd = E_NOEXS;
441: goto error_exit;
442: }
443: #if CHK_PAR
444: if ( cmsgsz > porcb->maxcmsz ) {
445: ercd = E_PAR;
446: goto error_exit;
447: }
448: #endif
449: if ( (caltcb->state & TS_WAIT) == 0
450: || caltcb->wspec != &wspec_rdv
451: || rdvno != caltcb->winfo.rdv.rdvno ) {
452: ercd = E_OBJ;
453: goto error_exit;
454: }
455: if ( porcb->maxrmsz > caltcb->winfo.rdv.maxrmsz ) {
456: ercd = E_OBJ;
457: goto error_exit;
458: }
459: #if CHK_PAR
460: if ( cmsgsz > caltcb->winfo.rdv.maxrmsz ) {
461: ercd = E_PAR;
462: goto error_exit;
463: }
464: #endif
465:
466:
467: queue = porcb->accept_queue.next;
468: while ( queue != &porcb->accept_queue ) {
469: tcb = (TCB*)queue;
470: queue = queue->next;
471: if ( (calptn & tcb->winfo.acp.acpptn) == 0 ) {
472: continue;
473: }
474:
475:
476: if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) {
477: wait_release_ng(caltcb, E_DISWAI);
478: ercd = E_DISWAI;
479: goto error_exit;
480: }
481:
482:
483: new_rdvno = gen_rdvno(caltcb);
484: if ( cmsgsz > 0 ) {
485: MEMCPY(tcb->winfo.acp.msg, msg, (UINT)cmsgsz);
486: }
487: *tcb->winfo.acp.p_rdvno = new_rdvno;
488: *tcb->winfo.acp.p_cmsgsz = cmsgsz;
489: wait_release_ok(tcb);
490:
491:
492: if ( is_diswai((GCB*)porcb, caltcb, TTW_RDV) ) {
493: wait_release_ng(caltcb, E_DISWAI);
494: ercd = E_DISWAI;
495: goto error_exit;
496: }
497:
498:
499: caltcb->winfo.rdv.rdvno = new_rdvno;
500: caltcb->winfo.rdv.msg = caltcb->winfo.cal.msg;
501: caltcb->winfo.rdv.maxrmsz = porcb->maxrmsz;
502: caltcb->winfo.rdv.p_rmsgsz = caltcb->winfo.cal.p_rmsgsz;
503: caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE;
504: goto error_exit;
505: }
506:
507:
508: if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) {
509: wait_release_ng(caltcb, E_DISWAI);
510: ercd = E_DISWAI;
511: goto error_exit;
512: }
513:
514:
515: caltcb->wspec = ( (porcb->poratr & TA_TPRI) != 0 )?
516: &wspec_cal_tpri: &wspec_cal_tfifo;
517: caltcb->wid = porid;
518: caltcb->winfo.cal.calptn = calptn;
519: caltcb->winfo.cal.msg = caltcb->winfo.rdv.msg;
520: caltcb->winfo.cal.cmsgsz = cmsgsz;
521: caltcb->winfo.cal.p_rmsgsz = caltcb->winfo.rdv.p_rmsgsz;
522: caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE;
523: timer_insert(&caltcb->wtmeb, TMO_FEVR,
524: (CBACK)wait_release_tmout, caltcb);
525: if ( (porcb->poratr & TA_TPRI) != 0 ) {
526: queue_insert_tpri(caltcb, &porcb->call_queue);
527: } else {
528: QueInsert(&caltcb->tskque, &porcb->call_queue);
529: }
530:
531: if ( cmsgsz > 0 ) {
532: MEMCPY(caltcb->winfo.cal.msg, msg, (UINT)cmsgsz);
533: }
534:
535: error_exit:
536: END_CRITICAL_SECTION;
537:
538: return ercd;
539: }
540:
541: 542: 543:
544: SYSCALL ER _tk_rpl_rdv( RNO rdvno, CONST void *msg, INT rmsgsz )
545: {
546: TCB *caltcb;
547: ER ercd = E_OK;
548:
549: CHECK_RDVNO(rdvno);
550: CHECK_PAR(rmsgsz >= 0);
551: CHECK_INTSK();
552:
553: caltcb = get_tcb(get_tskid_rdvno(rdvno));
554:
555: BEGIN_CRITICAL_SECTION;
556: if ( (caltcb->state & TS_WAIT) == 0
557: || caltcb->wspec != &wspec_rdv
558: || rdvno != caltcb->winfo.rdv.rdvno ) {
559: ercd = E_OBJ;
560: goto error_exit;
561: }
562: #if CHK_PAR
563: if ( rmsgsz > caltcb->winfo.rdv.maxrmsz ) {
564: ercd = E_PAR;
565: goto error_exit;
566: }
567: #endif
568:
569:
570: if ( rmsgsz > 0 ) {
571: MEMCPY(caltcb->winfo.rdv.msg, msg, (UINT)rmsgsz);
572: }
573: *caltcb->winfo.rdv.p_rmsgsz = rmsgsz;
574: wait_release_ok(caltcb);
575:
576: error_exit:
577: END_CRITICAL_SECTION;
578:
579: return ercd;
580: }
581:
582: 583: 584:
585: SYSCALL ER _tk_ref_por( ID porid, T_RPOR *pk_rpor )
586: {
587: PORCB *porcb;
588: ER ercd = E_OK;
589:
590: CHECK_PORID(porid);
591:
592: porcb = get_porcb(porid);
593:
594: BEGIN_CRITICAL_SECTION;
595: if ( porcb->porid == 0 ) {
596: ercd = E_NOEXS;
597: } else {
598: pk_rpor->exinf = porcb->exinf;
599: pk_rpor->wtsk = wait_tskid(&porcb->call_queue);
600: pk_rpor->atsk = wait_tskid(&porcb->accept_queue);
601: pk_rpor->maxcmsz = porcb->maxcmsz;
602: pk_rpor->maxrmsz = porcb->maxrmsz;
603: }
604: END_CRITICAL_SECTION;
605:
606: return ercd;
607: }
608:
609:
610: 611: 612:
613: #if USE_DBGSPT
614:
615: 616: 617:
618: #if USE_OBJECT_NAME
619: EXPORT ER rendezvous_getname(ID id, UB **name)
620: {
621: PORCB *porcb;
622: ER ercd = E_OK;
623:
624: CHECK_PORID(id);
625:
626: BEGIN_DISABLE_INTERRUPT;
627: porcb = get_porcb(id);
628: if ( porcb->porid == 0 ) {
629: ercd = E_NOEXS;
630: goto error_exit;
631: }
632: if ( (porcb->poratr & TA_DSNAME) == 0 ) {
633: ercd = E_OBJ;
634: goto error_exit;
635: }
636: *name = porcb->name;
637:
638: error_exit:
639: END_DISABLE_INTERRUPT;
640:
641: return ercd;
642: }
643: #endif
644:
645: 646: 647:
648: SYSCALL INT _td_lst_por( ID list[], INT nent )
649: {
650: PORCB *porcb, *end;
651: INT n = 0;
652:
653: BEGIN_DISABLE_INTERRUPT;
654: end = porcb_table + NUM_PORID;
655: for ( porcb = porcb_table; porcb < end; porcb++ ) {
656: if ( porcb->porid == 0 ) {
657: continue;
658: }
659:
660: if ( n++ < nent ) {
661: *list++ = porcb->porid;
662: }
663: }
664: END_DISABLE_INTERRUPT;
665:
666: return n;
667: }
668:
669: 670: 671:
672: SYSCALL ER _td_ref_por( ID porid, TD_RPOR *pk_rpor )
673: {
674: PORCB *porcb;
675: ER ercd = E_OK;
676:
677: CHECK_PORID(porid);
678:
679: porcb = get_porcb(porid);
680:
681: BEGIN_DISABLE_INTERRUPT;
682: if ( porcb->porid == 0 ) {
683: ercd = E_NOEXS;
684: } else {
685: pk_rpor->exinf = porcb->exinf;
686: pk_rpor->wtsk = wait_tskid(&porcb->call_queue);
687: pk_rpor->atsk = wait_tskid(&porcb->accept_queue);
688: pk_rpor->maxcmsz = porcb->maxcmsz;
689: pk_rpor->maxrmsz = porcb->maxrmsz;
690: }
691: END_DISABLE_INTERRUPT;
692:
693: return ercd;
694: }
695:
696: 697: 698:
699: SYSCALL INT _td_cal_que( ID porid, ID list[], INT nent )
700: {
701: PORCB *porcb;
702: QUEUE *q;
703: ER ercd = E_OK;
704:
705: CHECK_PORID(porid);
706:
707: porcb = get_porcb(porid);
708:
709: BEGIN_DISABLE_INTERRUPT;
710: if ( porcb->porid == 0 ) {
711: ercd = E_NOEXS;
712: } else {
713: INT n = 0;
714: for ( q = porcb->call_queue.next; q != &porcb->call_queue; q = q->next ) {
715: if ( n++ < nent ) {
716: *list++ = ((TCB*)q)->tskid;
717: }
718: }
719: ercd = n;
720: }
721: END_DISABLE_INTERRUPT;
722:
723: return ercd;
724: }
725:
726: 727: 728:
729: SYSCALL INT _td_acp_que( ID porid, ID list[], INT nent )
730: {
731: PORCB *porcb;
732: QUEUE *q;
733: ER ercd = E_OK;
734:
735: CHECK_PORID(porid);
736:
737: porcb = get_porcb(porid);
738:
739: BEGIN_DISABLE_INTERRUPT;
740: if ( porcb->porid == 0 ) {
741: ercd = E_NOEXS;
742: } else {
743: INT n = 0;
744: for ( q = porcb->accept_queue.next; q != &porcb->accept_queue; q = q->next ) {
745: if ( n++ < nent ) {
746: *list++ = ((TCB*)q)->tskid;
747: }
748: }
749: ercd = n;
750: }
751: END_DISABLE_INTERRUPT;
752:
753: return ercd;
754: }
755:
756: #endif
757: #endif