comparison src/nucleus/mbc.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4e78acac3d88
1 /*************************************************************************/
2 /* */
3 /* Copyright Mentor Graphics Corporation 2002 */
4 /* All Rights Reserved. */
5 /* */
6 /* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS */
7 /* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS */
8 /* SUBJECT TO LICENSE TERMS. */
9 /* */
10 /*************************************************************************/
11
12 /*************************************************************************/
13 /* */
14 /* FILE NAME VERSION */
15 /* */
16 /* mbc.c Nucleus PLUS 1.14 */
17 /* */
18 /* COMPONENT */
19 /* */
20 /* MB - Mailbox Management */
21 /* */
22 /* DESCRIPTION */
23 /* */
24 /* This file contains the core routines for the Mailbox management */
25 /* component. */
26 /* */
27 /* DATA STRUCTURES */
28 /* */
29 /* None */
30 /* */
31 /* FUNCTIONS */
32 /* */
33 /* MBC_Create_Mailbox Create a mailbox */
34 /* MBC_Delete_Mailbox Delete a mailbox */
35 /* MBC_Send_To_Mailbox Send a mailbox message */
36 /* MBC_Receive_From_Mailbox Receive a mailbox message */
37 /* MBC_Cleanup Cleanup on timeout or a */
38 /* terminate condition */
39 /* */
40 /* DEPENDENCIES */
41 /* */
42 /* cs_extr.h Common Service functions */
43 /* tc_extr.h Thread Control functions */
44 /* mb_extr.h Mailbox functions */
45 /* hi_extr.h History functions */
46 /* */
47 /* HISTORY */
48 /* */
49 /* DATE REMARKS */
50 /* */
51 /* 03-01-1993 Created initial version 1.0 */
52 /* 04-19-1993 Verified version 1.0 */
53 /* 08-09-1993 Corrected pointer retrieval */
54 /* loop, resulting in version 1.0a */
55 /* 08-09-1993 Verified version 1.0a */
56 /* 03-01-1994 Moved non-core functions into */
57 /* supplemental files, changed */
58 /* function interfaces to match */
59 /* those in prototype, added */
60 /* register options, changed */
61 /* protection logic to reduce */
62 /* overhead, resulting in */
63 /* version 1.1 */
64 /* */
65 /* 03-18-1994 Verified version 1.1 */
66 /* 04-17-1996 updated to version 1.2 */
67 /* 03-24-1998 Released version 1.3 */
68 /* 03-26-1999 Released 1.11m (new release */
69 /* numbering scheme) */
70 /* 04-17-2002 Released version 1.13m */
71 /* 11-07-2002 Released version 1.14 */
72 /*************************************************************************/
73 #define NU_SOURCE_FILE
74
75
76 #include "cs_extr.h" /* Common service functions */
77 #include "tc_extr.h" /* Thread control functions */
78 #include "mb_extr.h" /* Mailbox functions */
79 #include "hi_extr.h" /* History functions */
80 #include "profiler.h" /* ProView interface */
81
82 /* Define external inner-component global data references. */
83
84 extern CS_NODE *MBD_Created_Mailboxes_List;
85 extern UNSIGNED MBD_Total_Mailboxes;
86 extern TC_PROTECT MBD_List_Protect;
87
88
89 /* Define internal component function prototypes. */
90
91 VOID MBC_Cleanup(VOID *information);
92
93
94 /*************************************************************************/
95 /* */
96 /* FUNCTION */
97 /* */
98 /* MBC_Create_Mailbox */
99 /* */
100 /* DESCRIPTION */
101 /* */
102 /* This function creates a mailbox and then places it on the list */
103 /* of created mailboxes. */
104 /* */
105 /* CALLED BY */
106 /* */
107 /* Application */
108 /* MBCE_Create_Mailbox Error checking shell */
109 /* */
110 /* CALLS */
111 /* */
112 /* CSC_Place_On_List Add node to linked-list */
113 /* [HIC_Make_History_Entry] Make entry in history log */
114 /* [TCT_Check_Stack] Stack checking function */
115 /* TCT_Protect Data structure protect */
116 /* TCT_Unprotect Un-protect data structure */
117 /* */
118 /* INPUTS */
119 /* */
120 /* mailbox_ptr Mailbox control block pointer*/
121 /* name Mailbox name */
122 /* suspend_type Suspension type */
123 /* */
124 /* OUTPUTS */
125 /* */
126 /* NU_SUCCESS */
127 /* */
128 /* HISTORY */
129 /* */
130 /* DATE REMARKS */
131 /* */
132 /* 03-01-1993 Created initial version 1.0 */
133 /* 04-19-1993 Verified version 1.0 */
134 /* 03-01-1994 Changed function interface to */
135 /* match the prototype, added */
136 /* register variable logic, */
137 /* resulting in version 1.1 */
138 /* */
139 /* 03-18-1994 Verified version 1.1 */
140 /* */
141 /*************************************************************************/
142 STATUS MBC_Create_Mailbox(NU_MAILBOX *mailbox_ptr, CHAR *name,
143 OPTION suspend_type)
144 {
145
146 R1 MB_MCB *mailbox; /* Mailbox control block ptr */
147 INT i; /* Working index variable */
148 NU_SUPERV_USER_VARIABLES
149
150 /* Switch to supervisor mode */
151 NU_SUPERVISOR_MODE();
152
153 /* Move input mailbox pointer into internal pointer. */
154 mailbox = (MB_MCB *) mailbox_ptr;
155
156 #ifdef NU_ENABLE_STACK_CHECK
157
158 /* Call stack checking function to check for an overflow condition. */
159 TCT_Check_Stack();
160
161 #endif
162
163 #ifdef NU_ENABLE_HISTORY
164
165 /* Make an entry that corresponds to this function in the system history
166 log. */
167 HIC_Make_History_Entry(NU_CREATE_MAILBOX_ID, (UNSIGNED) mailbox,
168 (UNSIGNED) name, (UNSIGNED) suspend_type);
169
170 #endif
171
172 /* First, clear the mailbox ID just in case it is an old Mailbox
173 Control Block. */
174 mailbox -> mb_id = 0;
175
176 /* Fill in the mailbox name. */
177 for (i = 0; i < NU_MAX_NAME; i++)
178 mailbox -> mb_name[i] = name[i];
179
180 /* Clear the message present flag- initial it to "no message present." */
181 mailbox -> mb_message_present = NU_FALSE;
182
183 /* Setup the mailbox suspension type. */
184 if (suspend_type == NU_FIFO)
185
186 /* FIFO suspension is selected, setup the flag accordingly. */
187 mailbox -> mb_fifo_suspend = NU_TRUE;
188 else
189
190 /* Priority suspension is selected. */
191 mailbox -> mb_fifo_suspend = NU_FALSE;
192
193 /* Clear the suspension list pointer. */
194 mailbox -> mb_suspension_list = NU_NULL;
195
196 /* Clear the number of tasks waiting on the mailbox counter. */
197 mailbox -> mb_tasks_waiting = 0;
198
199 /* Initialize link pointers. */
200 mailbox -> mb_created.cs_previous = NU_NULL;
201 mailbox -> mb_created.cs_next = NU_NULL;
202
203 /* Protect against access to the list of created mailboxes. */
204 TCT_Protect(&MBD_List_Protect);
205
206 /* At this point the mailbox is completely built. The ID can now be
207 set and it can be linked into the created mailbox list. */
208 mailbox -> mb_id = MB_MAILBOX_ID;
209
210 /* Link the mailbox into the list of created mailboxes and increment the
211 total number of mailboxes in the system. */
212 CSC_Place_On_List(&MBD_Created_Mailboxes_List, &(mailbox -> mb_created));
213 MBD_Total_Mailboxes++;
214
215 #ifdef INCLUDE_PROVIEW
216 _RTProf_DumpMailBox(RT_PROF_CREATE_MAILBOX,mailbox,RT_PROF_OK);
217 #endif /* INCLUDE_PROVIEW */
218 /* Release protection against access to the list of created mailboxes. */
219 TCT_Unprotect();
220
221 /* Return to user mode */
222 NU_USER_MODE();
223
224 /* Return successful completion. */
225 return(NU_SUCCESS);
226 }
227
228
229 /*************************************************************************/
230 /* */
231 /* FUNCTION */
232 /* */
233 /* MBC_Delete_Mailbox */
234 /* */
235 /* DESCRIPTION */
236 /* */
237 /* This function deletes a mailbox and removes it from the list of */
238 /* created mailboxes. All tasks suspended on the mailbox are */
239 /* resumed. Note that this function does not free the memory */
240 /* associated with the mailbox control block. */
241 /* */
242 /* CALLED BY */
243 /* */
244 /* Application */
245 /* MBCE_Delete_Mailbox Error checking shell */
246 /* */
247 /* CALLS */
248 /* */
249 /* CSC_Remove_From_List Remove node from list */
250 /* [HIC_Make_History_Entry] Make entry in history log */
251 /* TCC_Resume_Task Resume a suspended task */
252 /* [TCT_Check_Stack] Stack checking function */
253 /* TCT_Control_To_System Transfer control to system */
254 /* TCT_Protect Protect created list */
255 /* TCT_Set_Current_Protect Setup current protection ptr */
256 /* TCT_System_Protect Protect against system access*/
257 /* TCT_System_Unprotect Release system protection */
258 /* TCT_Unprotect Release protection */
259 /* */
260 /* INPUTS */
261 /* */
262 /* mailbox_ptr Mailbox control block pointer*/
263 /* */
264 /* OUTPUTS */
265 /* */
266 /* NU_SUCCESS */
267 /* */
268 /* HISTORY */
269 /* */
270 /* DATE REMARKS */
271 /* */
272 /* 03-01-1993 Created initial version 1.0 */
273 /* 04-19-1993 Verified version 1.0 */
274 /* 03-01-1994 Changed function interface to */
275 /* match the prototype, added */
276 /* register variable logic, */
277 /* optimized protection logic, */
278 /* resulting in version 1.1 */
279 /* */
280 /* 03-18-1994 Verified version 1.1 */
281 /* */
282 /*************************************************************************/
283 STATUS MBC_Delete_Mailbox(NU_MAILBOX *mailbox_ptr)
284 {
285
286 R1 MB_MCB *mailbox; /* Mailbox control block ptr */
287 MB_SUSPEND *suspend_ptr; /* Suspend block pointer */
288 MB_SUSPEND *next_ptr; /* Next suspend block pointer*/
289 STATUS preempt; /* Status for resume call */
290 NU_SUPERV_USER_VARIABLES
291
292 /* Switch to supervisor mode */
293 NU_SUPERVISOR_MODE();
294
295 /* Move input mailbox pointer into internal pointer. */
296 mailbox = (MB_MCB *) mailbox_ptr;
297
298 #ifdef NU_ENABLE_STACK_CHECK
299
300 /* Call stack checking function to check for an overflow condition. */
301 TCT_Check_Stack();
302
303 #endif
304
305 #ifdef NU_ENABLE_HISTORY
306
307 /* Make an entry that corresponds to this function in the system history
308 log. */
309 HIC_Make_History_Entry(NU_DELETE_MAILBOX_ID, (UNSIGNED) mailbox,
310 (UNSIGNED) 0, (UNSIGNED) 0);
311
312 #endif
313
314 /* Call protection just in case another thread is using the mailbox. */
315 TCT_System_Protect();
316
317 #ifdef INCLUDE_PROVIEW
318 _RTProf_DumpMailBox(RT_PROF_DELETE_MAILBOX,mailbox,RT_PROF_OK);
319 #endif /* INCLUDE_PROVIEW */
320 /* Clear the mailbox ID. */
321 mailbox -> mb_id = 0;
322
323 /* Clear protection. */
324 TCT_Unprotect();
325
326 /* Protect against access to the list of created mailboxes. */
327 TCT_Protect(&MBD_List_Protect);
328
329 /* Remove the mailbox from the list of created mailboxes. */
330 CSC_Remove_From_List(&MBD_Created_Mailboxes_List,
331 &(mailbox -> mb_created));
332
333 /* Decrement the total number of created mailboxes. */
334 MBD_Total_Mailboxes--;
335
336 /* Pickup the suspended task pointer list. */
337 suspend_ptr = mailbox -> mb_suspension_list;
338
339 /* Walk the chain task(s) currently suspended on the mailbox. */
340 preempt = 0;
341 while (suspend_ptr)
342 {
343
344 /* Protect against system access. */
345 TCT_System_Protect();
346
347 /* Resume the suspended task. Insure that the status returned is
348 NU_MAILBOX_DELETED. */
349 suspend_ptr -> mb_return_status = NU_MAILBOX_DELETED;
350
351 /* Point to the next suspend structure in the link. */
352 next_ptr = (MB_SUSPEND *) (suspend_ptr -> mb_suspend_link.cs_next);
353
354 /* Resume the specified task. */
355 preempt = preempt |
356 TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task,
357 NU_MAILBOX_SUSPEND);
358
359 /* Determine if the next is the same as the head pointer. */
360 if (next_ptr == mailbox -> mb_suspension_list)
361
362 /* Clear the suspension pointer to signal the end of the list
363 traversal. */
364 suspend_ptr = NU_NULL;
365 else
366
367 /* Position the suspend pointer to the next suspend block. */
368 suspend_ptr = next_ptr;
369
370 /* Setup current protection pointer. */
371 TCT_Set_Current_Protect(&MBD_List_Protect);
372
373 /* Unprotect the system protection. */
374 TCT_System_Unprotect();
375 }
376
377 /* Determine if preemption needs to occur. */
378 if (preempt)
379
380 /* Transfer control to system to facilitate preemption. */
381 TCT_Control_To_System();
382
383 /* Release protection against access to the list of created mailboxes. */
384 TCT_Unprotect();
385
386 /* Return to user mode */
387 NU_USER_MODE();
388
389 /* Return a successful completion. */
390 return(NU_SUCCESS);
391 }
392
393
394 /*************************************************************************/
395 /* */
396 /* FUNCTION */
397 /* */
398 /* MBC_Send_To_Mailbox */
399 /* */
400 /* DESCRIPTION */
401 /* */
402 /* This function sends a 4-word message to the specified mailbox. */
403 /* If there are one or more tasks suspended on the mailbox for a */
404 /* message, the message is copied into the message area of the */
405 /* first task waiting and that task is resumed. If the mailbox */
406 /* is full, suspension of the calling task is possible. */
407 /* */
408 /* CALLED BY */
409 /* */
410 /* Application */
411 /* MBCE_Send_To_Mailbox Error checking shell */
412 /* */
413 /* CALLS */
414 /* */
415 /* CSC_Place_On_List Place on suspend list */
416 /* CSC_Priority_Place_On_List Place on priority list */
417 /* CSC_Remove_From_List Remove from suspend list */
418 /* [HIC_Make_History_Entry] Make entry in history log */
419 /* TCC_Resume_Task Resume a suspended task */
420 /* TCC_Suspend_Task Suspend calling task */
421 /* TCC_Task_Priority Pickup task's priority */
422 /* [TCT_Check_Stack] Stack checking function */
423 /* TCT_Control_To_System Transfer control to system */
424 /* TCT_Current_Thread Pickup current thread pointer*/
425 /* TCT_System_Protect Protect against system access*/
426 /* TCT_Unprotect Release protection */
427 /* */
428 /* INPUTS */
429 /* */
430 /* mailbox_ptr Mailbox control block pointer*/
431 /* message Pointer to message to send */
432 /* suspend Suspension option if full */
433 /* */
434 /* OUTPUTS */
435 /* */
436 /* NU_SUCCESS If service is successful */
437 /* NU_MAILBOX_FULL If mailbox is currently full */
438 /* NU_TIMEOUT If timeout on service expires*/
439 /* NU_MAILBOX_DELETED If mailbox is deleted during */
440 /* suspension */
441 /* NU_MAILBOX_RESET If mailbox is deleted during */
442 /* suspension */
443 /* */
444 /* HISTORY */
445 /* */
446 /* DATE REMARKS */
447 /* */
448 /* 03-01-1993 Created initial version 1.0 */
449 /* 04-19-1993 Verified version 1.0 */
450 /* 03-01-1994 Changed function interface to */
451 /* match the prototype, added */
452 /* register variable logic, */
453 /* optimized protection logic, */
454 /* resulting in version 1.1 */
455 /* */
456 /* 03-18-1994 Verified version 1.1 */
457 /* */
458 /*************************************************************************/
459 STATUS MBC_Send_To_Mailbox(NU_MAILBOX *mailbox_ptr, VOID *message,
460 UNSIGNED suspend)
461 {
462
463 R1 MB_MCB *mailbox; /* Mailbox control block ptr */
464 MB_SUSPEND suspend_block; /* Allocate suspension block */
465 R2 MB_SUSPEND *suspend_ptr; /* Pointer to suspend block */
466 R3 UNSIGNED *source_ptr; /* Pointer to source */
467 R4 UNSIGNED *destination_ptr; /* Pointer to destination */
468 TC_TCB *task; /* Task pointer */
469 STATUS preempt; /* Preempt flag */
470 STATUS status; /* Completion status */
471 NU_SUPERV_USER_VARIABLES
472
473 /* Switch to supervisor mode */
474 NU_SUPERVISOR_MODE();
475
476 /* Move input mailbox pointer into internal pointer. */
477 mailbox = (MB_MCB *) mailbox_ptr;
478
479
480 #ifdef NU_ENABLE_STACK_CHECK
481
482 /* Call stack checking function to check for an overflow condition. */
483 TCT_Check_Stack();
484
485 #endif
486
487 #ifdef NU_ENABLE_HISTORY
488
489 /* Make an entry that corresponds to this function in the system history
490 log. */
491 HIC_Make_History_Entry(NU_SEND_TO_MAILBOX_ID, (UNSIGNED) mailbox,
492 (UNSIGNED) message, (UNSIGNED) suspend);
493
494 #endif
495
496 /* Initialize the status as successful. */
497 status = NU_SUCCESS;
498
499 /* Protect against simultaneous access to the mailbox. */
500 TCT_System_Protect();
501
502 /* Determine if the mailbox is empty or full. */
503 if (mailbox -> mb_message_present)
504 {
505
506 /* Mailbox already has a message. Determine if suspension is
507 required. */
508 if (suspend)
509 {
510
511 /* Suspension is requested. */
512
513 /* Increment the number of tasks waiting. */
514 mailbox -> mb_tasks_waiting++;
515
516 #ifdef INCLUDE_PROVIEW
517 _RTProf_DumpMailBox(RT_PROF_SEND_TO_MAILBOX,mailbox,RT_PROF_WAIT);
518 #endif /* INCLUDE_PROVIEW */
519
520 /* Setup the suspend block and suspend the calling task. */
521 suspend_ptr = &suspend_block;
522 suspend_ptr -> mb_mailbox = mailbox;
523 suspend_ptr -> mb_suspend_link.cs_next = NU_NULL;
524 suspend_ptr -> mb_suspend_link.cs_previous = NU_NULL;
525 suspend_ptr -> mb_message_area = (UNSIGNED *) message;
526 task = (TC_TCB *) TCT_Current_Thread();
527 suspend_ptr -> mb_suspended_task = task;
528
529 /* Determine if priority or FIFO suspension is associated with the
530 mailbox. */
531 if (mailbox -> mb_fifo_suspend)
532 {
533
534 /* FIFO suspension is required. Link the suspend block into
535 the list of suspended tasks on this mailbox. */
536 CSC_Place_On_List((CS_NODE **) &(mailbox ->mb_suspension_list),
537 &(suspend_ptr -> mb_suspend_link));
538 }
539 else
540 {
541
542 /* Get the priority of the current thread so the suspend block
543 can be placed in the appropriate place. */
544 suspend_ptr -> mb_suspend_link.cs_priority =
545 TCC_Task_Priority(task);
546
547 CSC_Priority_Place_On_List((CS_NODE **)
548 &(mailbox -> mb_suspension_list),
549 &(suspend_ptr -> mb_suspend_link));
550 }
551
552 /* Finally, suspend the calling task. Note that the suspension call
553 automatically clears the protection on the mailbox. */
554 TCC_Suspend_Task((NU_TASK *) task, NU_MAILBOX_SUSPEND,
555 MBC_Cleanup, suspend_ptr, suspend);
556
557 /* Pickup the return status. */
558 status = suspend_ptr -> mb_return_status;
559 }
560 else
561 {
562
563 /* Return a status of NU_MAILBOX_FULL because there is no
564 room in the mailbox for the message. */
565 status = NU_MAILBOX_FULL;
566 #ifdef INCLUDE_PROVIEW
567 _RTProf_DumpMailBox(RT_PROF_SEND_TO_MAILBOX,mailbox,RT_PROF_FAIL);
568 #endif /* INCLUDE_PROVIEW */
569
570 }
571 }
572 else
573 {
574
575 /* Determine if a task is waiting on the mailbox. */
576 if (mailbox -> mb_suspension_list)
577 {
578
579 /* Task is waiting on mailbox for a message. */
580
581 /* Decrement the number of tasks waiting on mailbox. */
582 mailbox -> mb_tasks_waiting--;
583
584 #ifdef INCLUDE_PROVIEW
585 _RTProf_DumpMailBox(RT_PROF_SEND_TO_MAILBOX,mailbox,RT_PROF_OK);
586 #endif /* INCLUDE_PROVIEW */
587
588 /* Remove the first suspended block from the list. */
589 suspend_ptr = mailbox -> mb_suspension_list;
590 CSC_Remove_From_List((CS_NODE **)
591 &(mailbox -> mb_suspension_list),
592 &(suspend_ptr -> mb_suspend_link));
593
594 /* Setup the source and destination pointers. */
595 source_ptr = (UNSIGNED *) message;
596 destination_ptr = suspend_ptr -> mb_message_area;
597
598 /* Copy the message directly into the waiting task's
599 destination. */
600 *destination_ptr = *source_ptr;
601 *(destination_ptr + 1) = *(source_ptr + 1);
602 *(destination_ptr + 2) = *(source_ptr + 2);
603 *(destination_ptr + 3) = *(source_ptr + 3);
604
605 /* Setup the appropriate return value. */
606 suspend_ptr -> mb_return_status = NU_SUCCESS;
607
608 /* Wakeup the waiting task and check for preemption. */
609 preempt =
610 TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task,
611 NU_MAILBOX_SUSPEND);
612
613 /* Determine if preemption needs to take place. */
614 if (preempt)
615
616 /* Transfer control to the system if the resumed task function
617 detects a preemption condition. */
618 TCT_Control_To_System();
619 }
620 else
621 {
622
623 /* Mailbox is empty and no task is waiting. */
624
625 /* Setup the source and destination pointers. */
626 source_ptr = (UNSIGNED *) message;
627 destination_ptr = &(mailbox -> mb_message_area[0]);
628
629 /* Place the message in the mailbox. */
630 *destination_ptr = *source_ptr;
631 *(destination_ptr + 1) = *(source_ptr + 1);
632 *(destination_ptr + 2) = *(source_ptr + 2);
633 *(destination_ptr + 3) = *(source_ptr + 3);
634
635 /* Indicate that the mailbox has a message. */
636 mailbox -> mb_message_present = NU_TRUE;
637
638 #ifdef INCLUDE_PROVIEW
639 _RTProf_DumpMailBox(RT_PROF_SEND_TO_MAILBOX,mailbox,RT_PROF_OK);
640 #endif /* INCLUDE_PROVIEW */
641 }
642 }
643
644 /* Release protection. */
645 TCT_Unprotect();
646
647 /* Return to user mode */
648 NU_USER_MODE();
649
650 /* Return the completion status. */
651 return(status);
652 }
653
654
655 /*************************************************************************/
656 /* */
657 /* FUNCTION */
658 /* */
659 /* MBC_Receive_From_Mailbox */
660 /* */
661 /* DESCRIPTION */
662 /* */
663 /* This function receives a message from the specified mailbox. */
664 /* If there is a message currently in the mailbox, the message is */
665 /* removed from the mailbox and placed in the caller's area. */
666 /* Otherwise, if no message is present in the mailbox, suspension */
667 /* of the calling task is possible. */
668 /* */
669 /* CALLED BY */
670 /* */
671 /* Application */
672 /* MBCE_Receive_From_Mailbox Error checking shell */
673 /* */
674 /* CALLS */
675 /* */
676 /* CSC_Place_On_List Place on suspend list */
677 /* CSC_Priority_Place_On_List Place on priority list */
678 /* CSC_Remove_From_List Remove from suspend list */
679 /* [HIC_Make_History_Entry] Make entry in history log */
680 /* TCC_Resume_Task Resume a suspended task */
681 /* TCC_Suspend_Task Suspend calling task */
682 /* TCC_Task_Priority Pickup task priority */
683 /* [TCT_Check_Stack] Stack checking function */
684 /* TCT_Control_To_System Transfer control to system */
685 /* TCT_Current_Thread Pickup current thread pointer*/
686 /* TCT_System_Protect Protect mailbox */
687 /* TCT_Unprotect Release protection */
688 /* */
689 /* INPUTS */
690 /* */
691 /* mailbox_ptr Mailbox control block pointer*/
692 /* message Pointer to message to send */
693 /* suspend Suspension option if empty */
694 /* */
695 /* OUTPUTS */
696 /* */
697 /* NU_SUCCESS If service is successful */
698 /* NU_MAILBOX_EMPTY If mailbox is currently empty*/
699 /* NU_TIMEOUT If timeout on service expires*/
700 /* NU_MAILBOX_DELETED If mailbox is deleted during */
701 /* suspension */
702 /* NU_MAILBOX_RESET If mailbox is deleted during */
703 /* suspension */
704 /* */
705 /* HISTORY */
706 /* */
707 /* DATE REMARKS */
708 /* */
709 /* 03-01-1993 Created initial version 1.0 */
710 /* 04-19-1993 Verified version 1.0 */
711 /* 03-01-1994 Changed function interface to */
712 /* match the prototype, added */
713 /* register variable logic, */
714 /* optimized protection logic, */
715 /* resulting in version 1.1 */
716 /* */
717 /* 03-18-1994 Verified version 1.1 */
718 /* */
719 /*************************************************************************/
720 STATUS MBC_Receive_From_Mailbox(NU_MAILBOX *mailbox_ptr, VOID *message,
721 UNSIGNED suspend)
722 {
723
724 R1 MB_MCB *mailbox; /* Mailbox control block ptr */
725 MB_SUSPEND suspend_block; /* Allocate suspension block */
726 R2 MB_SUSPEND *suspend_ptr; /* Pointer to suspend block */
727 R3 UNSIGNED *source_ptr; /* Pointer to source */
728 R4 UNSIGNED *destination_ptr; /* Pointer to destination */
729 TC_TCB *task; /* Task pointer */
730 STATUS preempt; /* Preemption flag */
731 STATUS status; /* Completion status */
732 NU_SUPERV_USER_VARIABLES
733
734 /* Switch to supervisor mode */
735 NU_SUPERVISOR_MODE();
736
737 /* Move input mailbox pointer into internal pointer. */
738 mailbox = (MB_MCB *) mailbox_ptr;
739
740 #ifdef NU_ENABLE_STACK_CHECK
741
742 /* Call stack checking function to check for an overflow condition. */
743 TCT_Check_Stack();
744
745 #endif
746
747 #ifdef NU_ENABLE_HISTORY
748
749 /* Make an entry that corresponds to this function in the system history
750 log. */
751 HIC_Make_History_Entry(NU_RECEIVE_FROM_MAILBOX_ID, (UNSIGNED) mailbox,
752 (UNSIGNED) message, (UNSIGNED) suspend);
753
754 #endif
755
756 /* Initialize the status as successful. */
757 status = NU_SUCCESS;
758
759 /* Protect against simultaneous access to the mailbox. */
760 TCT_System_Protect();
761
762 /* Determine if the mailbox is empty or full. */
763 if (mailbox -> mb_message_present)
764 {
765
766 /* Copy message from mailbox into the caller's area. */
767
768 /* Setup the source and destination pointers. */
769 source_ptr = &(mailbox -> mb_message_area[0]);
770 destination_ptr = (UNSIGNED *) message;
771
772 /* Copy the message directly into the waiting task's
773 destination. */
774 *destination_ptr = *source_ptr;
775 *(destination_ptr + 1) = *(source_ptr + 1);
776 *(destination_ptr + 2) = *(source_ptr + 2);
777 *(destination_ptr + 3) = *(source_ptr + 3);
778
779 /* Determine if another task is waiting to place something into the
780 mailbox. */
781 if (mailbox -> mb_suspension_list)
782 {
783
784 /* Yes, another task is waiting to send something to the
785 mailbox. */
786
787 /* Decrement the number of tasks waiting counter. */
788 mailbox -> mb_tasks_waiting--;
789
790 #ifdef INCLUDE_PROVIEW
791 _RTProf_DumpMailBox(RT_PROF_RECEIVE_FROM_MAILBOX,mailbox,RT_PROF_OK);
792 #endif /* INCLUDE_PROVIEW */
793 /* Remove the first suspended block from the list. */
794 suspend_ptr = mailbox -> mb_suspension_list;
795 CSC_Remove_From_List((CS_NODE **)
796 &(mailbox -> mb_suspension_list),
797 &(suspend_ptr -> mb_suspend_link));
798
799 /* Setup the source and destination pointers. */
800 source_ptr = suspend_ptr -> mb_message_area;
801 destination_ptr = &(mailbox -> mb_message_area[0]);
802
803 /* Copy the message directly into the waiting task's
804 destination. */
805 *destination_ptr = *source_ptr;
806 *(destination_ptr + 1) = *(source_ptr + 1);
807 *(destination_ptr + 2) = *(source_ptr + 2);
808 *(destination_ptr + 3) = *(source_ptr + 3);
809
810 /* Setup the appropriate return value. */
811 suspend_ptr -> mb_return_status = NU_SUCCESS;
812
813 /* Resume the suspended task. */
814 preempt =
815 TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task,
816 NU_MAILBOX_SUSPEND);
817
818 /* Determine if a preempt condition is present. */
819 if (preempt)
820
821 /* Transfer control to the system if the resumed task function
822 detects a preemption condition. */
823 TCT_Control_To_System();
824 }
825 else
826 {
827
828 /* Clear the message present flag. */
829 mailbox -> mb_message_present = NU_FALSE;
830
831 #ifdef INCLUDE_PROVIEW
832 _RTProf_DumpMailBox(RT_PROF_RECEIVE_FROM_MAILBOX,mailbox,RT_PROF_OK);
833 #endif /* INCLUDE_PROVIEW */
834
835 }
836
837 }
838 else
839 {
840
841 /* Mailbox is empty. Determine if suspension is required. */
842 if (suspend)
843 {
844
845 /* Suspension is required. */
846
847 /* Increment the number of tasks waiting on the mailbox counter. */
848 mailbox -> mb_tasks_waiting++;
849
850 #ifdef INCLUDE_PROVIEW
851 _RTProf_DumpMailBox(RT_PROF_RECEIVE_FROM_MAILBOX,mailbox,RT_PROF_WAIT);
852 #endif /* INCLUDE_PROVIEW */
853
854 /* Setup the suspend block and suspend the calling task. */
855 suspend_ptr = &suspend_block;
856 suspend_ptr -> mb_mailbox = mailbox;
857 suspend_ptr -> mb_suspend_link.cs_next = NU_NULL;
858 suspend_ptr -> mb_suspend_link.cs_previous = NU_NULL;
859 suspend_ptr -> mb_message_area = (UNSIGNED *) message;
860 task = (TC_TCB *) TCT_Current_Thread();
861 suspend_ptr -> mb_suspended_task = task;
862
863 /* Determine if priority or FIFO suspension is associated with the
864 mailbox. */
865 if (mailbox -> mb_fifo_suspend)
866 {
867
868 /* FIFO suspension is required. Link the suspend block into
869 the list of suspended tasks on this mailbox. */
870 CSC_Place_On_List((CS_NODE **) &(mailbox ->mb_suspension_list),
871 &(suspend_ptr -> mb_suspend_link));
872 }
873 else
874 {
875
876 /* Get the priority of the current thread so the suspend block
877 can be placed in the appropriate place. */
878 suspend_ptr -> mb_suspend_link.cs_priority =
879 TCC_Task_Priority(task);
880
881 CSC_Priority_Place_On_List((CS_NODE **)
882 &(mailbox -> mb_suspension_list),
883 &(suspend_block.mb_suspend_link));
884 }
885
886 /* Finally, suspend the calling task. Note that the suspension call
887 automatically clears the protection on the mailbox. */
888 TCC_Suspend_Task((NU_TASK *) task, NU_MAILBOX_SUSPEND,
889 MBC_Cleanup, &suspend_block, suspend);
890
891 /* Pickup the return status. */
892 status = suspend_ptr -> mb_return_status;
893 }
894 else
895 {
896
897 /* Return a status of NU_MAILBOX_EMPTY because there is
898 nothing in the mailbox. */
899 status = NU_MAILBOX_EMPTY;
900
901 #ifdef INCLUDE_PROVIEW
902 _RTProf_DumpMailBox(RT_PROF_RECEIVE_FROM_MAILBOX,mailbox,RT_PROF_FAIL);
903 #endif /* INCLUDE_PROVIEW */
904 }
905
906 }
907
908 /* Release protection. */
909 TCT_Unprotect();
910
911 /* Return to user mode */
912 NU_USER_MODE();
913
914 /* Return the completion status. */
915 return(status);
916 }
917
918
919 /*************************************************************************/
920 /* */
921 /* FUNCTION */
922 /* */
923 /* MBC_Cleanup */
924 /* */
925 /* DESCRIPTION */
926 /* */
927 /* This function is responsible for removing a suspension block */
928 /* from a mailbox. It is not called unless a timeout or a task */
929 /* terminate is in progress. Note that protection is already in */
930 /* effect - the same protection at suspension time. */
931 /* */
932 /* CALLED BY */
933 /* */
934 /* TCC_Timeout Task timeout */
935 /* TCC_Terminate Task terminate */
936 /* */
937 /* CALLS */
938 /* */
939 /* CSC_Remove_From_List Remove suspend block from */
940 /* the suspension list */
941 /* */
942 /* INPUTS */
943 /* */
944 /* information Pointer to suspend block */
945 /* */
946 /* OUTPUTS */
947 /* */
948 /* None */
949 /* */
950 /* HISTORY */
951 /* */
952 /* DATE REMARKS */
953 /* */
954 /* 03-01-1993 Created initial version 1.0 */
955 /* 04-19-1993 Verified version 1.0 */
956 /* */
957 /*************************************************************************/
958 VOID MBC_Cleanup(VOID *information)
959 {
960
961 MB_SUSPEND *suspend_ptr; /* Suspension block pointer */
962 NU_SUPERV_USER_VARIABLES
963
964 /* Switch to supervisor mode */
965 NU_SUPERVISOR_MODE();
966
967 /* Use the information pointer as a suspend pointer. */
968 suspend_ptr = (MB_SUSPEND *) information;
969
970 /* By default, indicate that the service timed-out. It really does not
971 matter if this function is called from a terminate request since
972 the task does not resume. */
973 suspend_ptr -> mb_return_status = NU_TIMEOUT;
974
975 /* Decrement the number of tasks waiting counter. */
976 (suspend_ptr -> mb_mailbox) -> mb_tasks_waiting--;
977
978 /* Unlink the suspend block from the suspension list. */
979 CSC_Remove_From_List((CS_NODE **)
980 &((suspend_ptr -> mb_mailbox) -> mb_suspension_list),
981 &(suspend_ptr -> mb_suspend_link));
982
983 /* Return to user mode */
984 NU_USER_MODE();
985 }
986
987
988
989
990
991
992