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