summaryrefslogtreecommitdiff
path: root/rpmio/rpmsw.c
blob: 2a6d70af4a069b2f18ba6bf6046d1fef927c7c9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/** \ingroup rpmio
 * \file rpmio/rpmsw.c
 */

#include "system.h"
#include <rpm/rpmsw.h>
#include "debug.h"

static rpmtime_t rpmsw_overhead = 0;

static rpmtime_t rpmsw_cycles = 1;

static int rpmsw_initialized = 0;

rpmsw rpmswNow(rpmsw sw)
{
    if (!rpmsw_initialized)
	(void) rpmswInit();
    if (sw == NULL)
	return NULL;
    if (gettimeofday(&sw->u.tv, NULL))
    	return NULL;
    return sw;
}

/** \ingroup rpmio
 * Return difference of 2 timeval stamps in micro-seconds.
 * @param *etv		end timeval
 * @param *btv		begin timeval
 * @return		difference in milli-seconds
 */
static inline
rpmtime_t tvsub(const struct timeval * etv,
		const struct timeval * btv)
{
    time_t secs, usecs;
    if (etv == NULL  || btv == NULL) return 0;
    secs = etv->tv_sec - btv->tv_sec;
    for (usecs = etv->tv_usec - btv->tv_usec; usecs < 0; usecs += 1000000)
	secs--;
    return ((secs * 1000000) + usecs);
}

rpmtime_t rpmswDiff(rpmsw end, rpmsw begin)
{
    unsigned long long ticks = 0;

    if (end == NULL || begin == NULL)
	return 0;
    ticks = tvsub(&end->u.tv, &begin->u.tv);
    if (ticks >= rpmsw_overhead)
	ticks -= rpmsw_overhead;
    if (rpmsw_cycles > 1)
	ticks /= rpmsw_cycles;
    return ticks;
}

rpmtime_t rpmswInit(void)
{
    struct rpmsw_s begin, end;
    rpmtime_t sum_overhead = 0;
    int i;

    rpmsw_initialized = 1;

    rpmsw_overhead = 0;
    rpmsw_cycles = 0;

    /* Convergence for simultaneous cycles and overhead is overkill ... */
    for (i = 0; i < 3; i++) {
	/* Calculate timing overhead in usecs. */
	(void) rpmswNow(&begin);
	sum_overhead += rpmswDiff(rpmswNow(&end), &begin);

	rpmsw_overhead = sum_overhead/(i+1);
    }

    return rpmsw_overhead;
}

int rpmswEnter(rpmop op, ssize_t rc)
{
    if (op == NULL)
	return 0;

    op->count++;
    if (rc < 0) {
	op->bytes = 0;
	op->usecs = 0;
    }
    (void) rpmswNow(&op->begin);
    return 0;
}

rpmtime_t rpmswExit(rpmop op, ssize_t rc)
{
    struct rpmsw_s end;

    if (op == NULL)
	return 0;

    op->usecs += rpmswDiff(rpmswNow(&end), &op->begin);
    if (rc > 0)
	op->bytes += rc;
    op->begin = end;	/* structure assignment */
    return op->usecs;
}

rpmtime_t rpmswAdd(rpmop to, rpmop from)
{
    rpmtime_t usecs = 0;
    if (to != NULL && from != NULL) {
	to->count += from->count;
	to->bytes += from->bytes;
	to->usecs += from->usecs;
	usecs = to->usecs;
    }
    return usecs;
}

rpmtime_t rpmswSub(rpmop to, rpmop from)
{
    rpmtime_t usecs = 0;
    if (to != NULL && from != NULL) {
	to->count -= from->count;
	to->bytes -= from->bytes;
	to->usecs -= from->usecs;
	usecs = to->usecs;
    }
    return usecs;
}