mirror of
https://github.com/opnsense/src.git
synced 2026-04-15 14:29:58 -04:00
231 lines
4.3 KiB
C
231 lines
4.3 KiB
C
/*
|
|
* 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.24 2001/09/11 04:05:17 gshapiro Exp $")
|
|
|
|
#if _FFR_TIMERS
|
|
# include <sys/types.h>
|
|
# include <sys/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 */
|