root / lab4 / .minix-src / include / minix / timers.h @ 13
History | View | Annotate | Download (4.87 KB)
1 | 13 | up20180614 | /* This library provides generic watchdog timer management functionality.
|
---|---|---|---|
2 | * The functions operate on a timer queue provided by the caller. Note that
|
||
3 | * the timers must use absolute time to allow sorting. The library provides:
|
||
4 | *
|
||
5 | * tmrs_settimer: (re)set a new watchdog timer in the timers queue
|
||
6 | * tmrs_clrtimer: remove a timer from both the timers queue
|
||
7 | * tmrs_exptimers: check for expired timers and run watchdog functions
|
||
8 | *
|
||
9 | * Author:
|
||
10 | * Jorrit N. Herder <jnherder@cs.vu.nl>
|
||
11 | * Adapted from tmr_settimer and tmr_clrtimer in src/kernel/clock.c.
|
||
12 | * Last modified: September 30, 2004.
|
||
13 | */
|
||
14 | #ifndef _MINIX_TIMERS_H
|
||
15 | #define _MINIX_TIMERS_H
|
||
16 | |||
17 | #include <limits.h> |
||
18 | |||
19 | #include <sys/types.h> |
||
20 | #include <minix/const.h> |
||
21 | #include <minix/u64.h> |
||
22 | #include <minix/minlib.h> |
||
23 | #include <minix/endpoint.h> |
||
24 | |||
25 | typedef void (*tmr_func_t)(int arg); |
||
26 | |||
27 | /* A minix_timer_t variable must be declare for each distinct timer to be used.
|
||
28 | * The timers watchdog function and expiration time are automatically set
|
||
29 | * by the library function tmrs_settimer, but its argument is not. In general,
|
||
30 | * the timer is in use when it has a callback function.
|
||
31 | */
|
||
32 | typedef struct minix_timer |
||
33 | { |
||
34 | struct minix_timer *tmr_next; /* next in a timer chain */ |
||
35 | clock_t tmr_exp_time; /* expiration time (absolute) */
|
||
36 | tmr_func_t tmr_func; /* function to call when expired */
|
||
37 | int tmr_arg; /* integer argument */ |
||
38 | } minix_timer_t; |
||
39 | |||
40 | /*
|
||
41 | * Clock times may wrap. Thus, we must only ever compare relative times, which
|
||
42 | * means they must be no more than half the total maximum time value apart.
|
||
43 | * The clock_t type is unsigned (int or long), thus we take half that.
|
||
44 | */
|
||
45 | #define TMRDIFF_MAX (INT_MAX)
|
||
46 | |||
47 | /* This value must be used only instead of a timer difference value. */
|
||
48 | #define TMR_NEVER ((clock_t)TMRDIFF_MAX + 1) |
||
49 | |||
50 | /* These definitions can be used to set or get data from a timer variable. */
|
||
51 | #define tmr_exp_time(tp) ((tp)->tmr_exp_time)
|
||
52 | #define tmr_is_set(tp) ((tp)->tmr_func != NULL) |
||
53 | /*
|
||
54 | * tmr_is_first() returns TRUE iff the first given absolute time is sooner than
|
||
55 | * or equal to the second given time.
|
||
56 | */
|
||
57 | #define tmr_is_first(a,b) ((clock_t)(b) - (clock_t)(a) <= TMRDIFF_MAX)
|
||
58 | #define tmr_has_expired(tp,now) tmr_is_first((tp)->tmr_exp_time, (now))
|
||
59 | |||
60 | /* Timers should be initialized once before they are being used. Be careful
|
||
61 | * not to reinitialize a timer that is in a list of timers, or the chain
|
||
62 | * will be broken.
|
||
63 | */
|
||
64 | #define tmr_inittimer(tp) (void)((tp)->tmr_func = NULL, (tp)->tmr_next = NULL) |
||
65 | |||
66 | /* The following generic timer management functions are available. They
|
||
67 | * can be used to operate on the lists of timers. Adding a timer to a list
|
||
68 | * automatically takes care of removing it.
|
||
69 | */
|
||
70 | int tmrs_settimer(minix_timer_t **tmrs, minix_timer_t *tp, clock_t exp_time,
|
||
71 | tmr_func_t watchdog, int arg, clock_t *old_head, clock_t *new_head);
|
||
72 | int tmrs_clrtimer(minix_timer_t **tmrs, minix_timer_t *tp, clock_t *old_head,
|
||
73 | clock_t *new_head); |
||
74 | int tmrs_exptimers(minix_timer_t **tmrs, clock_t now, clock_t *new_head);
|
||
75 | |||
76 | #define PRINT_STATS(cum_spenttime, cum_instances) { \
|
||
77 | if(ex64hi(cum_spenttime)) { util_stacktrace(); printf(" ( ??? %lu %lu)\n", \ |
||
78 | ex64hi(cum_spenttime), ex64lo(cum_spenttime)); } \ |
||
79 | printf("%s:%d,%lu,%lu\n", \
|
||
80 | __FILE__, __LINE__, cum_instances, \ |
||
81 | ex64lo(cum_spenttime)); \ |
||
82 | } |
||
83 | |||
84 | #define RESET_STATS(starttime, cum_instances, cum_spenttime, cum_starttime) { \
|
||
85 | cum_instances = 0; \
|
||
86 | cum_starttime = starttime; \ |
||
87 | cum_spenttime = make64(0,0); \ |
||
88 | } |
||
89 | |||
90 | #define TIME_BLOCK_VAR(timed_code_block, time_interval) do { \ |
||
91 | static u64_t _cum_spenttime, _cum_starttime; \
|
||
92 | static int _cum_instances; \ |
||
93 | u64_t _next_cum_spent, _starttime, _endtime, _dt, _cum_dt; \ |
||
94 | u32_t _dt_micros; \ |
||
95 | read_tsc_64(&_starttime); \ |
||
96 | do { timed_code_block } while(0); \ |
||
97 | read_tsc_64(&_endtime); \ |
||
98 | _dt = _endtime - _starttime; \ |
||
99 | if(_cum_instances == 0) { \ |
||
100 | RESET_STATS(_starttime, _cum_instances, _cum_spenttime, _cum_starttime); \ |
||
101 | } \ |
||
102 | _next_cum_spent = add64(_cum_spenttime, _dt); \ |
||
103 | if(ex64hi(_next_cum_spent)) { \
|
||
104 | PRINT_STATS(_cum_spenttime, _cum_instances); \ |
||
105 | RESET_STATS(_starttime, _cum_instances, _cum_spenttime, _cum_starttime); \ |
||
106 | } \ |
||
107 | _cum_spenttime = add64(_cum_spenttime, _dt); \ |
||
108 | _cum_instances++; \ |
||
109 | _cum_dt = _endtime - _cum_starttime; \ |
||
110 | if(_cum_dt > make64(0, 120)) { \ |
||
111 | PRINT_STATS(_cum_spenttime, _cum_instances); \ |
||
112 | RESET_STATS(_starttime, _cum_instances, _cum_spenttime, _cum_starttime); \ |
||
113 | } \ |
||
114 | } while(0) |
||
115 | |||
116 | #define TIME_BLOCK(timed_code_block) TIME_BLOCK_VAR(timed_code_block, 100) |
||
117 | #define TIME_BLOCK_T(timed_code_block, t) TIME_BLOCK_VAR(timed_code_block, t)
|
||
118 | |||
119 | /* Timers abstraction for system processes. This would be in minix/sysutil.h
|
||
120 | * if it weren't for naming conflicts.
|
||
121 | */
|
||
122 | |||
123 | void init_timer(minix_timer_t *tp);
|
||
124 | void set_timer(minix_timer_t *tp, clock_t ticks, tmr_func_t watchdog, int arg); |
||
125 | void cancel_timer(minix_timer_t *tp);
|
||
126 | void expire_timers(clock_t now);
|
||
127 | |||
128 | #endif /* _MINIX_TIMERS_H */ |