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