comparison src/nucleus/tmc.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 /* tmc.c Nucleus PLUS 1.14 */
17 /* */
18 /* COMPONENT */
19 /* */
20 /* TM - Timer Management */
21 /* */
22 /* DESCRIPTION */
23 /* */
24 /* This file contains the core routines for the timer management */
25 /* component. */
26 /* */
27 /* DATA STRUCTURES */
28 /* */
29 /* None */
30 /* */
31 /* FUNCTIONS */
32 /* */
33 /* TMC_Init_Task_Timer Initialize task timer */
34 /* TMC_Start_Task_Timer Start task timer */
35 /* TMC_Stop_Task_Timer Stop task timer */
36 /* TMC_Start_Timer Actually start a timer */
37 /* TMC_Stop_Timer Actually stop a timer */
38 /* TMC_Timer_HISR Timer High-Level Interrupt */
39 /* Service Routine (HISR) */
40 /* TMC_Timer_Expiration Timer expiration function */
41 /* */
42 /* DEPENDENCIES */
43 /* */
44 /* cs_extr.h Common Service functions */
45 /* tc_extr.h Thread Control functions */
46 /* tm_extr.h Timer functions */
47 /* hi_extr.h History functions */
48 /* */
49 /* HISTORY */
50 /* */
51 /* DATE REMARKS */
52 /* */
53 /* 03-01-1993 Created initial version 1.0 */
54 /* 04-19-1993 Verified version 1.0 */
55 /* 08-09-1993 Corrected the following problems */
56 /* - Moved sleep, timeout, and */
57 /* application timer expiration */
58 /* processing to system timer */
59 /* HISR. Removed timer task */
60 /* logic */
61 /* - Corrected a disable timer */
62 /* problem that caused a delay */
63 /* in subsequent timer */
64 /* expiration */
65 /* - Corrected the application */
66 /* timer ID returned by the */
67 /* timer information service */
68 /* Corrected the loop to return */
69 /* all application timer */
70 /* pointers */
71 /* - Corrected timer expiration */
72 /* while accessing from an LISR */
73 /* - Using the task time slice ptr */
74 /* instead of the time slice */
75 /* state flag */
76 /* Modifications resulted in */
77 /* version 1.0a */
78 /* 08-09-1993 Verified version 1.0a */
79 /* 03-01-1994 Moved non-core functions into */
80 /* supplemental files, modified */
81 /* protection logic to use system */
82 /* protect mechanism, removed the */
83 /* disable timer logic in start */
84 /* timer, insured valid time- */
85 /* slice task pointer, added */
86 /* register logic, resulting */
87 /* in version 1.1 */
88 /* */
89 /* 3-18-1994 Verified version 1.1 */
90 /* 08-25-95 Made the following changes */
91 /* */
92 /* +INT type = 0; Type of expiration */
93 /* +VOID *pointer = NU_NULL; Pointer type */
94 /* +UNSIGNED id = 0; Application timer ID */
95 /* -INT type; Type of expiration */
96 /* -VOID *pointer; Pointer type */
97 /* -UNSIGNED id; Application timer ID */
98 /* Expiration routine ptr */
99 /* +VOID (*expiration_routine)(UNSIGNED)= NU_NULL; */
100 /* -VOID (*expiration_routine)(UNSIGNED); */
101 /* 04-17-1996 updated to version 1.2 */
102 /* 03-24-1998 Released version 1.3. */
103 /* 03-26-1999 Released 1.11m (new release */
104 /* numbering scheme) */
105 /* 04-17-2002 Released version 1.13m */
106 /* 11-07-2002 Released version 1.14 */
107 /*************************************************************************/
108 #define NU_SOURCE_FILE
109
110
111 #include "cs_extr.h" /* Common service functions */
112 #include "tc_extr.h" /* Thread control functions */
113 #include "tm_extr.h" /* Timer functions */
114 #include "hi_extr.h" /* History functions */
115
116
117 /* Define external inner-component global data references. */
118
119 extern TM_TCB *TMD_Active_Timers_List;
120 extern INT TMD_Active_List_Busy;
121 extern UNSIGNED TMD_System_Clock;
122 extern UNSIGNED TMD_Timer_Start;
123 extern UNSIGNED TMD_Timer;
124 extern INT TMD_Timer_State;
125 extern UNSIGNED TMD_Time_Slice;
126 extern TC_TCB *TMD_Time_Slice_Task;
127 extern INT TMD_Time_Slice_State;
128
129
130 /* Define internal function prototypes. */
131
132 VOID TMC_Start_Timer(TM_TCB *timer, UNSIGNED time);
133 VOID TMC_Stop_Timer(TM_TCB *timer);
134 VOID TMC_Timer_Expiration(VOID);
135 UNSIGNED TMT_Read_Timer(VOID);
136 VOID TMT_Enable_Timer(UNSIGNED time);
137 VOID TMT_Disable_Timer(VOID);
138
139
140
141 /*************************************************************************/
142 /* */
143 /* FUNCTION */
144 /* */
145 /* TMC_Init_Task_Timer */
146 /* */
147 /* DESCRIPTION */
148 /* */
149 /* This function is responsible for initializing the supplied task */
150 /* timer. This routine must be called from Supervisor mode in a */
151 /* Supervisor/User mode switching kernel. */
152 /* */
153 /* CALLED BY */
154 /* */
155 /* TCC_Create_Task Task create function */
156 /* */
157 /* CALLS */
158 /* */
159 /* None */
160 /* */
161 /* INPUTS */
162 /* */
163 /* timer Timer control block pointer */
164 /* information Information pointer - always */
165 /* the task pointer */
166 /* */
167 /* OUTPUTS */
168 /* */
169 /* None */
170 /* */
171 /* HISTORY */
172 /* */
173 /* DATE REMARKS */
174 /* */
175 /* 03-01-1993 Created initial version 1.0 */
176 /* 04-19-1993 Verified version 1.0 */
177 /* */
178 /*************************************************************************/
179 VOID TMC_Init_Task_Timer(TM_TCB *timer, VOID *information)
180 {
181
182 /* Initialize the task timer. */
183 timer -> tm_timer_type = TM_TASK_TIMER;
184 timer -> tm_information = information;
185 timer -> tm_next_timer = NU_NULL;
186 timer -> tm_previous_timer = NU_NULL;
187 }
188
189
190 /*************************************************************************/
191 /* */
192 /* FUNCTION */
193 /* */
194 /* TMC_Start_Task_Timer */
195 /* */
196 /* DESCRIPTION */
197 /* */
198 /* This function is responsible for starting a task timer. Note */
199 /* that there are some special protection considerations since */
200 /* this function is called from the task control component. This */
201 /* routine must be called from Supervisor mode in a Supervisor/User */
202 /* mode switching kernel. */
203 /* */
204 /* CALLED BY */
205 /* */
206 /* TCC_Suspend_Task Suspend task with a timeout */
207 /* */
208 /* CALLS */
209 /* */
210 /* TMC_Start_Timer Start the timer */
211 /* */
212 /* INPUTS */
213 /* */
214 /* timer Timer control block pointer */
215 /* time Time associated with timer */
216 /* */
217 /* OUTPUTS */
218 /* */
219 /* None */
220 /* */
221 /* HISTORY */
222 /* */
223 /* DATE REMARKS */
224 /* */
225 /* 03-01-1993 Created initial version 1.0 */
226 /* 04-19-1993 Verified version 1.0 */
227 /* 03-01-1994 Removed protection logic since */
228 /* system protect is in force at */
229 /* the time this function is */
230 /* called, resulting in */
231 /* version 1.1 */
232 /* */
233 /* 03-18-1994 Verified version 1.1 */
234 /* */
235 /*************************************************************************/
236 VOID TMC_Start_Task_Timer(TM_TCB *timer, UNSIGNED time)
237 {
238
239 /* Start the specified timer. */
240 TMC_Start_Timer(timer, time);
241 }
242
243
244 /*************************************************************************/
245 /* */
246 /* FUNCTION */
247 /* */
248 /* TMC_Stop_Task_Timer */
249 /* */
250 /* DESCRIPTION */
251 /* */
252 /* This function is responsible for stopping a task timer. Note */
253 /* that there are some special protection considerations since */
254 /* this function is called from the task control component. This */
255 /* routine must be called from Supervisor mode in a Supervisor/User */
256 /* mode switching kernel. */
257 /* */
258 /* CALLED BY */
259 /* */
260 /* TCC_Resume_Task Resume task function */
261 /* TCC_Terminate_Task Terminate task function */
262 /* */
263 /* CALLS */
264 /* */
265 /* TMC_Stop_Timer Stop the timer */
266 /* */
267 /* INPUTS */
268 /* */
269 /* timer Timer control block pointer */
270 /* */
271 /* OUTPUTS */
272 /* */
273 /* None */
274 /* */
275 /* HISTORY */
276 /* */
277 /* DATE REMARKS */
278 /* */
279 /* 03-01-1993 Created initial version 1.0 */
280 /* 04-19-1993 Verified version 1.0 */
281 /* 03-01-1994 Removed protection logic since */
282 /* system protect is in force at */
283 /* the time this function is */
284 /* called, resulting in */
285 /* version 1.1 */
286 /* */
287 /* 03-18-1994 Verified version 1.1 */
288 /* */
289 /*************************************************************************/
290 VOID TMC_Stop_Task_Timer(TM_TCB *timer)
291 {
292
293 /* Stop the specified timer - if it is still active. */
294 if (timer -> tm_next_timer)
295
296 TMC_Stop_Timer(timer);
297 }
298
299
300 /*************************************************************************/
301 /* */
302 /* FUNCTION */
303 /* */
304 /* TMC_Start_Timer */
305 /* */
306 /* DESCRIPTION */
307 /* */
308 /* This function is responsible for starting both application and */
309 /* task timers. This routine must be called from Supervisor mode */
310 /* in a Supervisor/User mode switching kernel. */
311 /* */
312 /* CALLED BY */
313 /* */
314 /* TMC_Control_Timer Control application timer */
315 /* TMC_Start_Task_Timer Start task timer */
316 /* */
317 /* CALLS */
318 /* */
319 /* TMT_Read_Timer Read current timer counter */
320 /* TMT_Adjust_Timer Adjust the count-down timer */
321 /* TMT_Enable_Timer Enable count-down timer */
322 /* */
323 /* INPUTS */
324 /* */
325 /* timer Timer control block pointer */
326 /* time Time associated with timer */
327 /* */
328 /* OUTPUTS */
329 /* */
330 /* None */
331 /* */
332 /* HISTORY */
333 /* */
334 /* DATE REMARKS */
335 /* */
336 /* 03-01-1993 Created initial version 1.0 */
337 /* 04-19-1993 Verified version 1.0 */
338 /* 08-09-1993 Added logic to check for timer */
339 /* expiration before or during */
340 /* another LISR's access, */
341 /* resulting in version 1.0a */
342 /* 08-09-1993 Verified version 1.0a */
343 /* 03-01-1994 Removed disable timer logic to */
344 /* insure there is no timer loss, */
345 /* added register logic, */
346 /* resulting in version 1.1 */
347 /* */
348 /* 03-18-1994 Verified version 1.1 */
349 /* */
350 /*************************************************************************/
351 VOID TMC_Start_Timer(TM_TCB *timer, UNSIGNED time)
352 {
353
354 R1 TM_TCB *list_ptr; /* Working pointer timer ptr */
355 UNSIGNED elapsed; /* Elapsed time variable */
356 INT done; /* Search finished flag */
357
358
359 /* Note that protection over the active timer list is in force when this
360 function is called. */
361
362 /* Determine if the active list is empty. */
363 if (TMD_Active_Timers_List == NU_NULL)
364 {
365
366 /* Place the timer on an empty list. */
367 timer -> tm_next_timer = timer;
368 timer -> tm_previous_timer = timer;
369
370 /* Link the timer to the list head. */
371 TMD_Active_Timers_List = timer;
372
373 /* Setup the actual count-down timer structures. */
374 TMD_Timer_Start = time;
375 timer -> tm_remaining_time = time;
376
377
378 /* BUG FIX FOR NU_RESET WITH INITIAL TIME OF 0 */
379 /* Determine if there is any time remaining on the timer.
380 If so, enable the timer. Otherwise, the Timer HISR is
381 already pending, so skip starting the timer again. */
382
383 if (time != 0)
384 /* Start the actual count-down timer. */
385 TMT_Enable_Timer(TMD_Timer_Start);
386 else
387 TMD_Timer_State = TM_EXPIRED;
388
389 }
390 else
391 {
392
393 /* Place the new timer into the list. */
394
395 /* Pickup the head of the list. */
396 list_ptr = TMD_Active_Timers_List;
397
398 /* Determine if the timer is being added while the timer
399 expiration task is running. If so, don't attempt to adjust
400 the expiration list. If not, adjust the list. */
401 if (!TMD_Active_List_Busy)
402 {
403
404 /* Calculate the elapsed amount of time from the last timer
405 request. */
406 elapsed = TMD_Timer_Start - TMT_Read_Timer();
407
408 /* Adjust the first entry in the timer list and the timer
409 start value accordingly. */
410 TMD_Timer_Start = TMD_Timer_Start - elapsed;
411
412 /* Make sure the remaining time is never below zero. */
413 if (list_ptr -> tm_remaining_time > elapsed)
414 {
415 list_ptr -> tm_remaining_time = list_ptr -> tm_remaining_time
416 - elapsed;
417 }
418 else
419 {
420 list_ptr -> tm_remaining_time = 0;
421 }
422
423
424 }
425
426 /* At this point the timer list is accurate again. Find the
427 appropriate place on the timer list for the new timer. */
428
429 /* Determine where to place the timer in the list. */
430 done = NU_FALSE;
431 do
432 {
433
434 /* Determine if the timer belongs before the current timer
435 pointed to by list_ptr. */
436 if (time < list_ptr -> tm_remaining_time)
437 {
438
439 /* Update the time of the next timer. */
440 list_ptr -> tm_remaining_time =
441 list_ptr -> tm_remaining_time - time;
442
443 /* Determine if an insertion at the head of the list is
444 present. */
445 if (list_ptr == TMD_Active_Timers_List)
446
447 /* Move the list head to the new timer. */
448 TMD_Active_Timers_List = timer;
449
450 /* Set the done flag to end the search. */
451 done = NU_TRUE;
452 }
453 else
454 {
455
456 /* Decrement the time by the remaining value of each timer in
457 the list. In this way, the list never has to be searched
458 again. */
459 time = time - list_ptr -> tm_remaining_time;
460
461 /* Move the list pointer to the next timer in the list. */
462 list_ptr = list_ptr -> tm_next_timer;
463
464 /* Check to see if the list has wrapped around. */
465 if (list_ptr == TMD_Active_Timers_List)
466
467 /* Searching is done. */
468 done = NU_TRUE;
469 }
470 } while (!done);
471
472 /* Link the new timer into the list. */
473 timer -> tm_next_timer = list_ptr;
474 timer -> tm_previous_timer = list_ptr -> tm_previous_timer;
475 (list_ptr -> tm_previous_timer) -> tm_next_timer = timer;
476 list_ptr -> tm_previous_timer = timer;
477
478 /* Update the remaining time parameter. */
479 timer -> tm_remaining_time = time;
480
481 /* Determine if a new timer should be started. */
482 if (!TMD_Active_List_Busy)
483 {
484
485 /* Calculate the new timer expiration. */
486 time = TMD_Active_Timers_List -> tm_remaining_time;
487
488 /* Determine if the new expiration is less than the current
489 time, if any. If not, let already started time expire. */
490 if (time <= TMD_Timer_Start)
491 {
492
493 /* Setup for a smaller timer expiration. */
494 TMD_Timer_Start = time;
495
496 /* Determine if there is any time remaining on the timer in
497 the front of the list. If so, adjust the timer.
498 Otherwise, the Timer HISR is already pending, so skip
499 starting the timer again. */
500 if (TMD_Timer_Start)
501
502 /* Still some remaining time, adjust the timer. */
503 TMT_Adjust_Timer(TMD_Timer_Start);
504 else
505
506 /* Indicate that the task and application timer has
507 expired. */
508 TMD_Timer_State = TM_EXPIRED;
509 }
510 }
511 }
512 }
513
514
515 /*************************************************************************/
516 /* */
517 /* FUNCTION */
518 /* */
519 /* TMC_Stop_Timer */
520 /* */
521 /* DESCRIPTION */
522 /* */
523 /* This function is responsible for stopping both application and */
524 /* task timers. This routine must be called from Supervisor mode */
525 /* in a Supervisor/User mode switching kernel. */
526 /* */
527 /* CALLED BY */
528 /* */
529 /* TMC_Control_Timer Control application timer */
530 /* TMC_Stop_Task_Timer Start task timer */
531 /* */
532 /* CALLS */
533 /* */
534 /* TMT_Disable_Timer Disable the count-down timer */
535 /* */
536 /* INPUTS */
537 /* */
538 /* timer Timer control block pointer */
539 /* */
540 /* OUTPUTS */
541 /* */
542 /* None */
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 /* 08-09-1993 Corrected a problem associated */
551 /* with stopping the last timer */
552 /* on the active list, resulting */
553 /* in version 1.0a */
554 /* 08-09-1993 Verified version 1.0a */
555 /* */
556 /*************************************************************************/
557 VOID TMC_Stop_Timer(TM_TCB *timer)
558 {
559
560 /* Note that the active timer list is already under protection. */
561
562 /* If the next neighbor of the timer that needs to be stopped is not the
563 head of the timer list, add the remaining time field to the remaining
564 time of the next neighbor. */
565 if ((timer -> tm_next_timer) != TMD_Active_Timers_List)
566
567 /* Adjust the next neighbor's remaining time field. */
568 (timer -> tm_next_timer) -> tm_remaining_time =
569 (timer -> tm_next_timer) -> tm_remaining_time +
570 timer -> tm_remaining_time;
571
572 /* Unlink the timer from the active list. */
573 if (timer -> tm_next_timer == timer)
574 {
575 /* Only timer on the list. */
576 TMD_Active_Timers_List = NU_NULL;
577
578 /* Disable the timer. */
579 TMT_Disable_Timer();
580 }
581 else
582 {
583
584 /* More than one timer on the list. */
585 (timer -> tm_previous_timer) -> tm_next_timer = timer -> tm_next_timer;
586 (timer -> tm_next_timer) -> tm_previous_timer =
587 timer -> tm_previous_timer;
588
589 /* Determine if the timer is at the head of the list. */
590 if (TMD_Active_Timers_List == timer)
591
592 /* Yes, move the head pointer to the next timer. */
593 TMD_Active_Timers_List = timer -> tm_next_timer;
594 }
595
596 /* Clear the timer's next and previous pointers. */
597 timer -> tm_next_timer = NU_NULL;
598 timer -> tm_previous_timer = NU_NULL;
599 }
600
601
602 /*************************************************************************/
603 /* */
604 /* FUNCTION */
605 /* */
606 /* TMC_Timer_HISR */
607 /* */
608 /* DESCRIPTION */
609 /* */
610 /* This function is responsible for High-Level interrupt processing */
611 /* of a timer expiration. If an application timer has expired, */
612 /* the timer expiration function is called. Otherwise, if the */
613 /* time-slice timer has expired, time-slice processing is invoked. */
614 /* */
615 /* CALLED BY */
616 /* */
617 /* None */
618 /* */
619 /* CALLS */
620 /* */
621 /* TCC_Time_Slice Task time-slice processing */
622 /* TMC_Timer_Expiration Timer expiration processing */
623 /* TMT_Retrieve_TS_Task Retrieve time-sliced task ptr*/
624 /* */
625 /* INPUTS */
626 /* */
627 /* None */
628 /* */
629 /* OUTPUTS */
630 /* */
631 /* None */
632 /* */
633 /* HISTORY */
634 /* */
635 /* DATE REMARKS */
636 /* */
637 /* 03-01-1993 Created initial version 1.0 */
638 /* 04-19-1993 Verified version 1.0 */
639 /* 08-09-1993 Added sleep, timeout, and */
640 /* application timer expiration */
641 /* processing to the timer HISR, */
642 /* using time slice task pointer */
643 /* instead of state flag, */
644 /* resulting in version 1.0a */
645 /* 08-09-1993 Verified version 1.0a */
646 /* 03-01-1994 Modified function interface to */
647 /* TCC_Time_Slice, added logic to */
648 /* insure valid pointer for some */
649 /* ports, resulting in version 1.1 */
650 /* */
651 /* 03-18-1994 Verified version 1.1 */
652 /* */
653 /*************************************************************************/
654 VOID TMC_Timer_HISR(VOID)
655 {
656
657 NU_TASK *task; /* Time slice task. */
658
659
660 /* Determine if the task timer has expired. */
661 if (TMD_Timer_State == TM_EXPIRED)
662
663 /* Resume the timer task. */
664 TMC_Timer_Expiration();
665
666 /* Determine if the time-slice timer has expired. */
667 task = TMT_Retrieve_TS_Task();
668 if (task)
669 {
670 NU_SUPERV_USER_VARIABLES
671
672 /* Switch to supervisor mode
673
674 Note that this HISR function can make the switch to supervisor mode
675 this is only possible because the code lives within the kernel */
676 NU_SUPERVISOR_MODE();
677
678 /* Reset the time-slice state. */
679 TMD_Time_Slice_State = TM_NOT_ACTIVE;
680
681 /* Process the time-slice. */
682 TCC_Time_Slice(task);
683
684 /* Clear the time slice task pointer. */
685 TMD_Time_Slice_Task = NU_NULL;
686
687 /* Return to user mode */
688 NU_USER_MODE();
689 }
690 }
691
692
693 /*************************************************************************/
694 /* */
695 /* FUNCTION */
696 /* */
697 /* TMC_Timer_Expiration */
698 /* */
699 /* DESCRIPTION */
700 /* */
701 /* This function is responsible for processing all task timer */
702 /* expirations. This includes application timers and basic task */
703 /* timers that are used for task sleeping and timeouts. */
704 /* */
705 /* CALLED BY */
706 /* */
707 /* None */
708 /* */
709 /* CALLS */
710 /* */
711 /* expiration_function Application specified timer */
712 /* expiration function */
713 /* TCC_Task_Timeout Task timeout function */
714 /* TCT_System_Protect Protect active timer list */
715 /* TCT_Unprotect Release protection of list */
716 /* TMC_Stop_Timer Stop timer */
717 /* TMC_Start_Timer Start timer */
718 /* TMT_Disable_Timer Disable timer */
719 /* TMT_Enable_Timer Enable timer */
720 /* */
721 /* INPUTS */
722 /* */
723 /* None */
724 /* */
725 /* OUTPUTS */
726 /* */
727 /* None */
728 /* */
729 /* HISTORY */
730 /* */
731 /* DATE REMARKS */
732 /* */
733 /* 03-01-1993 Created initial version 1.0 */
734 /* 04-19-1993 Verified version 1.0 */
735 /* 08-09-1993 Changed from TMC_Timer_Task to */
736 /* TMC_Timer_Expiration, */
737 /* resulting in version 1.0a */
738 /* 08-09-1993 Verified version 1.0a */
739 /* 03-01-1994 Modified function interface to */
740 /* TCC_Task_Timeout, changed */
741 /* protection logic to use system */
742 /* protetion, added register */
743 /* logic, resulting in version 1.1 */
744 /* */
745 /* 03-18-1994 Verified version 1.1 */
746 /* 08-25-95 Made the following changes */
747 /* */
748 /* +INT type = 0; Type of expiration */
749 /* +VOID *pointer = NU_NULL; Pointer type */
750 /* +UNSIGNED id = 0; Application timer ID */
751 /* -INT type; Type of expiration */
752 /* -VOID *pointer; Pointer type */
753 /* -UNSIGNED id; Application timer ID */
754 /* Expiration routine ptr */
755 /* +VOID (*expiration_routine)(UNSIGNED)= NU_NULL; */
756 /* -VOID (*expiration_routine)(UNSIGNED); */
757 /* */
758 /*************************************************************************/
759 VOID TMC_Timer_Expiration(VOID)
760 {
761
762 R1 TM_TCB *timer; /* Pointer to timer */
763 R2 TM_APP_TCB *app_timer; /* Pointer to app timer */
764 INT done; /* Expiration completion */
765 INT type = 0; /* Type of expiration */
766 VOID *pointer = NU_NULL; /* Pointer type */
767 UNSIGNED id = 0; /* Application timer ID */
768 /* Expiration routine ptr */
769 VOID (*expiration_routine)(UNSIGNED)= NU_NULL;
770 NU_SUPERV_USER_VARIABLES
771
772 /* Switch to supervisor mode */
773 NU_SUPERVISOR_MODE();
774
775 /* Use system protect to protect the active timer list. */
776 TCT_System_Protect();
777
778 /* Reset the timer state flag. */
779 TMT_Disable_Timer();
780
781 /* Set the busy flag to indicate that the list is being processed. */
782 TMD_Active_List_Busy = NU_TRUE;
783
784 /* Update the head of the list with the timer expiration
785 value. */
786 timer = TMD_Active_Timers_List;
787 if (timer)
788 {
789
790 /* Adjust the active timer's remaining time value. Note that
791 TMD_Timer_Start is never greater than the value in the first
792 timer location. */
793 if (timer -> tm_remaining_time > TMD_Timer_Start)
794
795 /* Timer has not expired. Simply subtract the last timer
796 value. */
797 timer -> tm_remaining_time = timer -> tm_remaining_time -
798 TMD_Timer_Start;
799 else
800
801 /* Clear the remaining time field of the timer. */
802 timer -> tm_remaining_time = 0;
803 }
804
805 /* Release protection, but keep the busy flag set to prevent
806 activating new timers. */
807 TCT_Unprotect();
808
809
810 /* Find expired timers. Note that the expired timers have values of
811 0 in the remaining time field. */
812 done = NU_FALSE;
813 do
814 {
815
816 /* Protect against list access. */
817 TCT_System_Protect();
818
819 /* Pickup the head of the active list. */
820 timer = TMD_Active_Timers_List;
821
822 /* Determine if the timer now at the head of the list has
823 expired. Processing continues until the list is empty or
824 until a non-expired timer is at the front of the list. */
825 if ((timer) && (timer -> tm_remaining_time == 0))
826 {
827
828 /* Timer has expired. Determine which type of timer has
829 expired. */
830 if (timer -> tm_timer_type == TM_APPL_TIMER)
831 {
832
833 /* Application timer has expired. */
834 type = TM_APPL_TIMER;
835
836 /* Pickup the pointer to the application timer control
837 block. */
838 app_timer = (TM_APP_TCB *) timer -> tm_information;
839
840 /* Increment the number of expirations. */
841 app_timer -> tm_expirations++;
842 #ifdef INCLUDE_PROVIEW
843 _RTProf_DumpTimer(RT_PROF_APP_TIMER_EXPIRED,app_timer,RT_PROF_OK);
844 #endif
845
846 /* Move the expiration information into local variables
847 in case they get corrupted before this expiration can
848 be processed. Expirations are processed without the
849 list protection in force. */
850 id = app_timer -> tm_expiration_id;
851 expiration_routine = app_timer -> tm_expiration_routine;
852
853 /* Clear the enabled flag and remove the timer from the
854 list. */
855 app_timer -> tm_enabled = NU_FALSE;
856 TMC_Stop_Timer(timer);
857
858 /* Determine if this timer should be started again. */
859 if (app_timer -> tm_reschedule_time)
860 {
861
862 /* Timer needs to be rescheduled. */
863
864 /* Setup the enable flag to show that the timer is
865 enabled. */
866 app_timer -> tm_enabled = NU_TRUE;
867
868 /* Call the start timer function to actually enable
869 the timer. This also puts it in the proper place
870 on the list. */
871 TMC_Start_Timer(timer,app_timer -> tm_reschedule_time);
872 }
873 }
874 else
875 {
876
877 /* Task timer has expired (sleeps and timeouts). */
878 type = TM_TASK_TIMER;
879
880 /* Remove the timer from the list. */
881 TMC_Stop_Timer(timer);
882
883 /* Save-off the task control block pointer. */
884 pointer = timer -> tm_information;
885 }
886 }
887 else
888
889 /* Processing is now complete- no more expired timers on the
890 list. */
891 done = NU_TRUE;
892
893 /* Release protection of active list. */
894 TCT_Unprotect();
895
896 /* Determine if a timer expiration needs to be finished. Note
897 that the actual expiration processing is done with protection
898 disabled. This prevents deadlock situations from arising. */
899 if (!done)
900 {
901
902 /* Determine which type of timer has expired. */
903 if (type == TM_APPL_TIMER)
904
905 /* Call application timer's expiration function. */
906 (*(expiration_routine)) (id);
907 else
908
909 /* Call the task timeout function in the thread control
910 function. */
911 TCC_Task_Timeout((NU_TASK *) pointer);
912 }
913 } while (!done);
914
915 /* Protect the active list again. */
916 TCT_System_Protect();
917
918 /* Clear the busy flag to indicate that list processing is complete. */
919 TMD_Active_List_Busy = NU_FALSE;
920
921 /* Determine if a new timer should be enabled. */
922 if (TMD_Active_Timers_List)
923 {
924
925 /* Yes, a new timer should be activated. */
926
927 /* Pickup the new timer expiration value. */
928 TMD_Timer_Start = TMD_Active_Timers_List -> tm_remaining_time;
929
930 /* Start the new timer. */
931 TMT_Enable_Timer(TMD_Timer_Start);
932 }
933
934 /* Release protection of the active timer list. */
935 TCT_Unprotect();
936
937 /* Return to user mode */
938 NU_USER_MODE();
939 }
940
941
942
943
944