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