comparison nuc-fw/nucleus/pic.c @ 79:947b1f473960

beginning of nuc-fw
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 11 Aug 2013 07:17:25 +0000
parents
children
comparison
equal deleted inserted replaced
78:2c266d4339ff 79:947b1f473960
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 /* pic.c Nucleus PLUS 1.14 */
17 /* */
18 /* COMPONENT */
19 /* */
20 /* PI - Pipe Management */
21 /* */
22 /* DESCRIPTION */
23 /* */
24 /* This file contains the core routines for the pipe management */
25 /* component. */
26 /* */
27 /* DATA STRUCTURES */
28 /* */
29 /* None */
30 /* */
31 /* FUNCTIONS */
32 /* */
33 /* PIC_Create_Pipe Create a message pipe */
34 /* PIC_Delete_Pipe Delete a message pipe */
35 /* PIC_Send_To_Pipe Send message to a pipe */
36 /* PIC_Receive_From_Pipe Receive a message from pipe */
37 /* PIC_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 /* pi_extr.h Pipe 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, corrected bug in */
63 /* pipe reset, optimized item */
64 /* copy loops, resulting in */
65 /* version 1.1 */
66 /* */
67 /* 03-18-1994 Verified version 1.1 */
68 /* 04-17-1996 updated to version 1.2 */
69 /* 03-24-1998 Released version 1.3 */
70 /* 03-26-1999 Released 1.11m (new release */
71 /* numbering scheme) */
72 /* 04-17-2002 Released version 1.13m */
73 /* 11-07-2002 Released version 1.14 */
74 /*************************************************************************/
75 #define NU_SOURCE_FILE
76
77
78 #include "cs_extr.h" /* Common service functions */
79 #include "tc_extr.h" /* Thread control functions */
80 #include "pi_extr.h" /* Pipe functions */
81 #include "hi_extr.h" /* History functions */
82 #include "profiler.h" /* ProView interface */
83
84
85 /* Define external inner-component global data references. */
86
87 extern CS_NODE *PID_Created_Pipes_List;
88 extern UNSIGNED PID_Total_Pipes;
89 extern TC_PROTECT PID_List_Protect;
90
91
92 /* Define internal component function prototypes. */
93
94 VOID PIC_Cleanup(VOID *information);
95
96
97 /*************************************************************************/
98 /* */
99 /* FUNCTION */
100 /* */
101 /* PIC_Create_Pipe */
102 /* */
103 /* DESCRIPTION */
104 /* */
105 /* This function creates a pipe and then places it on the list */
106 /* of created pipes. */
107 /* */
108 /* CALLED BY */
109 /* */
110 /* Application */
111 /* PICE_Create_Pipe Error checking shell */
112 /* */
113 /* CALLS */
114 /* */
115 /* CSC_Place_On_List Add to node to linked-list */
116 /* [HIC_Make_History_Entry] Make entry in history log */
117 /* [TCT_Check_Stack] Stack checking function */
118 /* TCT_Protect Data structure protect */
119 /* TCT_Unprotect Un-protect data structure */
120 /* */
121 /* INPUTS */
122 /* */
123 /* pipe_ptr Pipe control block pointer */
124 /* name Pipe name */
125 /* start_address Starting address of actual */
126 /* pipe area */
127 /* pipe_size Total size of pipe in bytes */
128 /* message_type Type of message supported by */
129 /* the pipe (fixed/variable) */
130 /* message_size Size of message. Variable */
131 /* message-length pipes, this */
132 /* represents the maximum size*/
133 /* suspend_type Suspension type */
134 /* */
135 /* OUTPUTS */
136 /* */
137 /* NU_SUCCESS */
138 /* */
139 /* HISTORY */
140 /* */
141 /* DATE REMARKS */
142 /* */
143 /* 03-01-1993 Created initial version 1.0 */
144 /* 04-19-1993 Verified version 1.0 */
145 /* 03-01-1994 Changed function interfaces to */
146 /* match those in prototype, */
147 /* added register options, */
148 /* resulting in version 1.1 */
149 /* */
150 /* 03-18-1994 Verified version 1.1 */
151 /* */
152 /*************************************************************************/
153 STATUS PIC_Create_Pipe(NU_PIPE *pipe_ptr, CHAR *name,
154 VOID *start_address, UNSIGNED pipe_size,
155 OPTION message_type, UNSIGNED message_size,
156 OPTION suspend_type)
157 {
158
159 R1 PI_PCB *pipe; /* Pipe control block ptr */
160 INT i; /* Working index variable */
161 NU_SUPERV_USER_VARIABLES
162
163 /* Switch to supervisor mode */
164 NU_SUPERVISOR_MODE();
165
166 /* Move input pipe pointer into internal pointer. */
167 pipe = (PI_PCB *) pipe_ptr;
168
169
170 #ifdef NU_ENABLE_STACK_CHECK
171
172 /* Call stack checking function to check for an overflow condition. */
173 TCT_Check_Stack();
174
175 #endif
176
177 #ifdef NU_ENABLE_HISTORY
178
179 /* Make an entry that corresponds to this function in the system history
180 log. */
181 HIC_Make_History_Entry(NU_CREATE_PIPE_ID, (UNSIGNED) pipe,
182 (UNSIGNED) name, (UNSIGNED) start_address);
183
184 #endif
185
186 /* First, clear the pipe ID just in case it is an old pipe
187 Control Block. */
188 pipe -> pi_id = 0;
189
190 /* Fill in the pipe name. */
191 for (i = 0; i < NU_MAX_NAME; i++)
192 pipe -> pi_name[i] = name[i];
193
194 /* Setup the pipe suspension type. */
195 if (suspend_type == NU_FIFO)
196
197 /* FIFO suspension is selected, setup the flag accordingly. */
198 pipe -> pi_fifo_suspend = NU_TRUE;
199
200 else
201
202 /* Priority suspension is selected. */
203 pipe -> pi_fifo_suspend = NU_FALSE;
204
205 /* Setup the pipe message type. */
206 if (message_type == NU_FIXED_SIZE)
207
208 /* Fixed-size messages are required. */
209 pipe -> pi_fixed_size = NU_TRUE;
210 else
211
212 /* Variable-size messages are required. */
213 pipe -> pi_fixed_size = NU_FALSE;
214
215 /* Setup the message size. */
216 pipe -> pi_message_size = message_size;
217
218 /* Clear the messages counter. */
219 pipe -> pi_messages = 0;
220
221 /* Setup the actual pipe pointers. */
222 pipe -> pi_pipe_size = pipe_size;
223
224 /* Determine if the pipe's size needs to be adjusted. */
225 if (pipe -> pi_fixed_size)
226
227 /* The size of a fixed-size message pipe must be an even multiple of
228 the actual message size. */
229 pipe_size = (pipe_size/message_size) * message_size;
230
231 else
232
233 /* Insure that the size is in terms of UNSIGNED data elements. This
234 insures that the UNSIGNED word is never written past the end of
235 the pipe. */
236 pipe_size = (pipe_size/sizeof(UNSIGNED)) * sizeof(UNSIGNED);
237
238 pipe -> pi_available = pipe_size;
239 pipe -> pi_start = (BYTE_PTR) start_address;
240 pipe -> pi_end = pipe -> pi_start + pipe_size;
241 pipe -> pi_read = (BYTE_PTR) start_address;
242 pipe -> pi_write = (BYTE_PTR) start_address;
243
244 /* Clear the suspension list pointer. */
245 pipe -> pi_suspension_list = NU_NULL;
246
247 /* Clear the number of tasks waiting on the pipe counter. */
248 pipe -> pi_tasks_waiting = 0;
249
250 /* Clear the urgent message list pointer. */
251 pipe -> pi_urgent_list = NU_NULL;
252
253 /* Initialize link pointers. */
254 pipe -> pi_created.cs_previous = NU_NULL;
255 pipe -> pi_created.cs_next = NU_NULL;
256
257 /* Protect against access to the list of created pipes. */
258 TCT_Protect(&PID_List_Protect);
259
260 /* At this point the pipe is completely built. The ID can now be
261 set and it can be linked into the created pipe list. */
262 pipe -> pi_id = PI_PIPE_ID;
263
264 /* Link the pipe into the list of created pipes and increment the
265 total number of pipes in the system. */
266 CSC_Place_On_List(&PID_Created_Pipes_List, &(pipe -> pi_created));
267 PID_Total_Pipes++;
268
269 #ifdef INCLUDE_PROVIEW
270 _RTProf_DumpPipe(RT_PROF_CREATE_PIPE,pipe,RT_PROF_OK);
271 #endif /* INCLUDE_PROVIEW */
272
273 /* Release protection against access to the list of created pipes. */
274 TCT_Unprotect();
275
276 /* Return to user mode */
277 NU_USER_MODE();
278
279 /* Return successful completion. */
280 return(NU_SUCCESS);
281 }
282
283
284 /*************************************************************************/
285 /* */
286 /* FUNCTION */
287 /* */
288 /* PIC_Delete_Pipe */
289 /* */
290 /* DESCRIPTION */
291 /* */
292 /* This function deletes a pipe and removes it from the list of */
293 /* created pipes. All tasks suspended on the pipe are */
294 /* resumed. Note that this function does not free the memory */
295 /* associated with the pipe. */
296 /* */
297 /* CALLED BY */
298 /* */
299 /* Application */
300 /* PICE_Delete_Pipe Error checking shell */
301 /* */
302 /* CALLS */
303 /* */
304 /* CSC_Remove_From_List Remove node from list */
305 /* [HIC_Make_History_Entry] Make entry in history log */
306 /* TCC_Resume_Task Resume a suspended task */
307 /* [TCT_Check_Stack] Stack checking function */
308 /* TCT_Control_To_System Transfer control to system */
309 /* TCT_Protect Protect created list */
310 /* TCT_Set_Current_Protect Modify current protection */
311 /* TCT_System_Protect Protect against system access*/
312 /* TCT_System_Unprotect Release system protection */
313 /* TCT_Unprotect Release protection */
314 /* */
315 /* INPUTS */
316 /* */
317 /* pipe_ptr Pipe control block pointer */
318 /* */
319 /* OUTPUTS */
320 /* */
321 /* NU_SUCCESS */
322 /* */
323 /* HISTORY */
324 /* */
325 /* DATE REMARKS */
326 /* */
327 /* 03-01-1993 Created initial version 1.0 */
328 /* 04-19-1993 Verified version 1.0 */
329 /* 03-01-1994 Changed function interfaces to */
330 /* match those in prototype, */
331 /* added register options, changed */
332 /* protection logic to reduce */
333 /* overhead, resulting in */
334 /* version 1.1 */
335 /* */
336 /* 03-18-1994 Verified version 1.1 */
337 /* */
338 /*************************************************************************/
339 STATUS PIC_Delete_Pipe(NU_PIPE *pipe_ptr)
340 {
341
342 R1 PI_PCB *pipe; /* Pipe control block ptr */
343 PI_SUSPEND *suspend_ptr; /* Suspend block pointer */
344 PI_SUSPEND *next_ptr; /* Next suspension block ptr */
345 STATUS preempt; /* Status for resume call */
346 NU_SUPERV_USER_VARIABLES
347
348 /* Switch to supervisor mode */
349 NU_SUPERVISOR_MODE();
350
351 /* Move input pipe pointer into internal pointer. */
352 pipe = (PI_PCB *) pipe_ptr;
353
354
355 #ifdef NU_ENABLE_STACK_CHECK
356
357 /* Call stack checking function to check for an overflow condition. */
358 TCT_Check_Stack();
359
360 #endif
361
362 #ifdef NU_ENABLE_HISTORY
363
364 /* Make an entry that corresponds to this function in the system history
365 log. */
366 HIC_Make_History_Entry(NU_DELETE_PIPE_ID, (UNSIGNED) pipe,
367 (UNSIGNED) 0, (UNSIGNED) 0);
368
369 #endif
370
371 /* Protect against access to the pipe. */
372 TCT_System_Protect();
373
374 #ifdef INCLUDE_PROVIEW
375 _RTProf_DumpPipe(RT_PROF_DELETE_PIPE,pipe,RT_PROF_OK);
376 #endif /* INCLUDE_PROVIEW */
377
378 /* Clear the pipe ID. */
379 pipe -> pi_id = 0;
380
381 /* Release protection. */
382 TCT_Unprotect();
383
384 /* Protect against access to the list of created pipes. */
385 TCT_Protect(&PID_List_Protect);
386
387 /* Remove the pipe from the list of created pipes. */
388 CSC_Remove_From_List(&PID_Created_Pipes_List, &(pipe -> pi_created));
389
390 /* Decrement the total number of created pipes. */
391 PID_Total_Pipes--;
392
393 /* Pickup the suspended task pointer list. */
394 suspend_ptr = pipe -> pi_suspension_list;
395
396 /* Walk the chain task(s) currently suspended on the pipe. */
397 preempt = 0;
398 while (suspend_ptr)
399 {
400
401 /* Protect against system access. */
402 TCT_System_Protect();
403
404 /* Resume the suspended task. Insure that the status returned is
405 NU_PIPE_DELETED. */
406 suspend_ptr -> pi_return_status = NU_PIPE_DELETED;
407
408 /* Point to the next suspend structure in the link. */
409 next_ptr = (PI_SUSPEND *) (suspend_ptr -> pi_suspend_link.cs_next);
410
411 /* Resume the specified task. */
412 preempt = preempt |
413 TCC_Resume_Task((NU_TASK *) suspend_ptr -> pi_suspended_task,
414 NU_PIPE_SUSPEND);
415
416 /* Determine if the next is the same as the head pointer. */
417 if (next_ptr == pipe -> pi_suspension_list)
418
419 /* Clear the suspension pointer to signal the end of the list
420 traversal. */
421 suspend_ptr = NU_NULL;
422 else
423
424 /* Setup the next suspension pointer. */
425 suspend_ptr = next_ptr;
426
427 /* Modify current protection. */
428 TCT_Set_Current_Protect(&PID_List_Protect);
429
430 /* Clear the system protection. */
431 TCT_System_Unprotect();
432 }
433
434 /* Pickup the urgent message suspension list. */
435 suspend_ptr = pipe -> pi_urgent_list;
436
437 /* Walk the chain task(s) currently suspended on the pipe. */
438 while (suspend_ptr)
439 {
440
441 /* Protect against system access. */
442 TCT_System_Protect();
443
444 /* Resume the suspended task. Insure that the status returned is
445 NU_PIPE_DELETED. */
446 suspend_ptr -> pi_return_status = NU_PIPE_DELETED;
447
448 /* Point to the next suspend structure in the link. */
449 next_ptr = (PI_SUSPEND *) (suspend_ptr -> pi_suspend_link.cs_next);
450
451 /* Resume the specified task. */
452 preempt = preempt |
453 TCC_Resume_Task((NU_TASK *) suspend_ptr -> pi_suspended_task,
454 NU_PIPE_SUSPEND);
455
456 /* Determine if the next is the same as the head pointer. */
457 if (next_ptr == pipe -> pi_urgent_list)
458
459 /* Clear the suspension pointer to signal the end of the list
460 traversal. */
461 suspend_ptr = NU_NULL;
462 else
463
464 /* Position suspend pointer to the next block. */
465 suspend_ptr = next_ptr;
466
467 /* Modify current protection. */
468 TCT_Set_Current_Protect(&PID_List_Protect);
469
470 /* Clear the system protection. */
471 TCT_System_Unprotect();
472 }
473
474 /* Determine if preemption needs to occur. */
475 if (preempt)
476
477 /* Transfer control to system to facilitate preemption. */
478 TCT_Control_To_System();
479
480 /* Release protection against access to the list of created pipes. */
481 TCT_Unprotect();
482
483 /* Return to user mode */
484 NU_USER_MODE();
485
486 /* Return a successful completion. */
487 return(NU_SUCCESS);
488 }
489
490
491 /*************************************************************************/
492 /* */
493 /* FUNCTION */
494 /* */
495 /* PIC_Send_To_Pipe */
496 /* */
497 /* DESCRIPTION */
498 /* */
499 /* This function sends a message to the specified pipe. The */
500 /* message length is determined by the caller. If there are one */
501 /* or more tasks suspended on the pipe for a message, the message */
502 /* is copied into the message area of the first waiting task. If */
503 /* the task's request is satisfied, it is resumed. Otherwise, if */
504 /* the pipe cannot hold the message, suspension of the calling */
505 /* task is an option of the caller. */
506 /* */
507 /* CALLED BY */
508 /* */
509 /* Application */
510 /* PICE_Send_To_Pipe Error checking shell */
511 /* */
512 /* CALLS */
513 /* */
514 /* CSC_Place_On_List Place on suspend list */
515 /* CSC_Priority_Place_On_List Place on priority list */
516 /* CSC_Remove_From_List Remove from suspend list */
517 /* [HIC_Make_History_Entry] Make entry in history log */
518 /* TCC_Resume_Task Resume a suspended task */
519 /* TCC_Suspend_Task Suspend calling task */
520 /* TCC_Task_Priority Pickup task's priority */
521 /* [TCT_Check_Stack] Stack checking function */
522 /* TCT_Control_To_System Transfer control to system */
523 /* TCT_Current_Thread Pickup current thread pointer*/
524 /* TCT_System_Protect Protect pipe */
525 /* TCT_Unprotect Release protection */
526 /* */
527 /* INPUTS */
528 /* */
529 /* pipe_ptr Pipe control block pointer */
530 /* message Pointer to message to send */
531 /* size Size of message to send */
532 /* suspend Suspension option if full */
533 /* */
534 /* OUTPUTS */
535 /* */
536 /* NU_SUCCESS If service is successful */
537 /* NU_PIPE_FULL If pipe is currently full */
538 /* NU_TIMEOUT If timeout on service expires*/
539 /* NU_PIPE_DELETED If pipe was deleted during */
540 /* suspension */
541 /* NU_PIPE_RESET If pipe was reset during */
542 /* suspension */
543 /* */
544 /* HISTORY */
545 /* */
546 /* DATE REMARKS */
547 /* */
548 /* 03-01-1993 Created initial version 1.0 */
549 /* 04-19-1993 Verified version 1.0 */
550 /* 03-01-1994 Changed function interfaces to */
551 /* match those in prototype, */
552 /* added register options, changed */
553 /* protection logic to reduce */
554 /* overhead, optimized copy loop, */
555 /* resulting in version 1.1 */
556 /* */
557 /* 03-18-1994 Verified version 1.1 */
558 /* */
559 /*************************************************************************/
560 STATUS PIC_Send_To_Pipe(NU_PIPE *pipe_ptr, VOID *message, UNSIGNED size,
561 UNSIGNED suspend)
562 {
563
564 R1 PI_PCB *pipe; /* Pipe control block ptr */
565 PI_SUSPEND suspend_block; /* Allocate suspension block */
566 PI_SUSPEND *suspend_ptr; /* Pointer to suspend block */
567 R2 BYTE_PTR source; /* Pointer to source */
568 R3 BYTE_PTR destination; /* Pointer to destination */
569 UNSIGNED copy_size; /* Partial copy size */
570 R4 INT i; /* Working counter */
571 UNSIGNED pad = 0; /* Number of pad bytes */
572 TC_TCB *task; /* Task pointer */
573 STATUS preempt; /* Preempt flag */
574 STATUS status; /* Completion status */
575 NU_SUPERV_USER_VARIABLES
576
577 /* Switch to supervisor mode */
578 NU_SUPERVISOR_MODE();
579
580 /* Move input pipe pointer into internal pointer. */
581 pipe = (PI_PCB *) pipe_ptr;
582
583
584 #ifdef NU_ENABLE_STACK_CHECK
585
586 /* Call stack checking function to check for an overflow condition. */
587 TCT_Check_Stack();
588
589 #endif
590
591 #ifdef NU_ENABLE_HISTORY
592
593 /* Make an entry that corresponds to this function in the system history
594 log. */
595 HIC_Make_History_Entry(NU_SEND_TO_PIPE_ID, (UNSIGNED) pipe,
596 (UNSIGNED) message, (UNSIGNED) size);
597
598 #endif
599
600 /* Initialize the status as successful. */
601 status = NU_SUCCESS;
602
603 /* Protect against simultaneous access to the pipe. */
604 TCT_System_Protect();
605
606 /* Determine if an extra word of overhead needs to be added to the
607 calculation. */
608 if (pipe -> pi_fixed_size)
609
610 /* No overhead. */
611 i = 0;
612 else
613 {
614
615 /* Variable messages have one additional word of overhead. */
616 i = sizeof(UNSIGNED);
617
618 /* Calculate the number of pad bytes necessary to make keep the pipe
619 write pointer on an UNSIGNED data element alignment. */
620 pad = (((size + sizeof(UNSIGNED) - 1)/sizeof(UNSIGNED)) *
621 sizeof(UNSIGNED)) - size;
622
623 /* Insure that padding is included in the overhead. */
624 i = i + ((INT) pad);
625
626 /* Make special check to see if a suspension needs to be
627 forced for a variable length message. */
628 if ((pipe -> pi_suspension_list) && (pipe -> pi_messages))
629 {
630
631 /* Pickup task control block pointer. */
632 task = (TC_TCB *) TCT_Current_Thread();
633
634 /* Now we know that there are other task(s) are suspended trying
635 to send a variable length message. Determine whether or not
636 a suspension should be forced. */
637 if ((pipe -> pi_fifo_suspend) ||
638 (suspend == NU_NO_SUSPEND) ||
639 ((pipe -> pi_suspension_list) -> pi_suspend_link.cs_priority <=
640 TCC_Task_Priority(task)))
641
642 /* Bump the computed size to avoid placing the new variable
643 length message ahead of the suspended tasks. */
644 i = (INT) pipe -> pi_available;
645 }
646 }
647
648 /* Determine if there is enough room in the pipe for the message. */
649 if (pipe -> pi_available < (size + i))
650 {
651
652 /* pipe does not have room for the message. Determine if
653 suspension is required. */
654 if (suspend)
655 {
656
657 /* Suspension is requested. */
658
659 /* Increment the number of tasks waiting. */
660 pipe -> pi_tasks_waiting++;
661
662 #ifdef INCLUDE_PROVIEW
663 _RTProf_DumpPipe(RT_PROF_SEND_TO_PIPE,pipe,RT_PROF_WAIT);
664 #endif /* INCLUDE_PROVIEW */
665
666 /* Setup the suspend block and suspend the calling task. */
667 suspend_ptr = &suspend_block;
668 suspend_ptr -> pi_pipe = pipe;
669 suspend_ptr -> pi_suspend_link.cs_next = NU_NULL;
670 suspend_ptr -> pi_suspend_link.cs_previous= NU_NULL;
671 suspend_ptr -> pi_message_area = (BYTE_PTR) message;
672 suspend_ptr -> pi_message_size = size;
673 task = (TC_TCB *) TCT_Current_Thread();
674 suspend_ptr -> pi_suspended_task = task;
675
676 /* Determine if priority or FIFO suspension is associated with the
677 pipe. */
678 if (pipe -> pi_fifo_suspend)
679 {
680
681 /* FIFO suspension is required. Link the suspend block into
682 the list of suspended tasks on this pipe. */
683 CSC_Place_On_List((CS_NODE **) &(pipe -> pi_suspension_list),
684 &(suspend_ptr -> pi_suspend_link));
685 }
686 else
687 {
688
689 /* Get the priority of the current thread so the suspend block
690 can be placed in the appropriate place. */
691 suspend_ptr -> pi_suspend_link.cs_priority =
692 TCC_Task_Priority(task);
693
694 CSC_Priority_Place_On_List((CS_NODE **)
695 &(pipe -> pi_suspension_list),
696 &(suspend_ptr -> pi_suspend_link));
697 }
698
699 /* Finally, suspend the calling task. Note that the suspension call
700 automatically clears the protection on the pipe. */
701 TCC_Suspend_Task((NU_TASK *) task, NU_PIPE_SUSPEND,
702 PIC_Cleanup, suspend_ptr, suspend);
703
704 /* Pickup the return status. */
705 status = suspend_ptr -> pi_return_status;
706 }
707 else
708 {
709
710 /* Return a status of NU_PIPE_FULL because there is no
711 room in the pipe for the message. */
712 status = NU_PIPE_FULL;
713
714 #ifdef INCLUDE_PROVIEW
715 _RTProf_DumpPipe(RT_PROF_SEND_TO_PIPE,pipe,RT_PROF_FAIL);
716 #endif /* INCLUDE_PROVIEW */
717 }
718
719 }
720 else
721 {
722
723 /* Determine if a task is waiting on an empty pipe. */
724 if ((pipe -> pi_suspension_list) && (pipe -> pi_messages == 0))
725 {
726
727 /* Task is waiting on pipe for a message. */
728
729 /* Decrement the number of tasks waiting on pipe. */
730 pipe -> pi_tasks_waiting--;
731
732 #ifdef INCLUDE_PROVIEW
733 _RTProf_DumpPipe(RT_PROF_SEND_TO_PIPE,pipe,RT_PROF_OK);
734 #endif /* INCLUDE_PROVIEW */
735
736 /* Remove the first suspended block from the list. */
737 suspend_ptr = pipe -> pi_suspension_list;
738 CSC_Remove_From_List((CS_NODE **) &(pipe -> pi_suspension_list),
739 &(suspend_ptr -> pi_suspend_link));
740
741 /* Setup the source and destination pointers. */
742 source = (BYTE_PTR) message;
743 destination = suspend_ptr -> pi_message_area;
744
745 /* Initialize the return status. */
746 suspend_ptr -> pi_return_status = NU_SUCCESS;
747
748 /* Loop to actually copy the message. */
749 i = (INT) size;
750 do
751 {
752 *(destination++) = *(source);
753 if ((--i) == 0)
754 break;
755 source++;
756 } while(1);
757
758 /* Return the size of the message copied. */
759 suspend_ptr -> pi_actual_size = size;
760
761 /* Wakeup the waiting task and check for preemption. */
762 preempt =
763 TCC_Resume_Task((NU_TASK *) suspend_ptr -> pi_suspended_task,
764 NU_PIPE_SUSPEND);
765
766 /* Determine if preemption needs to take place. */
767 if (preempt)
768
769 /* Transfer control to the system if the resumed task function
770 detects a preemption condition. */
771 TCT_Control_To_System();
772 }
773 else
774 {
775
776 /* There is enough room in the pipe and no task is waiting. */
777
778 /* Setup the source pointer. */
779 source = (BYTE_PTR) message;
780 destination = pipe -> pi_write;
781
782 /* Process according to the type of message supported. */
783 if (pipe -> pi_fixed_size)
784 {
785
786 /* Fixed-size messages are supported by this pipe. */
787
788 /* Loop to copy the message into the pipe area. */
789 i = (INT) size;
790 do
791 {
792 *(destination++) = *(source);
793 if ((--i) == 0)
794 break;
795 source++;
796 } while (1);
797 }
798 else
799 {
800
801 /* Variable-size messages are supported. Processing must
802 check for pipe wrap-around conditions. */
803
804 /* Place message size in first location. */
805 *((UNSIGNED *) destination) = size;
806 destination = destination + sizeof(UNSIGNED);
807
808 /* Check for a wrap-around condition on the pipe. */
809 if (destination >= pipe -> pi_end)
810
811 /* Wrap the write pointer back to the top of the pipe
812 area. */
813 destination = pipe -> pi_start;
814
815 /* Decrement the number of bytes remaining for this
816 extra word of overhead. */
817 pipe -> pi_available = pipe -> pi_available -
818 sizeof(UNSIGNED);
819
820 /* Calculate the number of bytes remaining from the write
821 pointer to the bottom of the pipe. */
822 copy_size = pipe -> pi_end - destination;
823
824 /* Determine if the message needs to be wrapped around the
825 edge of the pipe area. */
826 if (copy_size >= size)
827 {
828
829 /* Copy the whole message at once. */
830 i = (INT) size;
831 do
832 {
833 *(destination++) = *(source);
834 if ((--i) == 0)
835 break;
836 source++;
837 } while (1);
838 }
839 else
840 {
841
842 /* Copy the first half of the message. */
843 i = (INT) copy_size;
844 do
845 {
846 *(destination) = *(source++);
847 if ((--i) == 0)
848 break;
849 destination++;
850 } while (1);
851
852 /* Copy the second half of the message. */
853 destination = pipe -> pi_start;
854 i = (INT) (size - copy_size);
855 do
856 {
857 *(destination++) = *(source);
858 if ((--i) == 0)
859 break;
860 source++;
861 } while (1);
862 }
863 }
864
865 /* Check again for wrap-around condition on the write pointer. */
866 if (destination >= pipe -> pi_end)
867
868 /* Move the write pointer to the top of the pipe area. */
869 destination = pipe -> pi_start;
870
871 /* Determine if the pipe supports variable-length messages. If
872 so, pad bytes are needed to keep UNSIGNED alignment. */
873 if (pad)
874 {
875
876 /* Variable-size message. Add pad bytes to the write
877 pointer. */
878
879 /* Calculate the number of bytes remaining from the write
880 pointer to the bottom of the pipe. */
881 copy_size = pipe -> pi_end - destination;
882
883 /* If there is not enough room at the bottom of the pipe, the
884 pad bytes must be wrapped around to the top. */
885 if (copy_size <= pad)
886
887 /* Move write pointer to the top of the pipe and make the
888 necessary adjustment. */
889 destination = pipe -> pi_start + (pad - copy_size);
890 else
891
892 /* There is enough room in the pipe to simply add the
893 the pad bytes to the write pointer. */
894 destination = destination + pad;
895
896 /* Decrement the number of available bytes. */
897 pipe -> pi_available = pipe -> pi_available - pad;
898 }
899
900 /* Update the actual write pointer. */
901 pipe -> pi_write = destination;
902
903 /* Decrement the number of available bytes. */
904 pipe -> pi_available = pipe -> pi_available - size;
905
906 /* Increment the number of messages in the pipe. */
907 pipe -> pi_messages++;
908
909 #ifdef INCLUDE_PROVIEW
910 _RTProf_DumpPipe(RT_PROF_SEND_TO_PIPE,pipe,RT_PROF_OK);
911 #endif /* INCLUDE_PROVIEW */
912 }
913 }
914
915 /* Release protection against access to the pipe. */
916 TCT_Unprotect();
917
918 /* Return to user mode */
919 NU_USER_MODE();
920
921 /* Return the completion status. */
922 return(status);
923 }
924
925
926 /*************************************************************************/
927 /* */
928 /* FUNCTION */
929 /* */
930 /* PIC_Receive_From_Pipe */
931 /* */
932 /* DESCRIPTION */
933 /* */
934 /* This function receives a message from the specified pipe. The */
935 /* size of the message is specified by the caller. If there is a */
936 /* message currently in the pipe, the message is removed from the */
937 /* pipe and placed in the caller's area. Suspension is possible */
938 /* if the request cannot be satisfied. */
939 /* */
940 /* CALLED BY */
941 /* */
942 /* Application */
943 /* PICE_Receive_From_Pipe Error checking shell */
944 /* */
945 /* CALLS */
946 /* */
947 /* CSC_Place_On_List Place on suspend list */
948 /* CSC_Remove_From_List Remove from suspend list */
949 /* [HIC_Make_History_Entry] Make entry in history log */
950 /* TCC_Resume_Task Resume a suspended task */
951 /* TCC_Suspend_Task Suspend calling task */
952 /* TCC_Task_Priority Pickup task's priority */
953 /* [TCT_Check_Stack] Stack checking function */
954 /* TCT_Control_To_System Transfer control to system */
955 /* TCT_Current_Thread Pickup current thread pointer*/
956 /* TCT_System_Protect Protect pipe */
957 /* TCT_Unprotect Release protection */
958 /* */
959 /* INPUTS */
960 /* */
961 /* pipe_ptr Pipe control block pointer */
962 /* message Pointer to message to send */
963 /* size Size of the message */
964 /* actual_size Size of message received */
965 /* suspend Suspension option if empty */
966 /* */
967 /* OUTPUTS */
968 /* */
969 /* NU_SUCCESS If service is successful */
970 /* NU_PIPE_EMPTY If pipe is currently empty */
971 /* NU_TIMEOUT If timeout on service expires*/
972 /* NU_PIPE_DELETED If pipe was deleted during */
973 /* suspension */
974 /* NU_PIPE_RESET If pipe was reset during */
975 /* suspension */
976 /* */
977 /* HISTORY */
978 /* */
979 /* DATE REMARKS */
980 /* */
981 /* 03-01-1993 Created initial version 1.0 */
982 /* 04-19-1993 Verified version 1.0 */
983 /* 03-01-1994 Changed function interfaces to */
984 /* match those in prototype, */
985 /* added register options, changed */
986 /* protection logic to reduce */
987 /* overhead, optimized copy loop, */
988 /* resulting in version 1.1 */
989 /* */
990 /* 03-18-1994 Verified version 1.1 */
991 /* */
992 /*************************************************************************/
993 STATUS PIC_Receive_From_Pipe(NU_PIPE *pipe_ptr, VOID *message,
994 UNSIGNED size, UNSIGNED *actual_size, UNSIGNED suspend)
995 {
996
997 R1 PI_PCB *pipe; /* Pipe control block ptr */
998 PI_SUSPEND suspend_block; /* Allocate suspension block */
999 PI_SUSPEND *suspend_ptr; /* Pointer to suspend block */
1000 R2 BYTE_PTR source; /* Pointer to source */
1001 R3 BYTE_PTR destination; /* Pointer to destination */
1002 TC_TCB *task; /* Task pointer */
1003 UNSIGNED copy_size; /* Number of bytes to copy */
1004 UNSIGNED pad = 0; /* Number of pad bytes */
1005 R4 INT i; /* Working counter */
1006 STATUS preempt; /* Preemption flag */
1007 STATUS status; /* Completion status */
1008 NU_SUPERV_USER_VARIABLES
1009
1010 /* Switch to supervisor mode */
1011 NU_SUPERVISOR_MODE();
1012
1013 /* Move input pipe pointer into internal pointer. */
1014 pipe = (PI_PCB *) pipe_ptr;
1015
1016
1017 #ifdef NU_ENABLE_STACK_CHECK
1018
1019 /* Call stack checking function to check for an overflow condition. */
1020 TCT_Check_Stack();
1021
1022 #endif
1023
1024 #ifdef NU_ENABLE_HISTORY
1025
1026 /* Make an entry that corresponds to this function in the system history
1027 log. */
1028 HIC_Make_History_Entry(NU_RECEIVE_FROM_PIPE_ID, (UNSIGNED) pipe,
1029 (UNSIGNED) message, (UNSIGNED) size);
1030
1031 #endif
1032
1033 /* Initialize the status as successful. */
1034 status = NU_SUCCESS;
1035
1036 /* Protect against simultaneous access to the pipe. */
1037 TCT_System_Protect();
1038
1039 /* Determine if an urgent message request is currently suspended. */
1040 if (pipe -> pi_urgent_list)
1041 {
1042
1043 /* If so, copy the message from the suspended request block and
1044 resume the associated task. */
1045
1046 /* Decrement the number of tasks waiting on pipe. */
1047 pipe -> pi_tasks_waiting--;
1048
1049 /* Remove the first suspended block from the list. */
1050 suspend_ptr = pipe -> pi_urgent_list;
1051 CSC_Remove_From_List((CS_NODE **) &(pipe -> pi_urgent_list),
1052 &(suspend_ptr -> pi_suspend_link));
1053
1054 /* Setup the source and destination pointers. */
1055 destination = (BYTE_PTR) message;
1056 source = suspend_ptr -> pi_message_area;
1057
1058 /* Initialize the return status. */
1059 suspend_ptr -> pi_return_status = NU_SUCCESS;
1060
1061 /* Loop to actually copy the message. */
1062 i = (INT) size;
1063 do
1064 {
1065 *(destination++) = *(source);
1066 if ((--i) == 0)
1067 break;
1068 source++;
1069 } while (1);
1070
1071 /* Return the size of the message copied. */
1072 *actual_size = suspend_ptr -> pi_message_size;
1073
1074 /* Wakeup the waiting task and check for preemption. */
1075 preempt =
1076 TCC_Resume_Task((NU_TASK *) suspend_ptr -> pi_suspended_task,
1077 NU_PIPE_SUSPEND);
1078
1079 /* Determine if preemption needs to take place. */
1080 if (preempt)
1081
1082 /* Transfer control to the system if the resumed task function
1083 detects a preemption condition. */
1084 TCT_Control_To_System();
1085 }
1086
1087 /* Determine if there are messages in the pipe. */
1088 else if (pipe -> pi_messages)
1089 {
1090
1091 /* Copy message from pipe into the caller's area. */
1092
1093 /* Setup the source and destination pointers. */
1094 destination = (BYTE_PTR) message;
1095 source = pipe -> pi_read;
1096
1097 /* Process according to the type of message supported by the pipe. */
1098 if (pipe -> pi_fixed_size)
1099 {
1100
1101 /* Pipe supports fixed-size messages. */
1102
1103 /* Copy the message from the pipe area into the destination. */
1104 i = (INT) size;
1105 do
1106 {
1107 *(destination) = *(source++);
1108 if ((--i) == 0)
1109 break;
1110 destination++;
1111 } while (1);
1112 }
1113 else
1114 {
1115
1116 /* Pipe supports variable-size messages. */
1117
1118 /* Variable length message size is actually in the pipe area. */
1119 size = *((UNSIGNED *) source);
1120 source = source + sizeof(UNSIGNED);
1121
1122 /* Check for a wrap-around condition on the pipe. */
1123 if (source >= pipe -> pi_end)
1124
1125 /* Wrap the read pointer back to the top of the pipe
1126 area. */
1127 source = pipe -> pi_start;
1128
1129 /* Increment the number of available bytes in the pipe. */
1130 pipe -> pi_available = pipe -> pi_available + sizeof(UNSIGNED);
1131
1132 /* Calculate the number of pad bytes necessary to keep
1133 the pipe read pointer on an UNSIGNED data element alignment.*/
1134 pad = (((size + sizeof(UNSIGNED) - 1)/sizeof(UNSIGNED)) *
1135 sizeof(UNSIGNED)) - size;
1136
1137 /* Calculate the number of bytes remaining from the read pointer
1138 to the bottom of the pipe. */
1139 copy_size = pipe -> pi_end - source;
1140
1141 /* Determine if the message needs to be wrapped around the
1142 edge of the pipe area. */
1143 if (copy_size >= size)
1144 {
1145
1146 /* Copy the whole message at once. */
1147 i = (INT) size;
1148 do
1149 {
1150 *(destination) = *(source++);
1151 if ((--i) == 0)
1152 break;
1153 destination++;
1154 } while (1);
1155 }
1156 else
1157 {
1158
1159 /* Copy the first half of the message. */
1160 i = (INT) copy_size;
1161 do
1162 {
1163 *(destination++) = *(source);
1164 if ((--i) == 0)
1165 break;
1166 source++;
1167 } while (1);
1168
1169 /* Copy the second half of the message. */
1170 source = pipe -> pi_start;
1171 i = (INT) (size - copy_size);
1172 do
1173 {
1174 *(destination) = *(source++);
1175 if ((--i) == 0)
1176 break;
1177 destination++;
1178 } while (1);
1179 }
1180 }
1181
1182 /* Check again for wrap-around condition on the read pointer. */
1183 if (source >= pipe -> pi_end)
1184
1185 /* Move the read pointer to the top of the pipe area. */
1186 source = pipe -> pi_start;
1187
1188 /* Determine if the pipe supports variable-length messages. If
1189 so, pad bytes are needed to keep UNSIGNED alignment. */
1190 if (pad)
1191 {
1192
1193 /* Variable-size message. Add pad bytes to the read
1194 pointer. */
1195
1196 /* Calculate the number of bytes remaining from the read
1197 pointer to the bottom of the pipe. */
1198 copy_size = pipe -> pi_end - source;
1199
1200 /* If there is not enough room at the bottom of the pipe, the
1201 pad bytes must be wrapped around to the top. */
1202 if (copy_size <= pad)
1203
1204 /* Move read pointer to the top of the pipe and make the
1205 necessary adjustment. */
1206 source = pipe -> pi_start + (pad - copy_size);
1207 else
1208
1209 /* There is enough room in the pipe to simply add the
1210 the pad bytes to the read pointer. */
1211 source = source + pad;
1212
1213 /* Add pad bytes to the available bytes count. */
1214 pipe -> pi_available = pipe -> pi_available + pad;
1215 }
1216
1217 /* Adjust the actual read pointer. */
1218 pipe -> pi_read = source;
1219
1220 /* Increment the number of available bytes. */
1221 pipe -> pi_available = pipe -> pi_available + size;
1222
1223 /* Decrement the number of messages in the pipe. */
1224 pipe -> pi_messages--;
1225
1226 /* Return the number of bytes received. */
1227 *actual_size = size;
1228
1229 #ifdef INCLUDE_PROVIEW
1230 _RTProf_DumpPipe(RT_PROF_RECEIVE_FROM_PIPE,pipe,RT_PROF_OK);
1231 #endif /* INCLUDE_PROVIEW */
1232
1233 /* Determine if any tasks suspended on a full pipe can be woken
1234 up. */
1235 if (pipe -> pi_suspension_list)
1236 {
1237
1238 /* Pickup the suspension list and examine suspension blocks
1239 to see if the message could now fit in the pipe. */
1240 suspend_ptr = pipe -> pi_suspension_list;
1241 preempt = NU_FALSE;
1242 size = suspend_ptr -> pi_message_size;
1243 i = 0;
1244 pad = 0;
1245
1246 /* Overhead of each pipe message. */
1247 if (!pipe -> pi_fixed_size)
1248 {
1249
1250 /* Variable messages have one additional word of overhead. */
1251 i = sizeof(UNSIGNED);
1252
1253 /* Calculate the number of pad bytes necessary to keep
1254 the pipe write pointer on an UNSIGNED data element
1255 alignment. */
1256 pad = (((size + sizeof(UNSIGNED) - 1)/sizeof(UNSIGNED)) *
1257 sizeof(UNSIGNED)) - size;
1258
1259 /* Insure that padding is included in the overhead. */
1260 i = i + ((INT) pad);
1261 }
1262
1263 while ((suspend_ptr) && ((size + i) <= pipe -> pi_available))
1264 {
1265
1266 /* Place the suspended task's message into the pipe. */
1267
1268 /* Setup the source and destination pointers. */
1269 source = suspend_ptr -> pi_message_area;
1270 destination = pipe -> pi_write;
1271
1272 /* Process according to the type of message supported. */
1273 if (pipe -> pi_fixed_size)
1274 {
1275
1276 /* Fixed-size messages are supported by this pipe. */
1277
1278 /* Loop to copy the message into the pipe area. */
1279 i = (INT) size;
1280 do
1281 {
1282 *(destination++) = *(source);
1283 if ((--i) == 0)
1284 break;
1285 source++;
1286 } while (1);
1287 }
1288 else
1289 {
1290
1291 /* Variable-size messages are supported. Processing must
1292 check for pipe wrap-around conditions. */
1293
1294 /* Place message size in first location. */
1295 *((UNSIGNED *) destination) = size;
1296 destination = destination + sizeof(UNSIGNED);
1297
1298 /* Check for a wrap-around condition on the pipe. */
1299 if (destination >= pipe -> pi_end)
1300
1301 /* Wrap the write pointer back to the top of the pipe
1302 area. */
1303 destination = pipe -> pi_start;
1304
1305 /* Decrement the number of bytes remaining for this
1306 extra word of overhead. */
1307 pipe -> pi_available = pipe -> pi_available -
1308 sizeof(UNSIGNED);
1309
1310 /* Calculate the number of bytes remaining from the write
1311 pointer to the bottom of the pipe. */
1312 copy_size = pipe -> pi_end - destination;
1313
1314 /* Determine if the message needs to be wrapped around the
1315 edge of the pipe area. */
1316 if (copy_size >= size)
1317 {
1318
1319 /* Copy the whole message at once. */
1320 i = (INT) size;
1321 do
1322 {
1323 *(destination++) = *(source);
1324 if ((--i) == 0)
1325 break;
1326 source++;
1327 } while (1);
1328 }
1329 else
1330 {
1331
1332 /* Copy the first half of the message. */
1333 i = (INT) copy_size;
1334 do
1335 {
1336 *(destination) = *(source++);
1337 if ((--i) == 0)
1338 break;
1339 destination++;
1340 } while (1);
1341
1342 /* Copy the second half of the message. */
1343 destination = pipe -> pi_start;
1344 i = (INT) (size - copy_size);
1345 do
1346 {
1347 *(destination++) = *(source);
1348 if ((--i) == 0)
1349 break;
1350 source++;
1351 } while (1);
1352 }
1353 }
1354
1355 /* Check again for wrap-around condition on the write
1356 pointer. */
1357 if (destination >= pipe -> pi_end)
1358
1359 /* Move the write pointer to the top of the pipe area. */
1360 destination = pipe -> pi_start;
1361
1362 /* Determine if the pipe supports variable-length messages. If
1363 so, pad bytes are needed to keep UNSIGNED alignment. */
1364 if (pad)
1365 {
1366
1367 /* Variable-size message. Add pad bytes to the write
1368 pointer. */
1369
1370 /* Calculate the number of bytes remaining from the write
1371 pointer to the bottom of the pipe. */
1372 copy_size = pipe -> pi_end - destination;
1373
1374 /* If there is not enough room at the bottom of the pipe,
1375 the pad bytes must be wrapped around to the top. */
1376 if (copy_size <= pad)
1377
1378 /* Move write pointer to the top of the pipe and make
1379 the necessary adjustment. */
1380 destination = pipe -> pi_start + (pad - copy_size);
1381 else
1382
1383 /* There is enough room in the pipe to simply add
1384 the pad bytes to the write pointer. */
1385 destination = destination + pad;
1386
1387 /* Decrement the number of available bytes. */
1388 pipe -> pi_available = pipe -> pi_available - pad;
1389 }
1390
1391 /* Update the actual write pointer. */
1392 pipe -> pi_write = destination;
1393
1394 /* Decrement the number of available bytes. */
1395 pipe -> pi_available = pipe -> pi_available - size;
1396
1397 /* Increment the number of messages in the pipe. */
1398 pipe -> pi_messages++;
1399
1400 /* Decrement the number of tasks waiting counter. */
1401 pipe -> pi_tasks_waiting--;
1402
1403 /* Remove the first suspended block from the list. */
1404 CSC_Remove_From_List((CS_NODE **)
1405 &(pipe -> pi_suspension_list),
1406 &(suspend_ptr -> pi_suspend_link));
1407
1408 /* Return a successful status. */
1409 suspend_ptr -> pi_return_status = NU_SUCCESS;
1410
1411 /* Resume the suspended task. */
1412 preempt = preempt |
1413 TCC_Resume_Task((NU_TASK *) suspend_ptr -> pi_suspended_task,
1414 NU_PIPE_SUSPEND);
1415
1416 /* Setup suspend pointer to the head of the list. */
1417 suspend_ptr = pipe -> pi_suspension_list;
1418
1419 /* Determine if there really is another suspended block. If
1420 there is and the pipe supports variable length messages,
1421 calculate new size and padding parameters. */
1422 if ((suspend_ptr) && (!pipe -> pi_fixed_size))
1423 {
1424
1425 /* Get the next message size. */
1426 size = suspend_ptr -> pi_message_size;
1427
1428 /* Variable messages have one additional word of
1429 overhead. */
1430 i = sizeof(UNSIGNED);
1431
1432 /* Calculate the number of pad bytes necessary to
1433 keep the pipe write pointer on an UNSIGNED data element
1434 alignment. */
1435 pad = (((size + sizeof(UNSIGNED) - 1)/sizeof(UNSIGNED)) *
1436 sizeof(UNSIGNED)) - size;
1437
1438 /* Insure that padding is included in the overhead. */
1439 i = i + ((INT) pad);
1440 }
1441 }
1442
1443 /* Determine if a preempt condition is present. */
1444 if (preempt)
1445
1446 /* Transfer control to the system if the resumed task function
1447 detects a preemption condition. */
1448 TCT_Control_To_System();
1449 }
1450 }
1451 else
1452 {
1453
1454 /* pipe is empty. Determine if the task wants to suspend. */
1455 if (suspend)
1456 {
1457
1458 /* Increment the number of tasks waiting on the pipe counter. */
1459 pipe -> pi_tasks_waiting++;
1460
1461 #ifdef INCLUDE_PROVIEW
1462 _RTProf_DumpPipe(RT_PROF_RECEIVE_FROM_PIPE,pipe,RT_PROF_WAIT);
1463 #endif /* INCLUDE_PROVIEW */
1464
1465 /* Setup the suspend block and suspend the calling task. */
1466 suspend_ptr = &suspend_block;
1467 suspend_ptr -> pi_pipe = pipe;
1468 suspend_ptr -> pi_suspend_link.cs_next = NU_NULL;
1469 suspend_ptr -> pi_suspend_link.cs_previous = NU_NULL;
1470 suspend_ptr -> pi_message_area = (BYTE_PTR) message;
1471 suspend_ptr -> pi_message_size = size;
1472 task = (TC_TCB *) TCT_Current_Thread();
1473 suspend_ptr -> pi_suspended_task = task;
1474
1475 /* Determine if priority or FIFO suspension is associated with the
1476 pipe. */
1477 if (pipe -> pi_fifo_suspend)
1478 {
1479
1480 /* FIFO suspension is required. Link the suspend block into
1481 the list of suspended tasks on this pipe. */
1482 CSC_Place_On_List((CS_NODE **) &(pipe -> pi_suspension_list),
1483 &(suspend_ptr -> pi_suspend_link));
1484 }
1485 else
1486 {
1487
1488 /* Get the priority of the current thread so the suspend block
1489 can be placed in the appropriate place. */
1490 suspend_ptr -> pi_suspend_link.cs_priority =
1491 TCC_Task_Priority(task);
1492
1493 CSC_Priority_Place_On_List((CS_NODE **)
1494 &(pipe -> pi_suspension_list),
1495 &(suspend_ptr -> pi_suspend_link));
1496 }
1497
1498 /* Finally, suspend the calling task. Note that the suspension call
1499 automatically clears the protection on the pipe. */
1500 TCC_Suspend_Task((NU_TASK *) task, NU_PIPE_SUSPEND,
1501 PIC_Cleanup, suspend_ptr, suspend);
1502
1503 /* Pickup the status of the request. */
1504 status = suspend_ptr -> pi_return_status;
1505 *actual_size = suspend_ptr -> pi_actual_size;
1506 }
1507 else
1508 {
1509
1510 /* Return a status of NU_PIPE_EMPTY because there are no
1511 messages in the pipe. */
1512 status = NU_PIPE_EMPTY;
1513
1514 #ifdef INCLUDE_PROVIEW
1515 _RTProf_DumpPipe(RT_PROF_RECEIVE_FROM_PIPE,pipe,RT_PROF_FAIL);
1516 #endif /* INCLUDE_PROVIEW */
1517 }
1518 }
1519
1520 /* Release protection against access to the pipe. */
1521 TCT_Unprotect();
1522
1523 /* Return to user mode */
1524 NU_USER_MODE();
1525
1526 /* Return the completion status. */
1527 return(status);
1528 }
1529
1530
1531 /*************************************************************************/
1532 /* */
1533 /* FUNCTION */
1534 /* */
1535 /* PIC_Cleanup */
1536 /* */
1537 /* DESCRIPTION */
1538 /* */
1539 /* This function is responsible for removing a suspension block */
1540 /* from a pipe. It is not called unless a timeout or a task */
1541 /* terminate is in progress. Note that protection is already in */
1542 /* effect - the same protection at suspension time. This routine */
1543 /* must be called from Supervisor mode in Supervisor/User mode */
1544 /* switching kernels. */
1545 /* */
1546 /* CALLED BY */
1547 /* */
1548 /* TCC_Timeout Task timeout */
1549 /* TCC_Terminate Task terminate */
1550 /* */
1551 /* CALLS */
1552 /* */
1553 /* CSC_Remove_From_List Remove suspend block from */
1554 /* the suspension list */
1555 /* */
1556 /* INPUTS */
1557 /* */
1558 /* information Pointer to suspend block */
1559 /* */
1560 /* OUTPUTS */
1561 /* */
1562 /* None */
1563 /* */
1564 /* HISTORY */
1565 /* */
1566 /* DATE REMARKS */
1567 /* */
1568 /* 03-01-1993 Created initial version 1.0 */
1569 /* 04-19-1993 Verified version 1.0 */
1570 /* */
1571 /*************************************************************************/
1572 VOID PIC_Cleanup(VOID *information)
1573 {
1574
1575 PI_SUSPEND *suspend_ptr; /* Suspension block pointer */
1576 NU_SUPERV_USER_VARIABLES
1577
1578 /* Switch to supervisor mode */
1579 NU_SUPERVISOR_MODE();
1580
1581 /* Use the information pointer as a suspend pointer. */
1582 suspend_ptr = (PI_SUSPEND *) information;
1583
1584 /* By default, indicate that the service timed-out. It really does not
1585 matter if this function is called from a terminate request since
1586 the task does not resume. */
1587 suspend_ptr -> pi_return_status = NU_TIMEOUT;
1588
1589 /* Decrement the number of tasks waiting counter. */
1590 (suspend_ptr -> pi_pipe) -> pi_tasks_waiting--;
1591
1592 /* Determine if the suspend block is one the urgent list. */
1593 if ((suspend_ptr -> pi_pipe) -> pi_urgent_list)
1594 {
1595 /* Unlink the suspend block from the urgent list. */
1596 CSC_Remove_From_List((CS_NODE **)
1597 &((suspend_ptr -> pi_pipe) -> pi_urgent_list),
1598 &(suspend_ptr -> pi_suspend_link));
1599 }
1600 else
1601 {
1602 /* Unlink the suspend block from the suspension list. */
1603 CSC_Remove_From_List((CS_NODE **)
1604 &((suspend_ptr -> pi_pipe) -> pi_suspension_list),
1605 &(suspend_ptr -> pi_suspend_link));
1606 }
1607
1608 /* Return to user mode */
1609 NU_USER_MODE();
1610 }
1611
1612
1613
1614
1615
1616
1617