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 "mailbox.h"
23:
24: #if USE_MAILBOX == 1
25:
26: Noinit(EXPORT MBXCB knl_mbxcb_table[NUM_MBXID]);
27: Noinit(EXPORT QUEUE knl_free_mbxcb);
28:
29:
30: 31: 32:
33: EXPORT ER knl_mailbox_initialize( void )
34: {
35: MBXCB *mbxcb, *end;
36:
37:
38: if ( NUM_MBXID < 1 ) {
39: return E_SYS;
40: }
41:
42:
43: QueInit(&knl_free_mbxcb);
44: end = knl_mbxcb_table + NUM_MBXID;
45: for ( mbxcb = knl_mbxcb_table; mbxcb < end; mbxcb++ ) {
46: mbxcb->mbxid = 0;
47: QueInsert(&mbxcb->wait_queue, &knl_free_mbxcb);
48: }
49:
50: return E_OK;
51: }
52:
53:
54: 55: 56:
57: SYSCALL ID tk_cre_mbx( CONST T_CMBX *pk_cmbx )
58: {
59: #if CHK_RSATR
60: const ATR VALID_MBXATR = {
61: TA_MPRI
62: |TA_TPRI
63: #if USE_OBJECT_NAME
64: |TA_DSNAME
65: #endif
66: };
67: #endif
68: MBXCB *mbxcb;
69: ID mbxid;
70: ER ercd;
71:
72: CHECK_RSATR(pk_cmbx->mbxatr, VALID_MBXATR);
73:
74: BEGIN_CRITICAL_SECTION;
75:
76: mbxcb = (MBXCB*)QueRemoveNext(&knl_free_mbxcb);
77: if ( mbxcb == NULL ) {
78: ercd = E_LIMIT;
79: } else {
80: mbxid = ID_MBX(mbxcb - knl_mbxcb_table);
81:
82:
83: QueInit(&mbxcb->wait_queue);
84: mbxcb->mbxid = mbxid;
85: mbxcb->exinf = pk_cmbx->exinf;
86: mbxcb->mbxatr = pk_cmbx->mbxatr;
87: mbxcb->mq_head.msgque[0] = NULL;
88: #if USE_OBJECT_NAME
89: if ( (pk_cmbx->mbxatr & TA_DSNAME) != 0 ) {
90: knl_strncpy((char*)mbxcb->name, (char*)pk_cmbx->dsname,
91: OBJECT_NAME_LENGTH);
92: }
93: #endif
94: ercd = mbxid;
95: }
96: END_CRITICAL_SECTION;
97:
98: return ercd;
99: }
100:
101: #ifdef USE_FUNC_TK_DEL_MBX
102: 103: 104:
105: SYSCALL ER tk_del_mbx( ID mbxid )
106: {
107: MBXCB *mbxcb;
108: ER ercd = E_OK;
109:
110: CHECK_MBXID(mbxid);
111:
112: mbxcb = get_mbxcb(mbxid);
113:
114: BEGIN_CRITICAL_SECTION;
115: if ( mbxcb->mbxid == 0 ) {
116: ercd = E_NOEXS;
117: } else {
118:
119: knl_wait_delete(&mbxcb->wait_queue);
120:
121:
122: QueInsert(&mbxcb->wait_queue, &knl_free_mbxcb);
123: mbxcb->mbxid = 0;
124: }
125: END_CRITICAL_SECTION;
126:
127: return ercd;
128: }
129: #endif
130:
131: 132: 133:
134: SYSCALL ER tk_snd_mbx( ID mbxid, T_MSG *pk_msg )
135: {
136: MBXCB *mbxcb;
137: TCB *tcb;
138: ER ercd = E_OK;
139:
140: CHECK_MBXID(mbxid);
141:
142: mbxcb = get_mbxcb(mbxid);
143:
144: BEGIN_CRITICAL_SECTION;
145: if (mbxcb->mbxid == 0) {
146: ercd = E_NOEXS;
147: goto error_exit;
148: }
149:
150: if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) {
151: if ( ((T_MSG_PRI*)pk_msg)->msgpri <= 0 ) {
152: ercd = E_PAR;
153: goto error_exit;
154: }
155: }
156:
157: if ( !isQueEmpty(&mbxcb->wait_queue) ) {
158:
159: tcb = (TCB*)(mbxcb->wait_queue.next);
160: *tcb->winfo.mbx.ppk_msg = pk_msg;
161: knl_wait_release_ok(tcb);
162:
163: } else {
164:
165: if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) {
166:
167: knl_queue_insert_mpri((T_MSG_PRI*)pk_msg, &mbxcb->mq_head);
168: } else {
169:
170: nextmsg(pk_msg) = NULL;
171: if ( headmsg(mbxcb) == NULL ) {
172: headmsg(mbxcb) = pk_msg;
173: } else {
174: nextmsg(mbxcb->mq_tail) = pk_msg;
175: }
176: mbxcb->mq_tail = pk_msg;
177: }
178: }
179:
180: error_exit:
181: END_CRITICAL_SECTION;
182:
183: return ercd;
184: }
185:
186: 187: 188:
189: LOCAL void mbx_chg_pri( TCB *tcb, INT oldpri )
190: {
191: MBXCB *mbxcb;
192:
193: mbxcb = get_mbxcb(tcb->wid);
194: knl_gcb_change_priority((GCB*)mbxcb, tcb);
195: }
196:
197: 198: 199:
200: LOCAL CONST WSPEC knl_wspec_mbx_tfifo = { TTW_MBX, NULL, NULL };
201: LOCAL CONST WSPEC knl_wspec_mbx_tpri = { TTW_MBX, mbx_chg_pri, NULL };
202:
203: 204: 205:
206: SYSCALL ER tk_rcv_mbx( ID mbxid, T_MSG **ppk_msg, TMO tmout )
207: {
208: MBXCB *mbxcb;
209: ER ercd = E_OK;
210:
211: CHECK_MBXID(mbxid);
212: CHECK_TMOUT(tmout);
213: CHECK_DISPATCH();
214:
215: mbxcb = get_mbxcb(mbxid);
216:
217: BEGIN_CRITICAL_SECTION;
218: if ( mbxcb->mbxid == 0 ) {
219: ercd = E_NOEXS;
220: goto error_exit;
221: }
222:
223: if ( headmsg(mbxcb) != NULL ) {
224:
225: *ppk_msg = headmsg(mbxcb);
226: headmsg(mbxcb) = nextmsg(*ppk_msg);
227: } else {
228:
229: knl_ctxtsk->wspec = ( (mbxcb->mbxatr & TA_TPRI) != 0 )?
230: &knl_wspec_mbx_tpri: &knl_wspec_mbx_tfifo;
231: knl_ctxtsk->wercd = &ercd;
232: knl_ctxtsk->winfo.mbx.ppk_msg = ppk_msg;
233: knl_gcb_make_wait((GCB*)mbxcb, tmout);
234: }
235:
236: error_exit:
237: END_CRITICAL_SECTION;
238:
239: return ercd;
240: }
241:
242: #ifdef USE_FUNC_TK_REF_MBX
243: 244: 245:
246: SYSCALL ER tk_ref_mbx( ID mbxid, T_RMBX *pk_rmbx )
247: {
248: MBXCB *mbxcb;
249: ER ercd = E_OK;
250:
251: CHECK_MBXID(mbxid);
252:
253: mbxcb = get_mbxcb(mbxid);
254:
255: BEGIN_CRITICAL_SECTION;
256: if ( mbxcb->mbxid == 0 ) {
257: ercd = E_NOEXS;
258: } else {
259: pk_rmbx->exinf = mbxcb->exinf;
260: pk_rmbx->wtsk = knl_wait_tskid(&mbxcb->wait_queue);
261: pk_rmbx->pk_msg = headmsg(mbxcb);
262: }
263: END_CRITICAL_SECTION;
264:
265: return ercd;
266: }
267: #endif
268:
269:
270: 271: 272:
273: #if USE_DBGSPT
274:
275: #if USE_OBJECT_NAME
276: 277: 278:
279: EXPORT ER knl_mailbox_getname(ID id, UB **name)
280: {
281: MBXCB *mbxcb;
282: ER ercd = E_OK;
283:
284: CHECK_MBXID(id);
285:
286: BEGIN_DISABLE_INTERRUPT;
287: mbxcb = get_mbxcb(id);
288: if ( mbxcb->mbxid == 0 ) {
289: ercd = E_NOEXS;
290: goto error_exit;
291: }
292: if ( (mbxcb->mbxatr & TA_DSNAME) == 0 ) {
293: ercd = E_OBJ;
294: goto error_exit;
295: }
296: *name = mbxcb->name;
297:
298: error_exit:
299: END_DISABLE_INTERRUPT;
300:
301: return ercd;
302: }
303: #endif
304:
305: #ifdef USE_FUNC_TD_LST_MBX
306: 307: 308:
309: SYSCALL INT td_lst_mbx( ID list[], INT nent )
310: {
311: MBXCB *mbxcb, *end;
312: INT n = 0;
313:
314: BEGIN_DISABLE_INTERRUPT;
315: end = knl_mbxcb_table + NUM_MBXID;
316: for ( mbxcb = knl_mbxcb_table; mbxcb < end; mbxcb++ ) {
317: if ( mbxcb->mbxid == 0 ) {
318: continue;
319: }
320:
321: if ( n++ < nent ) {
322: *list++ = mbxcb->mbxid;
323: }
324: }
325: END_DISABLE_INTERRUPT;
326:
327: return n;
328: }
329: #endif
330:
331: #ifdef USE_FUNC_TD_REF_MBX
332: 333: 334:
335: SYSCALL ER td_ref_mbx( ID mbxid, TD_RMBX *pk_rmbx )
336: {
337: MBXCB *mbxcb;
338: ER ercd = E_OK;
339:
340: CHECK_MBXID(mbxid);
341:
342: mbxcb = get_mbxcb(mbxid);
343:
344: BEGIN_DISABLE_INTERRUPT;
345: if ( mbxcb->mbxid == 0 ) {
346: ercd = E_NOEXS;
347: } else {
348: pk_rmbx->exinf = mbxcb->exinf;
349: pk_rmbx->wtsk = knl_wait_tskid(&mbxcb->wait_queue);
350: pk_rmbx->pk_msg = headmsg(mbxcb);
351: }
352: END_DISABLE_INTERRUPT;
353:
354: return ercd;
355: }
356: #endif
357:
358: #ifdef USE_FUNC_TD_MBX_QUE
359: 360: 361:
362: SYSCALL INT td_mbx_que( ID mbxid, ID list[], INT nent )
363: {
364: MBXCB *mbxcb;
365: QUEUE *q;
366: ER ercd = E_OK;
367:
368: CHECK_MBXID(mbxid);
369:
370: mbxcb = get_mbxcb(mbxid);
371:
372: BEGIN_DISABLE_INTERRUPT;
373: if ( mbxcb->mbxid == 0 ) {
374: ercd = E_NOEXS;
375: } else {
376: INT n = 0;
377: for ( q = mbxcb->wait_queue.next; q != &mbxcb->wait_queue; q = q->next ) {
378: if ( n++ < nent ) {
379: *list++ = ((TCB*)q)->tskid;
380: }
381: }
382: ercd = n;
383: }
384: END_DISABLE_INTERRUPT;
385:
386: return ercd;
387: }
388: #endif
389:
390: #endif
391: #endif