106f25ae9SGregory Neil Shapiro /*
25dd76dd0SGregory 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>
144313cc83SGregory 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__
warntimer(const char * msg,...)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;
41*5b0945b5SGregory Neil Shapiro # endif
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
zerotimer(ptimer)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
addtimer(ta,tb)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
subtimer(ta,tb)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
getcurtimer(ptimer)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
getinctimer(ptimer)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
flushtimers()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
pushtimer(ptimer)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
poptimer(ptimer)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 *
strtimer(ptimer)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