FreeCalypso > hg > ffs-editor
comparison src/nucleus/evc.c @ 0:92470e5d0b9e
src: partial import from FC Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 15 May 2020 01:28:16 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92470e5d0b9e |
---|---|
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 |