1 /* 2 * Watchdog timer management. These functions in this file provide a 3 * convenient interface to the timers library that manages a list of 4 * watchdog timers. All details of scheduling an alarm at the CLOCK task 5 * are hidden behind this interface. 6 * 7 * The entry points into this file are: 8 * init_timer: initialize a timer structure 9 * set_timer: reset and existing or set a new watchdog timer 10 * cancel_timer: remove a timer from the list of timers 11 * expire_timers: check for expired timers and run watchdog functions 12 * 13 */ 14 15 #include "syslib.h" 16 #include <minix/timers.h> 17 #include <minix/sysutil.h> 18 19 static minix_timer_t *timers = NULL; 20 static int expiring = FALSE; 21 22 /* 23 * Initialize the timer 'tp'. 24 */ 25 void 26 init_timer(minix_timer_t * tp) 27 { 28 29 tmr_inittimer(tp); 30 } 31 32 /* 33 * Set the timer 'tp' to trigger 'ticks' clock ticks in the future. When it 34 * triggers, call function 'watchdog' with argument 'arg'. The given timer 35 * object must have been initialized with init_timer(3) already. The given 36 * number of ticks must be between 0 and TMRDIFF_MAX inclusive. A ticks value 37 * of zero will cause the alarm to trigger on the next clock tick. If the 38 * timer was already set, it will be canceled first. 39 */ 40 void 41 set_timer(minix_timer_t *tp, clock_t ticks, tmr_func_t watchdog, int arg) 42 { 43 clock_t prev_time, next_time; 44 int r, had_timers; 45 46 if (ticks > TMRDIFF_MAX) 47 panic("set_timer: ticks value too large: %u", (int)ticks); 48 49 /* Add the timer to the list. */ 50 had_timers = tmrs_settimer(&timers, tp, getticks() + ticks, watchdog, 51 arg, &prev_time, &next_time); 52 53 /* Reschedule our synchronous alarm if necessary. */ 54 if (!expiring && (!had_timers || next_time != prev_time)) { 55 if ((r = sys_setalarm(next_time, TRUE /*abs_time*/)) != OK) 56 panic("set_timer: couldn't set alarm: %d", r); 57 } 58 } 59 60 /* 61 * Cancel the timer 'tp'. The timer object must have been initialized with 62 * init_timer(3) first. If the timer was not set before, the call is a no-op. 63 */ 64 void 65 cancel_timer(minix_timer_t * tp) 66 { 67 clock_t next_time, prev_time; 68 int r, have_timers; 69 70 if (!tmr_is_set(tp)) 71 return; 72 73 have_timers = tmrs_clrtimer(&timers, tp, &prev_time, &next_time); 74 75 /* 76 * If the earliest timer has been removed, we have to set the alarm to 77 * the next timer, or cancel the alarm altogether if the last timer 78 * has been canceled. 79 */ 80 if (!expiring) { 81 if (!have_timers) 82 r = sys_setalarm(0, FALSE /*abs_time*/); 83 else if (prev_time != next_time) 84 r = sys_setalarm(next_time, TRUE /*abs_time*/); 85 else 86 r = OK; 87 88 if (r != OK) 89 panic("cancel_timer: couldn't set alarm: %d", r); 90 } 91 } 92 93 /* 94 * Expire all timers that were set to expire before/at the given current time. 95 */ 96 void 97 expire_timers(clock_t now) 98 { 99 clock_t next_time; 100 int r, have_timers; 101 102 /* 103 * Check for expired timers. Use a global variable to indicate that 104 * watchdog functions are called, so that sys_setalarm() isn't called 105 * more often than necessary when set_timer or cancel_timer are called 106 * from these watchdog functions. 107 */ 108 expiring = TRUE; 109 have_timers = tmrs_exptimers(&timers, now, &next_time); 110 expiring = FALSE; 111 112 /* Reschedule an alarm if necessary. */ 113 if (have_timers) { 114 if ((r = sys_setalarm(next_time, TRUE /*abs_time*/)) != OK) 115 panic("expire_timers: couldn't set alarm: %d", r); 116 } 117 } 118