comparison src/nucleus/evc.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 /* evc.c Nucleus PLUS 1.14 */
17 /* */
18 /* COMPONENT */
19 /* */
20 /* EV - Event Group Management */
21 /* */
22 /* DESCRIPTION */
23 /* */
24 /* This file contains the core routines for the Event Group */
25 /* Management component. */
26 /* */
27 /* DATA STRUCTURES */
28 /* */
29 /* None */
30 /* */
31 /* FUNCTIONS */
32 /* */
33 /* EVC_Create_Event_Group Create an event group */
34 /* EVC_Delete_Event_Group Delete an event group */
35 /* EVC_Set_Events Set events in a group */
36 /* EVC_Retrieve_Events Retrieve events from a group */
37 /* EVC_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 /* ev_extr.h Event Group 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 /* 10-28-1997 Corrected a problem where */
68 /* NU_Set_Events may not resume all */
69 /* waiting tasks. (SPR190) Created */
70 /* version 1.2a. */
71 /* 03-24-1998 Released version 1.3 */
72 /* 03-26-1999 Released 1.11m (new release */
73 /* numbering scheme) */
74 /* 04-17-2002 Released version 1.13m */
75 /* 11-07-2002 Released version 1.14 */
76 /*************************************************************************/
77 #define NU_SOURCE_FILE
78
79
80 #include "cs_extr.h" /* Common service functions */
81 #include "tc_extr.h" /* Thread control functions */
82 #include "ev_extr.h" /* Event Group functions */
83 #include "hi_extr.h" /* History functions */
84 #include "profiler.h" /* ProView interface */
85
86
87 /* Define external inner-component global data references. */
88
89 extern CS_NODE *EVD_Created_Event_Groups_List;
90 extern UNSIGNED EVD_Total_Event_Groups;
91 extern TC_PROTECT EVD_List_Protect;
92
93
94 /* Define internal component function prototypes. */
95
96 VOID EVC_Cleanup(VOID *information);
97
98
99 /*************************************************************************/
100 /* */
101 /* FUNCTION */
102 /* */
103 /* EVC_Create_Event_Group */
104 /* */
105 /* DESCRIPTION */
106 /* */
107 /* This function creates an event group and then places it on the */
108 /* list of created event groups. */
109 /* */
110 /* CALLED BY */
111 /* */
112 /* Application */
113 /* EVCE_Create_Event_Group Error checking shell */
114 /* */
115 /* CALLS */
116 /* */
117 /* CSC_Place_On_List Add node to linked-list */
118 /* [HIC_Make_History_Entry] Make entry in history log */
119 /* [TCT_Check_Stack] Stack checking function */
120 /* TCT_Protect Data structure protect */
121 /* TCT_Unprotect Un-protect data structure */
122 /* */
123 /* INPUTS */
124 /* */
125 /* event_group_ptr Event Group control block ptr*/
126 /* name Event Group name */
127 /* */
128 /* OUTPUTS */
129 /* */
130 /* NU_SUCCESS */
131 /* */
132 /* HISTORY */
133 /* */
134 /* DATE REMARKS */
135 /* */
136 /* 03-01-1993 Created initial version 1.0 */
137 /* 04-19-1993 Verified version 1.0 */
138 /* 03-01-1994 Changed function interfaces to */
139 /* match those in prototype, */
140 /* added register options, */
141 /* resulting in version 1.1 */
142 /* */
143 /* 03-18-1994 Verified version 1.1 */
144 /* */
145 /*************************************************************************/
146 STATUS EVC_Create_Event_Group(NU_EVENT_GROUP *event_group_ptr, CHAR *name)
147 {
148
149 R1 EV_GCB *event_group; /* Event control block ptr */
150 INT i; /* Working index variable */
151 NU_SUPERV_USER_VARIABLES
152
153 /* Switch to supervisor mode */
154 NU_SUPERVISOR_MODE();
155
156 /* Move input event group pointer into internal pointer. */
157 event_group = (EV_GCB *) event_group_ptr;
158
159
160 #ifdef NU_ENABLE_STACK_CHECK
161
162 /* Call stack checking function to check for an overflow condition. */
163 TCT_Check_Stack();
164
165 #endif
166
167 #ifdef NU_ENABLE_HISTORY
168
169 /* Make an entry that corresponds to this function in the system history
170 log. */
171 HIC_Make_History_Entry(NU_CREATE_EVENT_GROUP_ID, (UNSIGNED) event_group,
172 (UNSIGNED) name, (UNSIGNED) 0);
173
174 #endif
175
176 /* First, clear the event group ID just in case it is an old Event Group
177 Control Block. */
178 event_group -> ev_id = 0;
179
180 /* Fill in the event group name. */
181 for (i = 0; i < NU_MAX_NAME; i++)
182 event_group -> ev_name[i] = name[i];
183
184 /* Clear the flags of the event group. */
185 event_group -> ev_current_events = 0;
186
187 /* Clear the suspension list pointer. */
188 event_group -> ev_suspension_list = NU_NULL;
189
190 /* Clear the number of tasks waiting on the event_group counter. */
191 event_group -> ev_tasks_waiting = 0;
192
193 /* Initialize link pointers. */
194 event_group -> ev_created.cs_previous = NU_NULL;
195 event_group -> ev_created.cs_next = NU_NULL;
196
197 /* Protect against access to the list of created event_groups. */
198 TCT_Protect(&EVD_List_Protect);
199
200 /* At this point the event_group is completely built. The ID can now be
201 set and it can be linked into the created event_group list. */
202 event_group -> ev_id = EV_EVENT_ID;
203
204 /* Link the event group into the list of created event groups and
205 increment the total number of event groups in the system. */
206 CSC_Place_On_List(&EVD_Created_Event_Groups_List,
207 &(event_group -> ev_created));
208 EVD_Total_Event_Groups++;
209 #ifdef INCLUDE_PROVIEW
210 _RTProf_DumpEventGroup(RT_PROF_CREATE_EVENT_GROUP,event_group, RT_PROF_OK);
211 #endif /*INCLUDE_PROVIEW*/
212
213 /* Release protection against access to the list of created event
214 groups. */
215 TCT_Unprotect();
216
217 /* Return to user mode */
218 NU_USER_MODE();
219
220 /* Return successful completion. */
221 return(NU_SUCCESS);
222 }
223
224
225 /*************************************************************************/
226 /* */
227 /* FUNCTION */
228 /* */
229 /* EVC_Delete_Event_Group */
230 /* */
231 /* DESCRIPTION */
232 /* */
233 /* This function deletes an event group and removes it from the */
234 /* list of created event groups. All tasks suspended on the */
235 /* event group are resumed. Note that this function does not */
236 /* free the memory associated with the event group control block. */
237 /* */
238 /* CALLED BY */
239 /* */
240 /* Application */
241 /* EVCE_Delete_Event_Group Error checking shell */
242 /* */
243 /* CALLS */
244 /* */
245 /* CSC_Remove_From_List Remove node from list */
246 /* [HIC_Make_History_Entry] Make entry in history log */
247 /* TCC_Resume_Task Resume a suspended task */
248 /* [TCT_Check_Stack] Stack checking function */
249 /* TCT_Control_To_System Transfer control to system */
250 /* TCT_Protect Protect created list */
251 /* TCT_Set_Current_Protect Modify current protection */
252 /* TCT_System_Protect Setup system protection */
253 /* TCT_System_Unprotect Release system protection */
254 /* TCT_Unprotect Release protection */
255 /* */
256 /* INPUTS */
257 /* */
258 /* event_group_ptr Event Group control block ptr*/
259 /* */
260 /* OUTPUTS */
261 /* */
262 /* NU_SUCCESS */
263 /* */
264 /* HISTORY */
265 /* */
266 /* NAME DATE REMARKS */
267 /* */
268 /* 03-01-1993 Created initial version 1.0 */
269 /* 04-19-1993 Verified version 1.0 */
270 /* 03-01-1994 Changed function interfaces to */
271 /* match those in prototype, */
272 /* added register options, changed */
273 /* protection logic to reduce */
274 /* overhead, resulting in */
275 /* version 1.1 */
276 /* */
277 /* 03-18-1994 Verified version 1.1 */
278 /* */
279 /*************************************************************************/
280 STATUS EVC_Delete_Event_Group(NU_EVENT_GROUP *event_group_ptr)
281 {
282
283 R1 EV_GCB *event_group; /* Event control block ptr */
284 EV_SUSPEND *suspend_ptr; /* Suspend block pointer */
285 EV_SUSPEND *next_ptr; /* Next suspend block */
286 STATUS preempt; /* Status for resume call */
287 NU_SUPERV_USER_VARIABLES
288
289 /* Switch to supervisor mode */
290 NU_SUPERVISOR_MODE();
291
292 /* Move input event group pointer into internal pointer. */
293 event_group = (EV_GCB *) event_group_ptr;
294
295
296 #ifdef NU_ENABLE_STACK_CHECK
297
298 /* Call stack checking function to check for an overflow condition. */
299 TCT_Check_Stack();
300
301 #endif
302
303 #ifdef NU_ENABLE_HISTORY
304
305 /* Make an entry that corresponds to this function in the system history
306 log. */
307 HIC_Make_History_Entry(NU_DELETE_EVENT_GROUP_ID, (UNSIGNED) event_group,
308 (UNSIGNED) 0, (UNSIGNED) 0);
309
310 #endif
311
312 /* Protect against simultaneous access to the event group. */
313 TCT_System_Protect();
314
315 #ifdef INCLUDE_PROVIEW
316 _RTProf_DumpEventGroup(RT_PROF_DELETE_EVENT_GROUP, event_group, RT_PROF_OK);
317 #endif /*INCLUDE_PROVIEW*/
318
319 /* Clear the event group ID. */
320 event_group -> ev_id = 0;
321
322 /* Release protection. */
323 TCT_Unprotect();
324
325 /* Protect against access to the list of created event groups. */
326 TCT_Protect(&EVD_List_Protect);
327
328 /* Remove the event_group from the list of created event groups. */
329 CSC_Remove_From_List(&EVD_Created_Event_Groups_List,
330 &(event_group -> ev_created));
331
332 /* Decrement the total number of created event groups. */
333 EVD_Total_Event_Groups--;
334
335 /* Pickup the suspended task pointer list. */
336 suspend_ptr = event_group -> ev_suspension_list;
337
338 /* Walk the chain task(s) currently suspended on the event_group. */
339 preempt = 0;
340 while (suspend_ptr)
341 {
342
343 /* Protect against system access. */
344 TCT_System_Protect();
345
346 /* Resume the suspended task. Insure that the status returned is
347 NU_GROUP_DELETED. */
348 suspend_ptr -> ev_return_status = NU_GROUP_DELETED;
349
350 /* Point to the next suspend structure in the link. */
351 next_ptr = (EV_SUSPEND *) (suspend_ptr -> ev_suspend_link.cs_next);
352
353 /* Resume the specified task. */
354 preempt = preempt |
355 TCC_Resume_Task((NU_TASK *) suspend_ptr -> ev_suspended_task,
356 NU_EVENT_SUSPEND);
357
358 /* Determine if the next is the same as the current pointer. */
359 if (next_ptr == event_group -> ev_suspension_list)
360
361 /* Clear the suspension pointer to signal the end of the list
362 traversal. */
363 suspend_ptr = NU_NULL;
364 else
365
366 /* Move the next pointer into the suspend block pointer. */
367 suspend_ptr = next_ptr;
368
369 /* Modify current protection. */
370 TCT_Set_Current_Protect(&EVD_List_Protect);
371
372 /* Clear the system protection. */
373 TCT_System_Unprotect();
374 }
375
376 /* Determine if preemption needs to occur. */
377 if (preempt)
378
379 /* Transfer control to system to facilitate preemption. */
380 TCT_Control_To_System();
381
382 /* Release protection against access to the list of created
383 event groups. */
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 /* EVC_Set_Events */
399 /* */
400 /* DESCRIPTION */
401 /* */
402 /* This function sets event flags within the specified event flag */
403 /* group. Event flags may be ANDed or ORed against the current */
404 /* events of the group. Any task that is suspended on the group */
405 /* that has its request satisfied is resumed. */
406 /* */
407 /* CALLED BY */
408 /* */
409 /* Application */
410 /* EVCE_Set_Events Error checking shell */
411 /* */
412 /* CALLS */
413 /* */
414 /* CSC_Remove_From_List Remove from suspend list */
415 /* [HIC_Make_History_Entry] Make entry in history log */
416 /* TCC_Resume_Task Resume a suspended task */
417 /* [TCT_Check_Stack] Stack checking function */
418 /* TCT_Control_To_System Transfer control to system */
419 /* TCT_System_Protect Protect event group */
420 /* TCT_Unprotect Release protection */
421 /* */
422 /* INPUTS */
423 /* */
424 /* event_group_ptr Event Group control block ptr*/
425 /* events Event flag setting */
426 /* operation Operation to perform on the */
427 /* event flag group (AND/OR) */
428 /* */
429 /* OUTPUTS */
430 /* */
431 /* NU_SUCCESS If service is successful */
432 /* */
433 /* HISTORY */
434 /* */
435 /* DATE REMARKS */
436 /* */
437 /* 03-01-1993 Created initial version 1.0 */
438 /* 04-19-1993 Verified version 1.0 */
439 /* 03-01-1994 Changed function interfaces to */
440 /* match those in prototype, */
441 /* added register options, changed */
442 /* protection logic to reduce */
443 /* overhead, resulting in */
444 /* version 1.1 */
445 /* */
446 /* 03-18-1994 Verified version 1.1 */
447 /* 11-19-1996 Corrected SPR190. */
448 /* */
449 /*************************************************************************/
450 STATUS EVC_Set_Events(NU_EVENT_GROUP *event_group_ptr, UNSIGNED events,
451 OPTION operation)
452 {
453
454 R1 EV_GCB *event_group; /* Event control block ptr */
455 R2 EV_SUSPEND *suspend_ptr; /* Pointer to suspension blk */
456 R3 EV_SUSPEND *next_ptr; /* Pointer to next suspend */
457 R4 EV_SUSPEND *last_ptr; /* Last suspension block ptr */
458 UNSIGNED consume; /* Event flags to consume */
459 UNSIGNED compare; /* Event comparison variable */
460 INT preempt; /* Preemption required flag */
461 NU_SUPERV_USER_VARIABLES
462
463 /* Switch to supervisor mode */
464 NU_SUPERVISOR_MODE();
465
466 /* Move input event group pointer into internal pointer. */
467 event_group = (EV_GCB *) event_group_ptr;
468
469
470 #ifdef NU_ENABLE_STACK_CHECK
471
472 /* Call stack checking function to check for an overflow condition. */
473 TCT_Check_Stack();
474
475 #endif
476
477 #ifdef NU_ENABLE_HISTORY
478
479 /* Make an entry that corresponds to this function in the system history
480 log. */
481 HIC_Make_History_Entry(NU_SET_EVENTS_ID, (UNSIGNED) event_group,
482 (UNSIGNED) events, (UNSIGNED) operation);
483
484 #endif
485
486 /* Protect against simultaneous access to the event group. */
487 TCT_System_Protect();
488
489 /* Perform the specified operation on the current event flags in the
490 group. */
491 if (operation & EV_AND)
492
493 /* AND the specified events with the current events. */
494 event_group -> ev_current_events =
495 event_group -> ev_current_events & events;
496 else
497
498 /* OR the specified events with the current events. */
499 event_group -> ev_current_events =
500 event_group -> ev_current_events | events;
501
502 #ifdef INCLUDE_PROVIEW
503 _RTProf_DumpEventGroup(RT_PROF_SET_EVENTS,event_group , RT_PROF_OK);
504 #endif /*INCLUDE_PROVIEW*/
505 /* Determine if there are any tasks suspended for events from this
506 event flag group. */
507 if (event_group -> ev_suspension_list)
508 {
509
510 /* Initialize the consumption bits to 0. */
511 consume = 0;
512
513 /* Now, walk the chain of tasks suspended on this event flag group to
514 determine if any of their requests can be satisfied. */
515 suspend_ptr = event_group -> ev_suspension_list;
516
517 /* Setup a pointer to the last suspension block. */
518 last_ptr = (EV_SUSPEND *) suspend_ptr -> ev_suspend_link.cs_previous;
519
520 /* Clear the preempt flag. */
521 preempt = 0;
522 do
523 {
524
525 /* Determine if this request has been satisfied. */
526
527 /* First, find the event flags in common. */
528 compare = event_group -> ev_current_events &
529 suspend_ptr -> ev_requested_events;
530
531 /* Second, determine if all the event flags must match. */
532 if (suspend_ptr -> ev_operation & EV_AND)
533
534 /* Yes, an AND condition is present. All requested events
535 must be present. */
536 compare = (compare == suspend_ptr -> ev_requested_events);
537
538 /* Setup the next pointer. Note that this must be done before
539 the suspended task is resumed, since its suspend block could
540 get corrupted. */
541 next_ptr = (EV_SUSPEND *) suspend_ptr -> ev_suspend_link.cs_next;
542
543 /* If compare is non-zero, the suspended task's event request is
544 satisfied. */
545 if (compare)
546 {
547
548 /* Decrement the number of tasks waiting counter. */
549 event_group -> ev_tasks_waiting--;
550
551 /* Determine if consumption is requested. */
552 if (suspend_ptr -> ev_operation & EV_CONSUME)
553
554 /* Keep track of the event flags to consume. */
555 consume = consume | suspend_ptr -> ev_requested_events;
556
557 /* Remove the first suspended block from the list. */
558 CSC_Remove_From_List((CS_NODE **)
559 &(event_group -> ev_suspension_list),
560 &(suspend_ptr -> ev_suspend_link));
561
562 /* Setup the appropriate return value. */
563 suspend_ptr -> ev_return_status = NU_SUCCESS;
564 suspend_ptr -> ev_actual_events =
565 event_group -> ev_current_events;
566
567 /* Resume the suspended task. */
568 preempt = preempt |
569 TCC_Resume_Task((NU_TASK *) suspend_ptr -> ev_suspended_task,
570 NU_EVENT_SUSPEND);
571
572 }
573
574 /* Determine if there is another suspension block to examine. */
575 if (suspend_ptr != last_ptr)
576
577 /* More to examine in the suspension list. Look at the
578 next suspend block. */
579 suspend_ptr = next_ptr;
580 else
581
582 /* End of the list has been reached. Set the suspend pointer
583 to NULL to end the search. */
584 suspend_ptr = NU_NULL;
585
586 } while (suspend_ptr);
587
588 /* Apply all of the gathered consumption bits. */
589 event_group -> ev_current_events =
590 event_group -> ev_current_events & ~consume;
591
592 /* Determine if a preempt condition is present. */
593 if (preempt)
594
595 /* Transfer control to the system if the resumed task function
596 detects a preemption condition. */
597 TCT_Control_To_System();
598 }
599
600 /* Release protection of the event_group. */
601 TCT_Unprotect();
602
603 /* Return to user mode */
604 NU_USER_MODE();
605
606 /* Return a successful status. */
607 return(NU_SUCCESS);
608 }
609
610
611
612 /*************************************************************************/
613 /* */
614 /* FUNCTION */
615 /* */
616 /* EVC_Retrieve_Events */
617 /* */
618 /* DESCRIPTION */
619 /* */
620 /* This function retrieves various combinations of event flags from */
621 /* the specified event group. If the group does not contain the */
622 /* necessary flags, suspension of the calling task is possible. */
623 /* */
624 /* CALLED BY */
625 /* */
626 /* Application */
627 /* EVCE_Retrieve_Events Error checking shell */
628 /* */
629 /* CALLS */
630 /* */
631 /* CSC_Place_On_List Place on suspend list */
632 /* [HIC_Make_History_Entry] Make entry in history log */
633 /* TCC_Suspend_Task Suspend calling task */
634 /* [TCT_Check_Stack] Stack checking function */
635 /* TCT_Current_Thread Pickup current thread pointer*/
636 /* TCT_System_Protect Protect event group */
637 /* TCT_Unprotect Release protection */
638 /* */
639 /* INPUTS */
640 /* */
641 /* event_group_ptr Event Group control block ptr*/
642 /* requested_events Requested event flags */
643 /* operation AND/OR selection of flags */
644 /* retrieved_events Pointer to destination for */
645 /* actual flags retrieved */
646 /* suspend Suspension option */
647 /* */
648 /* OUTPUTS */
649 /* */
650 /* NU_SUCCESS If successful completion */
651 /* NU_TIMEOUT If timeout on suspension */
652 /* NU_NOT_PRESENT If event flags are not */
653 /* present */
654 /* */
655 /* HISTORY */
656 /* */
657 /* DATE REMARKS */
658 /* */
659 /* 03-01-1993 Created initial version 1.0 */
660 /* 04-19-1993 Verified version 1.0 */
661 /* 03-01-1994 Changed function interfaces to */
662 /* match those in prototype, */
663 /* added register options, changed */
664 /* protection logic to reduce */
665 /* overhead, resulting in */
666 /* version 1.1 */
667 /* */
668 /* 03-18-1994 Verified version 1.1 */
669 /* */
670 /*************************************************************************/
671 STATUS EVC_Retrieve_Events(NU_EVENT_GROUP *event_group_ptr,
672 UNSIGNED requested_events, OPTION operation,
673 UNSIGNED *retrieved_events, UNSIGNED suspend)
674 {
675
676 R1 EV_GCB *event_group; /* Event control block ptr */
677 R2 EV_SUSPEND *suspend_ptr; /* Pointer to suspend block */
678 EV_SUSPEND suspend_block; /* Suspension block */
679 R3 UNSIGNED compare; /* Event comparison variable */
680 TC_TCB *task; /* Pointer to task */
681 STATUS status; /* Completion status */
682 NU_SUPERV_USER_VARIABLES
683
684 /* Switch to supervisor mode */
685 NU_SUPERVISOR_MODE();
686
687 /* Move input event group pointer into internal pointer. */
688 event_group = (EV_GCB *) event_group_ptr;
689
690
691 #ifdef NU_ENABLE_STACK_CHECK
692
693 /* Call stack checking function to check for an overflow condition. */
694 TCT_Check_Stack();
695
696 #endif
697
698 #ifdef NU_ENABLE_HISTORY
699
700 /* Make an entry that corresponds to this function in the system history
701 log. */
702 HIC_Make_History_Entry(NU_RETRIEVE_EVENTS_ID, (UNSIGNED) event_group,
703 (UNSIGNED) requested_events, (UNSIGNED) operation);
704
705 #endif
706
707 /* Initialize the status as successful. */
708 status = NU_SUCCESS;
709
710 /* Protect against simultaneous access to the event group. */
711 TCT_System_Protect();
712
713 /* Determine if the events requested are present. */
714
715 /* Isolate common event flags. */
716 compare = event_group -> ev_current_events & requested_events;
717
718 /* Determine if all of the events must be present. */
719 if (operation & EV_AND)
720
721 /* Yes, all events must be present. See if the compare value is
722 the same as the requested value. */
723 compare = (compare == requested_events);
724
725 /* Determine if the requested combination of event flags are present. */
726 if (compare)
727 {
728
729 /* Yes, necessary event flags are present. */
730
731 /* Copy the current event flags into the appropriate destination. */
732 *retrieved_events = event_group -> ev_current_events;
733
734 /* Determine if consumption is required. If so, consume the event
735 flags present in the group. */
736 if (operation & EV_CONSUME)
737
738 event_group -> ev_current_events =
739 event_group -> ev_current_events & ~requested_events;
740
741 #ifdef INCLUDE_PROVIEW
742 _RTProf_DumpEventGroup(RT_PROF_RETRIEVE_EVENTS,event_group, RT_PROF_OK);
743 #endif /*INCLUDE_PROVIEW*/
744
745 }
746 else
747 {
748
749 /* Determine if the task requested suspension. */
750 if (suspend)
751 {
752
753 /* Suspension is selected. */
754
755 /* Increment the number of tasks waiting. */
756 event_group -> ev_tasks_waiting++;
757
758 #ifdef INCLUDE_PROVIEW
759 _RTProf_DumpEventGroup(RT_PROF_RETRIEVE_EVENTS,event_group, RT_PROF_WAIT);
760 #endif /*INCLUDE_PROVIEW*/
761
762 /* Setup the suspend block and suspend the calling task. */
763 suspend_ptr = &suspend_block;
764 suspend_ptr -> ev_event_group = event_group;
765 suspend_ptr -> ev_suspend_link.cs_next = NU_NULL;
766 suspend_ptr -> ev_suspend_link.cs_previous = NU_NULL;
767 task = (TC_TCB *) TCT_Current_Thread();
768 suspend_ptr -> ev_suspended_task = task;
769 suspend_ptr -> ev_requested_events = requested_events;
770 suspend_ptr -> ev_operation = operation;
771
772 /* Link the suspend block into the list of suspended tasks on this
773 event group. */
774 CSC_Place_On_List((CS_NODE **)
775 &(event_group -> ev_suspension_list),
776 &(suspend_ptr -> ev_suspend_link));
777
778 /* Finally, suspend the calling task. Note that the suspension call
779 automatically clears the protection on the event group. */
780 TCC_Suspend_Task((NU_TASK *) task, NU_EVENT_SUSPEND,
781 EVC_Cleanup, suspend_ptr, suspend);
782
783 /* Pickup the return status and the actual retrieved events. */
784 status = suspend_ptr -> ev_return_status;
785 *retrieved_events = suspend_ptr -> ev_actual_events;
786 }
787 else
788 {
789
790 /* No suspension requested. Simply return an error status
791 and zero the retrieved events variable. */
792 status = NU_NOT_PRESENT;
793 *retrieved_events = 0;
794 #ifdef INCLUDE_PROVIEW
795 _RTProf_DumpEventGroup(RT_PROF_RETRIEVE_EVENTS,event_group,RT_PROF_FAIL);
796 #endif /*INCLUDE_PROVIEW*/
797 }
798 }
799
800 /* Release protection of the event_group. */
801 TCT_Unprotect();
802
803 /* Return to user mode */
804 NU_USER_MODE();
805
806 /* Return the completion status. */
807 return(status);
808 }
809
810
811 /*************************************************************************/
812 /* */
813 /* FUNCTION */
814 /* */
815 /* EVC_Cleanup */
816 /* */
817 /* DESCRIPTION */
818 /* */
819 /* This function is responsible for removing a suspension block */
820 /* from a event group. It is not called unless a timeout or a task */
821 /* terminate is in progress. Note that protection is already in */
822 /* effect - the same protection at suspension time. This routine */
823 /* must be called from Supervisor mode in Supervisor/User mode */
824 /* switching kernels. */
825 /* */
826 /* CALLED BY */
827 /* */
828 /* TCC_Timeout Task timeout */
829 /* TCC_Terminate Task terminate */
830 /* */
831 /* CALLS */
832 /* */
833 /* CSC_Remove_From_List Remove suspend block from */
834 /* the suspension list */
835 /* */
836 /* INPUTS */
837 /* */
838 /* information Pointer to suspend block */
839 /* */
840 /* OUTPUTS */
841 /* */
842 /* None */
843 /* */
844 /* HISTORY */
845 /* */
846 /* DATE REMARKS */
847 /* */
848 /* 03-01-1993 Created initial version 1.0 */
849 /* 04-19-1993 Verified version 1.0 */
850 /* */
851 /*************************************************************************/
852 VOID EVC_Cleanup(VOID *information)
853 {
854
855 EV_SUSPEND *suspend_ptr; /* Suspension block pointer */
856 NU_SUPERV_USER_VARIABLES
857
858 /* Switch to supervisor mode */
859 NU_SUPERVISOR_MODE();
860
861 /* Use the information pointer as a suspend pointer. */
862 suspend_ptr = (EV_SUSPEND *) information;
863
864 /* By default, indicate that the service timed-out. It really does not
865 matter if this function is called from a terminate request since
866 the task does not resume. */
867 suspend_ptr -> ev_return_status = NU_TIMEOUT;
868
869 /* Decrement the number of tasks waiting counter. */
870 (suspend_ptr -> ev_event_group) -> ev_tasks_waiting--;
871
872 /* Unlink the suspend block from the suspension list. */
873 CSC_Remove_From_List((CS_NODE **)
874 &((suspend_ptr -> ev_event_group) -> ev_suspension_list),
875 &(suspend_ptr -> ev_suspend_link));
876
877 /* Return to user mode */
878 NU_USER_MODE();
879 }
880
881
882
883
884
885
886