Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / sendmail / timers.c
blob43dd73a0f33678ac38f4d6fc7e74b1be4afde2d1
1 /*
2 * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
9 * Contributed by Exactis.com, Inc.
13 #include <sm/gen.h>
14 SM_RCSID("@(#)$Id: timers.c,v 8.24 2001/09/11 04:05:17 gshapiro Exp $")
16 #if _FFR_TIMERS
17 # include <sys/types.h>
18 # include <sys/time.h>
19 # include "sendmail.h"
20 # include <sys/resource.h> /* Must be after sendmail.h for NCR MP-RAS */
22 static TIMER BaseTimer; /* current baseline */
23 static int NTimers; /* current pointer into stack */
24 static TIMER *TimerStack[MAXTIMERSTACK];
26 static void
27 # ifdef __STDC__
28 warntimer(const char *msg, ...)
29 # else /* __STDC__ */
30 warntimer(msg, va_alist)
31 const char *msg;
32 va_dcl
33 # endif /* __STDC__ */
35 char buf[MAXLINE];
36 SM_VA_LOCAL_DECL
38 # if 0
39 if (!tTd(98, 30))
40 return;
41 # endif /* 0 */
42 SM_VA_START(ap, msg);
43 (void) sm_vsnprintf(buf, sizeof buf, msg, ap);
44 SM_VA_END(ap);
45 sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx",
46 buf, (unsigned long) &CurEnv->e_timers);
49 static void
50 zerotimer(ptimer)
51 TIMER *ptimer;
53 memset(ptimer, '\0', sizeof *ptimer);
56 static void
57 addtimer(ta, tb)
58 TIMER *ta;
59 TIMER *tb;
61 tb->ti_wall_sec += ta->ti_wall_sec;
62 tb->ti_wall_usec += ta->ti_wall_usec;
63 if (tb->ti_wall_usec > 1000000)
65 tb->ti_wall_sec++;
66 tb->ti_wall_usec -= 1000000;
68 tb->ti_cpu_sec += ta->ti_cpu_sec;
69 tb->ti_cpu_usec += ta->ti_cpu_usec;
70 if (tb->ti_cpu_usec > 1000000)
72 tb->ti_cpu_sec++;
73 tb->ti_cpu_usec -= 1000000;
77 static void
78 subtimer(ta, tb)
79 TIMER *ta;
80 TIMER *tb;
82 tb->ti_wall_sec -= ta->ti_wall_sec;
83 tb->ti_wall_usec -= ta->ti_wall_usec;
84 if (tb->ti_wall_usec < 0)
86 tb->ti_wall_sec--;
87 tb->ti_wall_usec += 1000000;
89 tb->ti_cpu_sec -= ta->ti_cpu_sec;
90 tb->ti_cpu_usec -= ta->ti_cpu_usec;
91 if (tb->ti_cpu_usec < 0)
93 tb->ti_cpu_sec--;
94 tb->ti_cpu_usec += 1000000;
98 static int
99 getcurtimer(ptimer)
100 TIMER *ptimer;
102 struct rusage ru;
103 struct timeval now;
105 if (getrusage(RUSAGE_SELF, &ru) < 0 || gettimeofday(&now, NULL) < 0)
106 return -1;
107 ptimer->ti_wall_sec = now.tv_sec;
108 ptimer->ti_wall_usec = now.tv_usec;
109 ptimer->ti_cpu_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
110 ptimer->ti_cpu_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
111 if (ptimer->ti_cpu_usec > 1000000)
113 ptimer->ti_cpu_sec++;
114 ptimer->ti_cpu_usec -= 1000000;
116 return 0;
119 static void
120 getinctimer(ptimer)
121 TIMER *ptimer;
123 TIMER cur;
125 if (getcurtimer(&cur) < 0)
127 zerotimer(ptimer);
128 return;
130 if (BaseTimer.ti_wall_sec == 0)
132 /* first call */
133 memset(ptimer, '\0', sizeof *ptimer);
135 else
137 *ptimer = cur;
138 subtimer(&BaseTimer, ptimer);
140 BaseTimer = cur;
143 void
144 flushtimers()
146 NTimers = 0;
147 (void) getcurtimer(&BaseTimer);
150 void
151 pushtimer(ptimer)
152 TIMER *ptimer;
154 int i;
155 int save_errno = errno;
156 TIMER incr;
158 /* find how much time has changed since last call */
159 getinctimer(&incr);
161 /* add that into the old timers */
162 i = NTimers;
163 if (i > MAXTIMERSTACK)
164 i = MAXTIMERSTACK;
165 while (--i >= 0)
167 addtimer(&incr, TimerStack[i]);
168 if (TimerStack[i] == ptimer)
170 warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d",
171 (unsigned long) ptimer, i, NTimers);
172 errno = save_errno;
173 return;
176 errno = save_errno;
178 /* handle stack overflow */
179 if (NTimers >= MAXTIMERSTACK)
180 return;
182 /* now add the timer to the stack */
183 TimerStack[NTimers++] = ptimer;
186 void
187 poptimer(ptimer)
188 TIMER *ptimer;
190 int i;
191 int save_errno = errno;
192 TIMER incr;
194 /* find how much time has changed since last call */
195 getinctimer(&incr);
197 /* add that into the old timers */
198 i = NTimers;
199 if (i > MAXTIMERSTACK)
200 i = MAXTIMERSTACK;
201 while (--i >= 0)
202 addtimer(&incr, TimerStack[i]);
204 /* pop back to this timer */
205 for (i = 0; i < NTimers; i++)
207 if (TimerStack[i] == ptimer)
208 break;
211 if (i != NTimers - 1)
212 warntimer("poptimer: odd pop (timer=0x%lx, index=%d, NTimers=%d)",
213 (unsigned long) ptimer, i, NTimers);
214 NTimers = i;
216 /* clean up and return */
217 errno = save_errno;
220 char *
221 strtimer(ptimer)
222 TIMER *ptimer;
224 static char buf[40];
226 (void) sm_snprintf(buf, sizeof buf, "%ld.%06ldr/%ld.%06ldc",
227 ptimer->ti_wall_sec, ptimer->ti_wall_usec,
228 ptimer->ti_cpu_sec, ptimer->ti_cpu_usec);
229 return buf;
231 #endif /* _FFR_TIMERS */