timers.c revision 266692
1207753Smm/* 2207753Smm * Copyright (c) 1999-2001 Proofpoint, Inc. and its suppliers. 3207753Smm * All rights reserved. 4207753Smm * 5207753Smm * By using this file, you agree to the terms and conditions set 6207753Smm * forth in the LICENSE file which can be found at the top level of 7207753Smm * the sendmail distribution. 8207753Smm * 9207753Smm * Contributed by Exactis.com, Inc. 10207753Smm * 11207753Smm */ 12207753Smm 13207753Smm#include <sm/gen.h> 14207753SmmSM_RCSID("@(#)$Id: timers.c,v 8.27 2013-11-22 20:51:57 ca Exp $") 15207753Smm 16207753Smm#if _FFR_TIMERS 17207753Smm# include <sys/types.h> 18207753Smm# include <sm/time.h> 19312518Sdelphij# include "sendmail.h" 20207753Smm# include <sys/resource.h> /* Must be after sendmail.h for NCR MP-RAS */ 21207753Smm 22207753Smmstatic TIMER BaseTimer; /* current baseline */ 23207753Smmstatic int NTimers; /* current pointer into stack */ 24207753Smmstatic TIMER *TimerStack[MAXTIMERSTACK]; 25207753Smm 26207753Smmstatic void 27207753Smm# ifdef __STDC__ 28207753Smmwarntimer(const char *msg, ...) 29207753Smm# else /* __STDC__ */ 30207753Smmwarntimer(msg, va_alist) 31207753Smm const char *msg; 32207753Smm va_dcl 33207753Smm# endif /* __STDC__ */ 34207753Smm{ 35207753Smm char buf[MAXLINE]; 36207753Smm SM_VA_LOCAL_DECL 37207753Smm 38207753Smm# if 0 39207753Smm if (!tTd(98, 30)) 40207753Smm return; 41207753Smm# endif /* 0 */ 42207753Smm SM_VA_START(ap, msg); 43207753Smm (void) sm_vsnprintf(buf, sizeof(buf), msg, ap); 44207753Smm SM_VA_END(ap); 45207753Smm sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx", 46207753Smm buf, (unsigned long) &CurEnv->e_timers); 47207753Smm} 48207753Smm 49207753Smmstatic void 50207753Smmzerotimer(ptimer) 51207753Smm TIMER *ptimer; 52207753Smm{ 53312518Sdelphij memset(ptimer, '\0', sizeof(*ptimer)); 54207753Smm} 55207753Smm 56207753Smmstatic void 57312518Sdelphijaddtimer(ta, tb) 58207753Smm TIMER *ta; 59207753Smm TIMER *tb; 60207753Smm{ 61312518Sdelphij tb->ti_wall_sec += ta->ti_wall_sec; 62312518Sdelphij tb->ti_wall_usec += ta->ti_wall_usec; 63207753Smm if (tb->ti_wall_usec > 1000000) 64207753Smm { 65207753Smm tb->ti_wall_sec++; 66207753Smm tb->ti_wall_usec -= 1000000; 67207753Smm } 68207753Smm tb->ti_cpu_sec += ta->ti_cpu_sec; 69207753Smm tb->ti_cpu_usec += ta->ti_cpu_usec; 70207753Smm if (tb->ti_cpu_usec > 1000000) 71207753Smm { 72223935Smm tb->ti_cpu_sec++; 73223935Smm tb->ti_cpu_usec -= 1000000; 74223935Smm } 75223935Smm} 76207753Smm 77207753Smmstatic void 78207753Smmsubtimer(ta, tb) 79207753Smm TIMER *ta; 80207753Smm TIMER *tb; 81207753Smm{ 82207753Smm tb->ti_wall_sec -= ta->ti_wall_sec; 83207753Smm tb->ti_wall_usec -= ta->ti_wall_usec; 84207753Smm if (tb->ti_wall_usec < 0) 85207753Smm { 86207753Smm tb->ti_wall_sec--; 87207753Smm tb->ti_wall_usec += 1000000; 88207753Smm } 89207753Smm tb->ti_cpu_sec -= ta->ti_cpu_sec; 90207753Smm tb->ti_cpu_usec -= ta->ti_cpu_usec; 91207753Smm if (tb->ti_cpu_usec < 0) 92207753Smm { 93207753Smm tb->ti_cpu_sec--; 94207753Smm tb->ti_cpu_usec += 1000000; 95207753Smm } 96207753Smm} 97207753Smm 98207753Smmstatic int 99207753Smmgetcurtimer(ptimer) 100207753Smm TIMER *ptimer; 101207753Smm{ 102207753Smm struct rusage ru; 103207753Smm struct timeval now; 104207753Smm 105207753Smm if (getrusage(RUSAGE_SELF, &ru) < 0 || gettimeofday(&now, NULL) < 0) 106207753Smm return -1; 107207753Smm ptimer->ti_wall_sec = now.tv_sec; 108207753Smm ptimer->ti_wall_usec = now.tv_usec; 109207753Smm ptimer->ti_cpu_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; 110207753Smm ptimer->ti_cpu_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec; 111207753Smm if (ptimer->ti_cpu_usec > 1000000) 112207753Smm { 113207753Smm ptimer->ti_cpu_sec++; 114207753Smm ptimer->ti_cpu_usec -= 1000000; 115207753Smm } 116207753Smm return 0; 117207753Smm} 118207753Smm 119207753Smmstatic void 120207753Smmgetinctimer(ptimer) 121207753Smm TIMER *ptimer; 122207753Smm{ 123207753Smm TIMER cur; 124207753Smm 125207753Smm if (getcurtimer(&cur) < 0) 126207753Smm { 127207753Smm zerotimer(ptimer); 128207753Smm return; 129207753Smm } 130207753Smm if (BaseTimer.ti_wall_sec == 0) 131207753Smm { 132207753Smm /* first call */ 133207753Smm memset(ptimer, '\0', sizeof(*ptimer)); 134207753Smm } 135207753Smm else 136207753Smm { 137207753Smm *ptimer = cur; 138207753Smm subtimer(&BaseTimer, ptimer); 139207753Smm } 140207753Smm BaseTimer = cur; 141207753Smm} 142207753Smm 143207753Smmvoid 144207753Smmflushtimers() 145207753Smm{ 146207753Smm NTimers = 0; 147207753Smm (void) getcurtimer(&BaseTimer); 148207753Smm} 149207753Smm 150207753Smmvoid 151207753Smmpushtimer(ptimer) 152207753Smm TIMER *ptimer; 153207753Smm{ 154207753Smm int i; 155207753Smm int save_errno = errno; 156207753Smm TIMER incr; 157207753Smm 158207753Smm /* find how much time has changed since last call */ 159207753Smm getinctimer(&incr); 160207753Smm 161207753Smm /* add that into the old timers */ 162207753Smm i = NTimers; 163207753Smm if (i > MAXTIMERSTACK) 164207753Smm i = MAXTIMERSTACK; 165207753Smm while (--i >= 0) 166207753Smm { 167207753Smm addtimer(&incr, TimerStack[i]); 168207753Smm if (TimerStack[i] == ptimer) 169207753Smm { 170207753Smm warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d", 171207753Smm (unsigned long) ptimer, i, NTimers); 172207753Smm errno = save_errno; 173207753Smm return; 174207753Smm } 175207753Smm } 176207753Smm errno = save_errno; 177207753Smm 178207753Smm /* handle stack overflow */ 179207753Smm if (NTimers >= MAXTIMERSTACK) 180207753Smm return; 181207753Smm 182207753Smm /* now add the timer to the stack */ 183207753Smm TimerStack[NTimers++] = ptimer; 184207753Smm} 185207753Smm 186207753Smmvoid 187207753Smmpoptimer(ptimer) 188207753Smm TIMER *ptimer; 189207753Smm{ 190207753Smm int i; 191207753Smm int save_errno = errno; 192207753Smm TIMER incr; 193207753Smm 194207753Smm /* find how much time has changed since last call */ 195207753Smm getinctimer(&incr); 196207753Smm 197207753Smm /* add that into the old timers */ 198207753Smm i = NTimers; 199207753Smm if (i > MAXTIMERSTACK) 200207753Smm i = MAXTIMERSTACK; 201207753Smm while (--i >= 0) 202207753Smm addtimer(&incr, TimerStack[i]); 203207753Smm 204207753Smm /* pop back to this timer */ 205207753Smm for (i = 0; i < NTimers; i++) 206207753Smm { 207207753Smm if (TimerStack[i] == ptimer) 208207753Smm break; 209207753Smm } 210207753Smm 211207753Smm if (i != NTimers - 1) 212207753Smm warntimer("poptimer: odd pop (timer=0x%lx, index=%d, NTimers=%d)", 213207753Smm (unsigned long) ptimer, i, NTimers); 214312518Sdelphij NTimers = i; 215207753Smm 216312518Sdelphij /* clean up and return */ 217312518Sdelphij errno = save_errno; 218207753Smm} 219207753Smm 220207753Smmchar * 221207753Smmstrtimer(ptimer) 222207753Smm TIMER *ptimer; 223207753Smm{ 224207753Smm static char buf[40]; 225207753Smm 226207753Smm (void) sm_snprintf(buf, sizeof(buf), "%ld.%06ldr/%ld.%06ldc", 227207753Smm ptimer->ti_wall_sec, ptimer->ti_wall_usec, 228292588Sdelphij ptimer->ti_cpu_sec, ptimer->ti_cpu_usec); 229207753Smm return buf; 230207753Smm} 231312518Sdelphij#endif /* _FFR_TIMERS */ 232312518Sdelphij