root / lab4 / .minix-src / include / minix / timers.h @ 13
History | View | Annotate | Download (4.87 KB)
1 |
/* 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 */ |