Project

General

Profile

Statistics
| Revision:

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 */