source: trunk/third/sendmail/sendmail/timers.c @ 19204

Revision 19204, 4.3 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 *
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.
8 *
9 * Contributed by Exactis.com, Inc.
10 *
11 */
12
13#include <sm/gen.h>
14SM_RCSID("@(#)$Id: timers.c,v 1.1.1.1 2003-04-08 15:06:13 zacheiss Exp $")
15
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 */
21
22static TIMER    BaseTimer;              /* current baseline */
23static int      NTimers;                /* current pointer into stack */
24static TIMER    *TimerStack[MAXTIMERSTACK];
25
26static void
27# ifdef __STDC__
28warntimer(const char *msg, ...)
29# else /* __STDC__ */
30warntimer(msg, va_alist)
31        const char *msg;
32        va_dcl
33# endif /* __STDC__ */
34{
35        char buf[MAXLINE];
36        SM_VA_LOCAL_DECL
37
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);
47}
48
49static void
50zerotimer(ptimer)
51        TIMER *ptimer;
52{
53        memset(ptimer, '\0', sizeof *ptimer);
54}
55
56static void
57addtimer(ta, tb)
58        TIMER *ta;
59        TIMER *tb;
60{
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)
64        {
65                tb->ti_wall_sec++;
66                tb->ti_wall_usec -= 1000000;
67        }
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)
71        {
72                tb->ti_cpu_sec++;
73                tb->ti_cpu_usec -= 1000000;
74        }
75}
76
77static void
78subtimer(ta, tb)
79        TIMER *ta;
80        TIMER *tb;
81{
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)
85        {
86                tb->ti_wall_sec--;
87                tb->ti_wall_usec += 1000000;
88        }
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)
92        {
93                tb->ti_cpu_sec--;
94                tb->ti_cpu_usec += 1000000;
95        }
96}
97
98static int
99getcurtimer(ptimer)
100        TIMER *ptimer;
101{
102        struct rusage ru;
103        struct timeval now;
104
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)
112        {
113                ptimer->ti_cpu_sec++;
114                ptimer->ti_cpu_usec -= 1000000;
115        }
116        return 0;
117}
118
119static void
120getinctimer(ptimer)
121        TIMER *ptimer;
122{
123        TIMER cur;
124
125        if (getcurtimer(&cur) < 0)
126        {
127                zerotimer(ptimer);
128                return;
129        }
130        if (BaseTimer.ti_wall_sec == 0)
131        {
132                /* first call */
133                memset(ptimer, '\0', sizeof *ptimer);
134        }
135        else
136        {
137                *ptimer = cur;
138                subtimer(&BaseTimer, ptimer);
139        }
140        BaseTimer = cur;
141}
142
143void
144flushtimers()
145{
146        NTimers = 0;
147        (void) getcurtimer(&BaseTimer);
148}
149
150void
151pushtimer(ptimer)
152        TIMER *ptimer;
153{
154        int i;
155        int save_errno = errno;
156        TIMER incr;
157
158        /* find how much time has changed since last call */
159        getinctimer(&incr);
160
161        /* add that into the old timers */
162        i = NTimers;
163        if (i > MAXTIMERSTACK)
164                i = MAXTIMERSTACK;
165        while (--i >= 0)
166        {
167                addtimer(&incr, TimerStack[i]);
168                if (TimerStack[i] == ptimer)
169                {
170                        warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d",
171                                  (unsigned long) ptimer, i, NTimers);
172                        errno = save_errno;
173                        return;
174                }
175        }
176        errno = save_errno;
177
178        /* handle stack overflow */
179        if (NTimers >= MAXTIMERSTACK)
180                return;
181
182        /* now add the timer to the stack */
183        TimerStack[NTimers++] = ptimer;
184}
185
186void
187poptimer(ptimer)
188        TIMER *ptimer;
189{
190        int i;
191        int save_errno = errno;
192        TIMER incr;
193
194        /* find how much time has changed since last call */
195        getinctimer(&incr);
196
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]);
203
204        /* pop back to this timer */
205        for (i = 0; i < NTimers; i++)
206        {
207                if (TimerStack[i] == ptimer)
208                        break;
209        }
210
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;
215
216        /* clean up and return */
217        errno = save_errno;
218}
219
220char *
221strtimer(ptimer)
222        TIMER *ptimer;
223{
224        static char buf[40];
225
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;
230}
231#endif /* _FFR_TIMERS */
Note: See TracBrowser for help on using the repository browser.