diff options
Diffstat (limited to 'sendmail/src/timers.c')
-rw-r--r-- | sendmail/src/timers.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/sendmail/src/timers.c b/sendmail/src/timers.c new file mode 100644 index 0000000..43dc07d --- /dev/null +++ b/sendmail/src/timers.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * Contributed by Exactis.com, Inc. + * + */ + +#include <sm/gen.h> +SM_RCSID("@(#)$Id: timers.c,v 8.26 2006/08/15 23:24:58 ca Exp $") + +#if _FFR_TIMERS +# include <sys/types.h> +# include <sm/time.h> +# include "sendmail.h" +# include <sys/resource.h> /* Must be after sendmail.h for NCR MP-RAS */ + +static TIMER BaseTimer; /* current baseline */ +static int NTimers; /* current pointer into stack */ +static TIMER *TimerStack[MAXTIMERSTACK]; + +static void +# ifdef __STDC__ +warntimer(const char *msg, ...) +# else /* __STDC__ */ +warntimer(msg, va_alist) + const char *msg; + va_dcl +# endif /* __STDC__ */ +{ + char buf[MAXLINE]; + SM_VA_LOCAL_DECL + +# if 0 + if (!tTd(98, 30)) + return; +# endif /* 0 */ + SM_VA_START(ap, msg); + (void) sm_vsnprintf(buf, sizeof(buf), msg, ap); + SM_VA_END(ap); + sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx", + buf, (unsigned long) &CurEnv->e_timers); +} + +static void +zerotimer(ptimer) + TIMER *ptimer; +{ + memset(ptimer, '\0', sizeof(*ptimer)); +} + +static void +addtimer(ta, tb) + TIMER *ta; + TIMER *tb; +{ + tb->ti_wall_sec += ta->ti_wall_sec; + tb->ti_wall_usec += ta->ti_wall_usec; + if (tb->ti_wall_usec > 1000000) + { + tb->ti_wall_sec++; + tb->ti_wall_usec -= 1000000; + } + tb->ti_cpu_sec += ta->ti_cpu_sec; + tb->ti_cpu_usec += ta->ti_cpu_usec; + if (tb->ti_cpu_usec > 1000000) + { + tb->ti_cpu_sec++; + tb->ti_cpu_usec -= 1000000; + } +} + +static void +subtimer(ta, tb) + TIMER *ta; + TIMER *tb; +{ + tb->ti_wall_sec -= ta->ti_wall_sec; + tb->ti_wall_usec -= ta->ti_wall_usec; + if (tb->ti_wall_usec < 0) + { + tb->ti_wall_sec--; + tb->ti_wall_usec += 1000000; + } + tb->ti_cpu_sec -= ta->ti_cpu_sec; + tb->ti_cpu_usec -= ta->ti_cpu_usec; + if (tb->ti_cpu_usec < 0) + { + tb->ti_cpu_sec--; + tb->ti_cpu_usec += 1000000; + } +} + +static int +getcurtimer(ptimer) + TIMER *ptimer; +{ + struct rusage ru; + struct timeval now; + + if (getrusage(RUSAGE_SELF, &ru) < 0 || gettimeofday(&now, NULL) < 0) + return -1; + ptimer->ti_wall_sec = now.tv_sec; + ptimer->ti_wall_usec = now.tv_usec; + ptimer->ti_cpu_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; + ptimer->ti_cpu_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec; + if (ptimer->ti_cpu_usec > 1000000) + { + ptimer->ti_cpu_sec++; + ptimer->ti_cpu_usec -= 1000000; + } + return 0; +} + +static void +getinctimer(ptimer) + TIMER *ptimer; +{ + TIMER cur; + + if (getcurtimer(&cur) < 0) + { + zerotimer(ptimer); + return; + } + if (BaseTimer.ti_wall_sec == 0) + { + /* first call */ + memset(ptimer, '\0', sizeof(*ptimer)); + } + else + { + *ptimer = cur; + subtimer(&BaseTimer, ptimer); + } + BaseTimer = cur; +} + +void +flushtimers() +{ + NTimers = 0; + (void) getcurtimer(&BaseTimer); +} + +void +pushtimer(ptimer) + TIMER *ptimer; +{ + int i; + int save_errno = errno; + TIMER incr; + + /* find how much time has changed since last call */ + getinctimer(&incr); + + /* add that into the old timers */ + i = NTimers; + if (i > MAXTIMERSTACK) + i = MAXTIMERSTACK; + while (--i >= 0) + { + addtimer(&incr, TimerStack[i]); + if (TimerStack[i] == ptimer) + { + warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d", + (unsigned long) ptimer, i, NTimers); + errno = save_errno; + return; + } + } + errno = save_errno; + + /* handle stack overflow */ + if (NTimers >= MAXTIMERSTACK) + return; + + /* now add the timer to the stack */ + TimerStack[NTimers++] = ptimer; +} + +void +poptimer(ptimer) + TIMER *ptimer; +{ + int i; + int save_errno = errno; + TIMER incr; + + /* find how much time has changed since last call */ + getinctimer(&incr); + + /* add that into the old timers */ + i = NTimers; + if (i > MAXTIMERSTACK) + i = MAXTIMERSTACK; + while (--i >= 0) + addtimer(&incr, TimerStack[i]); + + /* pop back to this timer */ + for (i = 0; i < NTimers; i++) + { + if (TimerStack[i] == ptimer) + break; + } + + if (i != NTimers - 1) + warntimer("poptimer: odd pop (timer=0x%lx, index=%d, NTimers=%d)", + (unsigned long) ptimer, i, NTimers); + NTimers = i; + + /* clean up and return */ + errno = save_errno; +} + +char * +strtimer(ptimer) + TIMER *ptimer; +{ + static char buf[40]; + + (void) sm_snprintf(buf, sizeof(buf), "%ld.%06ldr/%ld.%06ldc", + ptimer->ti_wall_sec, ptimer->ti_wall_usec, + ptimer->ti_cpu_sec, ptimer->ti_cpu_usec); + return buf; +} +#endif /* _FFR_TIMERS */ |