xref: /freebsd/contrib/sendmail/src/timers.c (revision e2c0e292e8a7ca00ba99bcfccc9e637f45c3e8b1)
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