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/u64.h> 21 #include <minix/minlib.h> 22 #include <minix/endpoint.h> 23 24 struct minix_timer; 25 typedef void (*tmr_func_t)(struct minix_timer *tp); 26 typedef union { int ta_int; long ta_long; void *ta_ptr; } tmr_arg_t; 27 28 /* A minix_timer_t variable must be declare for each distinct timer to be used. 29 * The timers watchdog function and expiration time are automatically set 30 * by the library function tmrs_settimer, but its argument is not. 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 */ 36 tmr_func_t tmr_func; /* function to call when expired */ 37 tmr_arg_t tmr_arg; /* random argument */ 38 } minix_timer_t; 39 40 /* Used when the timer is not active. */ 41 #define TMR_NEVER ((clock_t) -1 < 0) ? ((clock_t) LONG_MAX) : ((clock_t) -1) 42 #undef TMR_NEVER 43 #define TMR_NEVER ((clock_t) LONG_MAX) 44 45 /* These definitions can be used to set or get data from a timer variable. */ 46 #define tmr_arg(tp) (&(tp)->tmr_arg) 47 #define tmr_exp_time(tp) (&(tp)->tmr_exp_time) 48 49 /* Timers should be initialized once before they are being used. Be careful 50 * not to reinitialize a timer that is in a list of timers, or the chain 51 * will be broken. 52 */ 53 #define tmr_inittimer(tp) (void)((tp)->tmr_exp_time = TMR_NEVER, \ 54 (tp)->tmr_next = NULL) 55 56 /* The following generic timer management functions are available. They 57 * can be used to operate on the lists of timers. Adding a timer to a list 58 * automatically takes care of removing it. 59 */ 60 clock_t tmrs_clrtimer(minix_timer_t **tmrs, minix_timer_t *tp, clock_t *new_head); 61 void tmrs_exptimers(minix_timer_t **tmrs, clock_t now, clock_t *new_head); 62 clock_t tmrs_settimer(minix_timer_t **tmrs, minix_timer_t *tp, clock_t exp_time, 63 tmr_func_t watchdog, clock_t *new_head); 64 65 #define PRINT_STATS(cum_spenttime, cum_instances) { \ 66 if(ex64hi(cum_spenttime)) { util_stacktrace(); printf(" ( ??? %lu %lu)\n", \ 67 ex64hi(cum_spenttime), ex64lo(cum_spenttime)); } \ 68 printf("%s:%d,%lu,%lu\n", \ 69 __FILE__, __LINE__, cum_instances, \ 70 ex64lo(cum_spenttime)); \ 71 } 72 73 #define RESET_STATS(starttime, cum_instances, cum_spenttime, cum_starttime) { \ 74 cum_instances = 0; \ 75 cum_starttime = starttime; \ 76 cum_spenttime = make64(0,0); \ 77 } 78 79 #define TIME_BLOCK_VAR(timed_code_block, time_interval) do { \ 80 static u64_t _cum_spenttime, _cum_starttime; \ 81 static int _cum_instances; \ 82 u64_t _next_cum_spent, _starttime, _endtime, _dt, _cum_dt; \ 83 u32_t _dt_micros; \ 84 read_tsc_64(&_starttime); \ 85 do { timed_code_block } while(0); \ 86 read_tsc_64(&_endtime); \ 87 _dt = _endtime - _starttime; \ 88 if(_cum_instances == 0) { \ 89 RESET_STATS(_starttime, _cum_instances, _cum_spenttime, _cum_starttime); \ 90 } \ 91 _next_cum_spent = add64(_cum_spenttime, _dt); \ 92 if(ex64hi(_next_cum_spent)) { \ 93 PRINT_STATS(_cum_spenttime, _cum_instances); \ 94 RESET_STATS(_starttime, _cum_instances, _cum_spenttime, _cum_starttime); \ 95 } \ 96 _cum_spenttime = add64(_cum_spenttime, _dt); \ 97 _cum_instances++; \ 98 _cum_dt = _endtime - _cum_starttime; \ 99 if(_cum_dt > make64(0, 120)) { \ 100 PRINT_STATS(_cum_spenttime, _cum_instances); \ 101 RESET_STATS(_starttime, _cum_instances, _cum_spenttime, _cum_starttime); \ 102 } \ 103 } while(0) 104 105 #define TIME_BLOCK(timed_code_block) TIME_BLOCK_VAR(timed_code_block, 100) 106 #define TIME_BLOCK_T(timed_code_block, t) TIME_BLOCK_VAR(timed_code_block, t) 107 108 /* Timers abstraction for system processes. This would be in minix/sysutil.h 109 * if it weren't for naming conflicts. 110 */ 111 112 void init_timer(minix_timer_t *tp); 113 void set_timer(minix_timer_t *tp, int ticks, tmr_func_t watchdog, int arg); 114 void cancel_timer(minix_timer_t *tp); 115 void expire_timers(clock_t now); 116 117 #endif /* _MINIX_TIMERS_H */ 118