1 /** \ingroup rpmio
2 * \file rpmio/rpmsw.c
3 */
4
5 #include "system.h"
6 #include <rpm/rpmsw.h>
7 #include "debug.h"
8
9 static rpmtime_t rpmsw_overhead = 0;
10
11 static rpmtime_t rpmsw_cycles = 1;
12
13 static int rpmsw_initialized = 0;
14
rpmswNow(rpmsw sw)15 rpmsw rpmswNow(rpmsw sw)
16 {
17 if (!rpmsw_initialized)
18 (void) rpmswInit();
19 if (sw == NULL)
20 return NULL;
21 if (gettimeofday(&sw->u.tv, NULL))
22 return NULL;
23 return sw;
24 }
25
26 /** \ingroup rpmio
27 * Return difference of 2 timeval stamps in micro-seconds.
28 * @param *etv end timeval
29 * @param *btv begin timeval
30 * @return difference in milli-seconds
31 */
32 static inline
tvsub(const struct timeval * etv,const struct timeval * btv)33 rpmtime_t tvsub(const struct timeval * etv,
34 const struct timeval * btv)
35 {
36 time_t secs, usecs;
37 if (etv == NULL || btv == NULL) return 0;
38 secs = etv->tv_sec - btv->tv_sec;
39 for (usecs = etv->tv_usec - btv->tv_usec; usecs < 0; usecs += 1000000)
40 secs--;
41 return ((secs * 1000000) + usecs);
42 }
43
rpmswDiff(rpmsw end,rpmsw begin)44 rpmtime_t rpmswDiff(rpmsw end, rpmsw begin)
45 {
46 unsigned long long ticks = 0;
47
48 if (end == NULL || begin == NULL)
49 return 0;
50 ticks = tvsub(&end->u.tv, &begin->u.tv);
51 if (ticks >= rpmsw_overhead)
52 ticks -= rpmsw_overhead;
53 if (rpmsw_cycles > 1)
54 ticks /= rpmsw_cycles;
55 return ticks;
56 }
57
rpmswInit(void)58 rpmtime_t rpmswInit(void)
59 {
60 struct rpmsw_s begin, end;
61 rpmtime_t sum_overhead = 0;
62 int i;
63
64 rpmsw_initialized = 1;
65
66 rpmsw_overhead = 0;
67 rpmsw_cycles = 0;
68
69 /* Convergence for simultaneous cycles and overhead is overkill ... */
70 for (i = 0; i < 3; i++) {
71 /* Calculate timing overhead in usecs. */
72 (void) rpmswNow(&begin);
73 sum_overhead += rpmswDiff(rpmswNow(&end), &begin);
74
75 rpmsw_overhead = sum_overhead/(i+1);
76 }
77
78 return rpmsw_overhead;
79 }
80
rpmswEnter(rpmop op,ssize_t rc)81 int rpmswEnter(rpmop op, ssize_t rc)
82 {
83 if (op == NULL)
84 return 0;
85
86 op->count++;
87 if (rc < 0) {
88 op->bytes = 0;
89 op->usecs = 0;
90 }
91 (void) rpmswNow(&op->begin);
92 return 0;
93 }
94
rpmswExit(rpmop op,ssize_t rc)95 rpmtime_t rpmswExit(rpmop op, ssize_t rc)
96 {
97 struct rpmsw_s end;
98
99 if (op == NULL)
100 return 0;
101
102 op->usecs += rpmswDiff(rpmswNow(&end), &op->begin);
103 if (rc > 0)
104 op->bytes += rc;
105 op->begin = end; /* structure assignment */
106 return op->usecs;
107 }
108
rpmswAdd(rpmop to,rpmop from)109 rpmtime_t rpmswAdd(rpmop to, rpmop from)
110 {
111 rpmtime_t usecs = 0;
112 if (to != NULL && from != NULL) {
113 to->count += from->count;
114 to->bytes += from->bytes;
115 to->usecs += from->usecs;
116 usecs = to->usecs;
117 }
118 return usecs;
119 }
120
rpmswSub(rpmop to,rpmop from)121 rpmtime_t rpmswSub(rpmop to, rpmop from)
122 {
123 rpmtime_t usecs = 0;
124 if (to != NULL && from != NULL) {
125 to->count -= from->count;
126 to->bytes -= from->bytes;
127 to->usecs -= from->usecs;
128 usecs = to->usecs;
129 }
130 return usecs;
131 }
132