summaryrefslogtreecommitdiff
path: root/rpmio/rpmsw.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpmio/rpmsw.c')
-rw-r--r--rpmio/rpmsw.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/rpmio/rpmsw.c b/rpmio/rpmsw.c
new file mode 100644
index 0000000..2a6d70a
--- /dev/null
+++ b/rpmio/rpmsw.c
@@ -0,0 +1,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;
+}