106f25ae9SGregory Neil Shapiro /* 2*5dd76dd0SGregory Neil Shapiro * Copyright (c) 1999-2001 Proofpoint, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 406f25ae9SGregory Neil Shapiro * 506f25ae9SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 606f25ae9SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 706f25ae9SGregory Neil Shapiro * the sendmail distribution. 806f25ae9SGregory Neil Shapiro * 906f25ae9SGregory Neil Shapiro * Contributed by Exactis.com, Inc. 1006f25ae9SGregory Neil Shapiro * 1106f25ae9SGregory Neil Shapiro */ 1206f25ae9SGregory Neil Shapiro 1340266059SGregory Neil Shapiro #include <sm/gen.h> 14*5dd76dd0SGregory Neil Shapiro SM_RCSID("@(#)$Id: timers.c,v 8.27 2013/11/22 20:51:57 ca Exp $") 1506f25ae9SGregory Neil Shapiro 1606f25ae9SGregory Neil Shapiro #if _FFR_TIMERS 1706f25ae9SGregory Neil Shapiro # include <sys/types.h> 184e4196cbSGregory Neil Shapiro # include <sm/time.h> 1906f25ae9SGregory Neil Shapiro # include "sendmail.h" 2006f25ae9SGregory Neil Shapiro # include <sys/resource.h> /* Must be after sendmail.h for NCR MP-RAS */ 2106f25ae9SGregory Neil Shapiro 2206f25ae9SGregory Neil Shapiro static TIMER BaseTimer; /* current baseline */ 2306f25ae9SGregory Neil Shapiro static int NTimers; /* current pointer into stack */ 2406f25ae9SGregory Neil Shapiro static TIMER *TimerStack[MAXTIMERSTACK]; 2506f25ae9SGregory Neil Shapiro 2606f25ae9SGregory Neil Shapiro static void 2706f25ae9SGregory Neil Shapiro # ifdef __STDC__ 2806f25ae9SGregory Neil Shapiro warntimer(const char *msg, ...) 2906f25ae9SGregory Neil Shapiro # else /* __STDC__ */ 3006f25ae9SGregory Neil Shapiro warntimer(msg, va_alist) 3106f25ae9SGregory Neil Shapiro const char *msg; 3206f25ae9SGregory Neil Shapiro va_dcl 3306f25ae9SGregory Neil Shapiro # endif /* __STDC__ */ 3406f25ae9SGregory Neil Shapiro { 3506f25ae9SGregory Neil Shapiro char buf[MAXLINE]; 3640266059SGregory Neil Shapiro SM_VA_LOCAL_DECL 3706f25ae9SGregory Neil Shapiro 3806f25ae9SGregory Neil Shapiro # if 0 3906f25ae9SGregory Neil Shapiro if (!tTd(98, 30)) 4006f25ae9SGregory Neil Shapiro return; 4106f25ae9SGregory Neil Shapiro # endif /* 0 */ 4240266059SGregory Neil Shapiro SM_VA_START(ap, msg); 43d0cef73dSGregory Neil Shapiro (void) sm_vsnprintf(buf, sizeof(buf), msg, ap); 4440266059SGregory Neil Shapiro SM_VA_END(ap); 4506f25ae9SGregory Neil Shapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx", 4640266059SGregory Neil Shapiro buf, (unsigned long) &CurEnv->e_timers); 4706f25ae9SGregory Neil Shapiro } 4806f25ae9SGregory Neil Shapiro 4906f25ae9SGregory Neil Shapiro static void 5006f25ae9SGregory Neil Shapiro zerotimer(ptimer) 5106f25ae9SGregory Neil Shapiro TIMER *ptimer; 5206f25ae9SGregory Neil Shapiro { 53d0cef73dSGregory Neil Shapiro memset(ptimer, '\0', sizeof(*ptimer)); 5406f25ae9SGregory Neil Shapiro } 5506f25ae9SGregory Neil Shapiro 5606f25ae9SGregory Neil Shapiro static void 5706f25ae9SGregory Neil Shapiro addtimer(ta, tb) 5806f25ae9SGregory Neil Shapiro TIMER *ta; 5906f25ae9SGregory Neil Shapiro TIMER *tb; 6006f25ae9SGregory Neil Shapiro { 6106f25ae9SGregory Neil Shapiro tb->ti_wall_sec += ta->ti_wall_sec; 6206f25ae9SGregory Neil Shapiro tb->ti_wall_usec += ta->ti_wall_usec; 6306f25ae9SGregory Neil Shapiro if (tb->ti_wall_usec > 1000000) 6406f25ae9SGregory Neil Shapiro { 6506f25ae9SGregory Neil Shapiro tb->ti_wall_sec++; 6606f25ae9SGregory Neil Shapiro tb->ti_wall_usec -= 1000000; 6706f25ae9SGregory Neil Shapiro } 6806f25ae9SGregory Neil Shapiro tb->ti_cpu_sec += ta->ti_cpu_sec; 6906f25ae9SGregory Neil Shapiro tb->ti_cpu_usec += ta->ti_cpu_usec; 7006f25ae9SGregory Neil Shapiro if (tb->ti_cpu_usec > 1000000) 7106f25ae9SGregory Neil Shapiro { 7206f25ae9SGregory Neil Shapiro tb->ti_cpu_sec++; 7306f25ae9SGregory Neil Shapiro tb->ti_cpu_usec -= 1000000; 7406f25ae9SGregory Neil Shapiro } 7506f25ae9SGregory Neil Shapiro } 7606f25ae9SGregory Neil Shapiro 7706f25ae9SGregory Neil Shapiro static void 7806f25ae9SGregory Neil Shapiro subtimer(ta, tb) 7906f25ae9SGregory Neil Shapiro TIMER *ta; 8006f25ae9SGregory Neil Shapiro TIMER *tb; 8106f25ae9SGregory Neil Shapiro { 8206f25ae9SGregory Neil Shapiro tb->ti_wall_sec -= ta->ti_wall_sec; 8306f25ae9SGregory Neil Shapiro tb->ti_wall_usec -= ta->ti_wall_usec; 8406f25ae9SGregory Neil Shapiro if (tb->ti_wall_usec < 0) 8506f25ae9SGregory Neil Shapiro { 8606f25ae9SGregory Neil Shapiro tb->ti_wall_sec--; 8706f25ae9SGregory Neil Shapiro tb->ti_wall_usec += 1000000; 8806f25ae9SGregory Neil Shapiro } 8906f25ae9SGregory Neil Shapiro tb->ti_cpu_sec -= ta->ti_cpu_sec; 9006f25ae9SGregory Neil Shapiro tb->ti_cpu_usec -= ta->ti_cpu_usec; 9106f25ae9SGregory Neil Shapiro if (tb->ti_cpu_usec < 0) 9206f25ae9SGregory Neil Shapiro { 9306f25ae9SGregory Neil Shapiro tb->ti_cpu_sec--; 9406f25ae9SGregory Neil Shapiro tb->ti_cpu_usec += 1000000; 9506f25ae9SGregory Neil Shapiro } 9606f25ae9SGregory Neil Shapiro } 9706f25ae9SGregory Neil Shapiro 9806f25ae9SGregory Neil Shapiro static int 9906f25ae9SGregory Neil Shapiro getcurtimer(ptimer) 10006f25ae9SGregory Neil Shapiro TIMER *ptimer; 10106f25ae9SGregory Neil Shapiro { 10206f25ae9SGregory Neil Shapiro struct rusage ru; 10306f25ae9SGregory Neil Shapiro struct timeval now; 10406f25ae9SGregory Neil Shapiro 10506f25ae9SGregory Neil Shapiro if (getrusage(RUSAGE_SELF, &ru) < 0 || gettimeofday(&now, NULL) < 0) 10606f25ae9SGregory Neil Shapiro return -1; 10706f25ae9SGregory Neil Shapiro ptimer->ti_wall_sec = now.tv_sec; 10806f25ae9SGregory Neil Shapiro ptimer->ti_wall_usec = now.tv_usec; 10906f25ae9SGregory Neil Shapiro ptimer->ti_cpu_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; 11006f25ae9SGregory Neil Shapiro ptimer->ti_cpu_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec; 11106f25ae9SGregory Neil Shapiro if (ptimer->ti_cpu_usec > 1000000) 11206f25ae9SGregory Neil Shapiro { 11306f25ae9SGregory Neil Shapiro ptimer->ti_cpu_sec++; 11406f25ae9SGregory Neil Shapiro ptimer->ti_cpu_usec -= 1000000; 11506f25ae9SGregory Neil Shapiro } 11606f25ae9SGregory Neil Shapiro return 0; 11706f25ae9SGregory Neil Shapiro } 11806f25ae9SGregory Neil Shapiro 11906f25ae9SGregory Neil Shapiro static void 12006f25ae9SGregory Neil Shapiro getinctimer(ptimer) 12106f25ae9SGregory Neil Shapiro TIMER *ptimer; 12206f25ae9SGregory Neil Shapiro { 12306f25ae9SGregory Neil Shapiro TIMER cur; 12406f25ae9SGregory Neil Shapiro 12506f25ae9SGregory Neil Shapiro if (getcurtimer(&cur) < 0) 12606f25ae9SGregory Neil Shapiro { 12706f25ae9SGregory Neil Shapiro zerotimer(ptimer); 12806f25ae9SGregory Neil Shapiro return; 12906f25ae9SGregory Neil Shapiro } 13006f25ae9SGregory Neil Shapiro if (BaseTimer.ti_wall_sec == 0) 13106f25ae9SGregory Neil Shapiro { 13206f25ae9SGregory Neil Shapiro /* first call */ 133d0cef73dSGregory Neil Shapiro memset(ptimer, '\0', sizeof(*ptimer)); 13406f25ae9SGregory Neil Shapiro } 13506f25ae9SGregory Neil Shapiro else 13606f25ae9SGregory Neil Shapiro { 13706f25ae9SGregory Neil Shapiro *ptimer = cur; 13806f25ae9SGregory Neil Shapiro subtimer(&BaseTimer, ptimer); 13906f25ae9SGregory Neil Shapiro } 14006f25ae9SGregory Neil Shapiro BaseTimer = cur; 14106f25ae9SGregory Neil Shapiro } 14206f25ae9SGregory Neil Shapiro 14306f25ae9SGregory Neil Shapiro void 14406f25ae9SGregory Neil Shapiro flushtimers() 14506f25ae9SGregory Neil Shapiro { 14606f25ae9SGregory Neil Shapiro NTimers = 0; 14706f25ae9SGregory Neil Shapiro (void) getcurtimer(&BaseTimer); 14806f25ae9SGregory Neil Shapiro } 14906f25ae9SGregory Neil Shapiro 15006f25ae9SGregory Neil Shapiro void 15106f25ae9SGregory Neil Shapiro pushtimer(ptimer) 15206f25ae9SGregory Neil Shapiro TIMER *ptimer; 15306f25ae9SGregory Neil Shapiro { 15406f25ae9SGregory Neil Shapiro int i; 15506f25ae9SGregory Neil Shapiro int save_errno = errno; 15606f25ae9SGregory Neil Shapiro TIMER incr; 15706f25ae9SGregory Neil Shapiro 15806f25ae9SGregory Neil Shapiro /* find how much time has changed since last call */ 15906f25ae9SGregory Neil Shapiro getinctimer(&incr); 16006f25ae9SGregory Neil Shapiro 16106f25ae9SGregory Neil Shapiro /* add that into the old timers */ 16206f25ae9SGregory Neil Shapiro i = NTimers; 16306f25ae9SGregory Neil Shapiro if (i > MAXTIMERSTACK) 16406f25ae9SGregory Neil Shapiro i = MAXTIMERSTACK; 16506f25ae9SGregory Neil Shapiro while (--i >= 0) 16606f25ae9SGregory Neil Shapiro { 16706f25ae9SGregory Neil Shapiro addtimer(&incr, TimerStack[i]); 16806f25ae9SGregory Neil Shapiro if (TimerStack[i] == ptimer) 16906f25ae9SGregory Neil Shapiro { 17006f25ae9SGregory Neil Shapiro warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d", 17140266059SGregory Neil Shapiro (unsigned long) ptimer, i, NTimers); 17206f25ae9SGregory Neil Shapiro errno = save_errno; 17306f25ae9SGregory Neil Shapiro return; 17406f25ae9SGregory Neil Shapiro } 17506f25ae9SGregory Neil Shapiro } 17606f25ae9SGregory Neil Shapiro errno = save_errno; 17706f25ae9SGregory Neil Shapiro 17806f25ae9SGregory Neil Shapiro /* handle stack overflow */ 17906f25ae9SGregory Neil Shapiro if (NTimers >= MAXTIMERSTACK) 18006f25ae9SGregory Neil Shapiro return; 18106f25ae9SGregory Neil Shapiro 18206f25ae9SGregory Neil Shapiro /* now add the timer to the stack */ 18306f25ae9SGregory Neil Shapiro TimerStack[NTimers++] = ptimer; 18406f25ae9SGregory Neil Shapiro } 18506f25ae9SGregory Neil Shapiro 18606f25ae9SGregory Neil Shapiro void 18706f25ae9SGregory Neil Shapiro poptimer(ptimer) 18806f25ae9SGregory Neil Shapiro TIMER *ptimer; 18906f25ae9SGregory Neil Shapiro { 19006f25ae9SGregory Neil Shapiro int i; 19106f25ae9SGregory Neil Shapiro int save_errno = errno; 19206f25ae9SGregory Neil Shapiro TIMER incr; 19306f25ae9SGregory Neil Shapiro 19406f25ae9SGregory Neil Shapiro /* find how much time has changed since last call */ 19506f25ae9SGregory Neil Shapiro getinctimer(&incr); 19606f25ae9SGregory Neil Shapiro 19706f25ae9SGregory Neil Shapiro /* add that into the old timers */ 19806f25ae9SGregory Neil Shapiro i = NTimers; 19906f25ae9SGregory Neil Shapiro if (i > MAXTIMERSTACK) 20006f25ae9SGregory Neil Shapiro i = MAXTIMERSTACK; 20106f25ae9SGregory Neil Shapiro while (--i >= 0) 20206f25ae9SGregory Neil Shapiro addtimer(&incr, TimerStack[i]); 20306f25ae9SGregory Neil Shapiro 20406f25ae9SGregory Neil Shapiro /* pop back to this timer */ 20506f25ae9SGregory Neil Shapiro for (i = 0; i < NTimers; i++) 206193538b7SGregory Neil Shapiro { 20706f25ae9SGregory Neil Shapiro if (TimerStack[i] == ptimer) 20806f25ae9SGregory Neil Shapiro break; 209193538b7SGregory Neil Shapiro } 210193538b7SGregory Neil Shapiro 21106f25ae9SGregory Neil Shapiro if (i != NTimers - 1) 21206f25ae9SGregory Neil Shapiro warntimer("poptimer: odd pop (timer=0x%lx, index=%d, NTimers=%d)", 21340266059SGregory Neil Shapiro (unsigned long) ptimer, i, NTimers); 21406f25ae9SGregory Neil Shapiro NTimers = i; 21506f25ae9SGregory Neil Shapiro 21606f25ae9SGregory Neil Shapiro /* clean up and return */ 21706f25ae9SGregory Neil Shapiro errno = save_errno; 21806f25ae9SGregory Neil Shapiro } 21906f25ae9SGregory Neil Shapiro 22006f25ae9SGregory Neil Shapiro char * 22106f25ae9SGregory Neil Shapiro strtimer(ptimer) 22206f25ae9SGregory Neil Shapiro TIMER *ptimer; 22306f25ae9SGregory Neil Shapiro { 22406f25ae9SGregory Neil Shapiro static char buf[40]; 22506f25ae9SGregory Neil Shapiro 226d0cef73dSGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "%ld.%06ldr/%ld.%06ldc", 22706f25ae9SGregory Neil Shapiro ptimer->ti_wall_sec, ptimer->ti_wall_usec, 22806f25ae9SGregory Neil Shapiro ptimer->ti_cpu_sec, ptimer->ti_cpu_usec); 22906f25ae9SGregory Neil Shapiro return buf; 23006f25ae9SGregory Neil Shapiro } 23106f25ae9SGregory Neil Shapiro #endif /* _FFR_TIMERS */ 232