timers.c revision 71345
1/* 2 * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 * Contributed by Exactis.com, Inc. 10 * 11 */ 12 13#ifndef lint 14static char id[] = "@(#)$Id: timers.c,v 8.13.16.1 2000/10/09 01:06:45 gshapiro Exp $"; 15#endif /* ! lint */ 16 17#if _FFR_TIMERS 18# include <sys/types.h> 19# include <sys/time.h> 20# include "sendmail.h" 21# include <sys/resource.h> /* Must be after sendmail.h for NCR MP-RAS */ 22 23static TIMER BaseTimer; /* current baseline */ 24static int NTimers; /* current pointer into stack */ 25static TIMER *TimerStack[MAXTIMERSTACK]; 26 27static void 28# ifdef __STDC__ 29warntimer(const char *msg, ...) 30# else /* __STDC__ */ 31warntimer(msg, va_alist) 32 const char *msg; 33 va_dcl 34# endif /* __STDC__ */ 35{ 36 char buf[MAXLINE]; 37 VA_LOCAL_DECL 38 39# if 0 40 if (!tTd(98, 30)) 41 return; 42# endif /* 0 */ 43 VA_START(msg); 44 vsnprintf(buf, sizeof buf, msg, ap); 45 VA_END; 46 sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx", 47 buf, (u_long) &CurEnv->e_timers); 48} 49 50static void 51zerotimer(ptimer) 52 TIMER *ptimer; 53{ 54 memset(ptimer, '\0', sizeof *ptimer); 55} 56 57static void 58addtimer(ta, tb) 59 TIMER *ta; 60 TIMER *tb; 61{ 62 tb->ti_wall_sec += ta->ti_wall_sec; 63 tb->ti_wall_usec += ta->ti_wall_usec; 64 if (tb->ti_wall_usec > 1000000) 65 { 66 tb->ti_wall_sec++; 67 tb->ti_wall_usec -= 1000000; 68 } 69 tb->ti_cpu_sec += ta->ti_cpu_sec; 70 tb->ti_cpu_usec += ta->ti_cpu_usec; 71 if (tb->ti_cpu_usec > 1000000) 72 { 73 tb->ti_cpu_sec++; 74 tb->ti_cpu_usec -= 1000000; 75 } 76} 77 78static void 79subtimer(ta, tb) 80 TIMER *ta; 81 TIMER *tb; 82{ 83 tb->ti_wall_sec -= ta->ti_wall_sec; 84 tb->ti_wall_usec -= ta->ti_wall_usec; 85 if (tb->ti_wall_usec < 0) 86 { 87 tb->ti_wall_sec--; 88 tb->ti_wall_usec += 1000000; 89 } 90 tb->ti_cpu_sec -= ta->ti_cpu_sec; 91 tb->ti_cpu_usec -= ta->ti_cpu_usec; 92 if (tb->ti_cpu_usec < 0) 93 { 94 tb->ti_cpu_sec--; 95 tb->ti_cpu_usec += 1000000; 96 } 97} 98 99static int 100getcurtimer(ptimer) 101 TIMER *ptimer; 102{ 103 struct rusage ru; 104 struct timeval now; 105 106 if (getrusage(RUSAGE_SELF, &ru) < 0 || gettimeofday(&now, NULL) < 0) 107 return -1; 108 ptimer->ti_wall_sec = now.tv_sec; 109 ptimer->ti_wall_usec = now.tv_usec; 110 ptimer->ti_cpu_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; 111 ptimer->ti_cpu_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec; 112 if (ptimer->ti_cpu_usec > 1000000) 113 { 114 ptimer->ti_cpu_sec++; 115 ptimer->ti_cpu_usec -= 1000000; 116 } 117 return 0; 118} 119 120static void 121getinctimer(ptimer) 122 TIMER *ptimer; 123{ 124 TIMER cur; 125 126 if (getcurtimer(&cur) < 0) 127 { 128 zerotimer(ptimer); 129 return; 130 } 131 if (BaseTimer.ti_wall_sec == 0) 132 { 133 /* first call */ 134 memset(ptimer, '\0', sizeof *ptimer); 135 } 136 else 137 { 138 *ptimer = cur; 139 subtimer(&BaseTimer, ptimer); 140 } 141 BaseTimer = cur; 142} 143 144void 145flushtimers() 146{ 147 NTimers = 0; 148 (void) getcurtimer(&BaseTimer); 149} 150 151void 152pushtimer(ptimer) 153 TIMER *ptimer; 154{ 155 int i; 156 int save_errno = errno; 157 TIMER incr; 158 159 /* find how much time has changed since last call */ 160 getinctimer(&incr); 161 162 /* add that into the old timers */ 163 i = NTimers; 164 if (i > MAXTIMERSTACK) 165 i = MAXTIMERSTACK; 166 while (--i >= 0) 167 { 168 addtimer(&incr, TimerStack[i]); 169 if (TimerStack[i] == ptimer) 170 { 171 warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d", 172 (u_long) ptimer, i, NTimers); 173 errno = save_errno; 174 return; 175 } 176 } 177 errno = save_errno; 178 179 /* handle stack overflow */ 180 if (NTimers >= MAXTIMERSTACK) 181 return; 182 183 /* now add the timer to the stack */ 184 TimerStack[NTimers++] = ptimer; 185} 186 187void 188poptimer(ptimer) 189 TIMER *ptimer; 190{ 191 int i; 192 int save_errno = errno; 193 TIMER incr; 194 195 /* find how much time has changed since last call */ 196 getinctimer(&incr); 197 198 /* add that into the old timers */ 199 i = NTimers; 200 if (i > MAXTIMERSTACK) 201 i = MAXTIMERSTACK; 202 while (--i >= 0) 203 addtimer(&incr, TimerStack[i]); 204 205 /* pop back to this timer */ 206 for (i = 0; i < NTimers; i++) 207 { 208 if (TimerStack[i] == ptimer) 209 break; 210 } 211 212 if (i != NTimers - 1) 213 warntimer("poptimer: odd pop (timer=0x%lx, index=%d, NTimers=%d)", 214 (u_long) ptimer, i, NTimers); 215 NTimers = i; 216 217 /* clean up and return */ 218 errno = save_errno; 219} 220 221char * 222strtimer(ptimer) 223 TIMER *ptimer; 224{ 225 static char buf[40]; 226 227 snprintf(buf, sizeof buf, "%ld.%06ldr/%ld.%06ldc", 228 ptimer->ti_wall_sec, ptimer->ti_wall_usec, 229 ptimer->ti_cpu_sec, ptimer->ti_cpu_usec); 230 return buf; 231} 232#endif /* _FFR_TIMERS */ 233