FreeCalypso > hg > ffs-editor
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 |