summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/psm.c6
-rw-r--r--rpmio/Makefile.am5
-rw-r--r--rpmio/rpmsq.c24
-rw-r--r--rpmio/rpmsq.h9
-rw-r--r--rpmio/rpmsw.c144
-rw-r--r--rpmio/rpmsw.h7
-rw-r--r--rpmio/tsw.c25
7 files changed, 167 insertions, 53 deletions
diff --git a/lib/psm.c b/lib/psm.c
index 706e41f67..78c227bf5 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -467,9 +467,11 @@ static pid_t psmWait(rpmpsm psm)
{
(void) rpmsqWait(&psm->sq);
- rpmMessage(RPMMESS_DEBUG, _("%s: waitpid(%d) rc %d status %x\n"),
+ rpmMessage(RPMMESS_DEBUG, _("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
psm->stepName, (unsigned)psm->sq.child,
- (unsigned)psm->sq.reaped, psm->sq.status);
+ (unsigned)psm->sq.reaped, psm->sq.status,
+ (unsigned)psm->sq.msecs/1000,
+ (unsigned)psm->sq.msecs%1000);
return psm->sq.reaped;
}
diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am
index 2400182e0..1202039d2 100644
--- a/rpmio/Makefile.am
+++ b/rpmio/Makefile.am
@@ -6,7 +6,7 @@ LINT = splint
EXTRA_DIST = tdigest.c tdir.c tficl.c tfts.c tglob.c tinv.c tkey.c trpmio.c
-EXTRA_PROGRAMS = tdigest tdir tfts tglob tinv tkey tring trpmio dumpasn1
+EXTRA_PROGRAMS = tdigest tdir tfts tglob tinv tkey tring trpmio tsw dumpasn1
INCLUDES = -I. \
-I$(top_srcdir) \
@@ -92,6 +92,9 @@ tring_LDADD = librpmio.la $(top_builddir)/popt/libpopt.la
trpmio_SOURCES = trpmio.c
trpmio_LDADD = librpmio.la $(top_builddir)/popt/libpopt.la
+tsw_SOURCES = tsw.c
+tsw_LDFLAGS = librpmio.la
+
dumpasn1_SOURCES = dumpasn1.c
tficl.o: tficl.c
diff --git a/rpmio/rpmsq.c b/rpmio/rpmsq.c
index 94dd4d04f..a27c84b33 100644
--- a/rpmio/rpmsq.c
+++ b/rpmio/rpmsq.c
@@ -319,31 +319,41 @@ static int rpmsqWaitUnregister(rpmsq sq)
/*@globals fileSystem, internalState @*/
/*@modifies fileSystem, internalState @*/
{
+ struct rpmsw_s end;
int same_thread = 0;
int ret = 0;
int xx;
- if (same_thread) ret = sighold(SIGCHLD);
+ if (same_thread)
+ ret = sighold(SIGCHLD);
+ else
+ ret = pthread_mutex_lock(&sq->mutex);
+ /* Start the child. */
if (sq->pipes[0] >= 0)
xx = close(sq->pipes[0]);
if (sq->pipes[1] >= 0)
xx = close(sq->pipes[1]);
sq->pipes[0] = sq->pipes[1] = -1;
+ (void) rpmswNow(&sq->begin);
+
/*@-infloops@*/
while (ret == 0 && sq->reaped != sq->child) {
- if (same_thread) {
+ if (same_thread)
ret = sigpause(SIGCHLD);
- } else {
- ret = pthread_mutex_lock(&sq->mutex);
+ else
ret = pthread_cond_wait(&sq->cond, &sq->mutex);
- xx = pthread_mutex_unlock(&sq->mutex);
- }
}
/*@=infloops@*/
- if (same_thread) xx = sigrelse(SIGCHLD);
+ sq->msecs = rpmswDiff(rpmswNow(&end), &sq->begin)/1000;
+ sq->script_msecs += sq->msecs;
+
+ if (same_thread)
+ xx = sigrelse(SIGCHLD);
+ else
+ xx = pthread_mutex_unlock(&sq->mutex);
#ifdef _RPMSQ_DEBUG
/*@-modfilesys@*/
diff --git a/rpmio/rpmsq.h b/rpmio/rpmsq.h
index a1498602a..04fcf5e84 100644
--- a/rpmio/rpmsq.h
+++ b/rpmio/rpmsq.h
@@ -11,6 +11,8 @@
#include <sys/signal.h>
#include <search.h> /* XXX insque(3)/remque(3) protos. */
+#include <rpmsw.h>
+
typedef struct rpmsig_s * rpmsig;
typedef struct rpmsqElem * rpmsq;
@@ -32,10 +34,13 @@ struct rpmsqElem {
pid_t child; /*!< Currently running child. */
volatile pid_t reaped; /*!< Reaped waitpid(3) return. */
volatile int status; /*!< Reaped waitpid(3) status. */
+ struct rpmsw_s begin; /*!< Start time. */
+ rpmtime_t msecs; /*!< Instance duration (msecs). */
+ rpmtime_t script_msecs; /*!< Accumulated script duration (msecs). */
int reaper; /*!< Register SIGCHLD handler? */
- int pipes[2];
+ int pipes[2]; /*!< Parent/child interlock. */
void * id; /*!< Blocking thread id (pthread_t). */
- pthread_mutex_t mutex;
+ pthread_mutex_t mutex; /*!< Signal delivery to thread condvar. */
pthread_cond_t cond;
};
diff --git a/rpmio/rpmsw.c b/rpmio/rpmsw.c
index df944f06f..9824221b4 100644
--- a/rpmio/rpmsw.c
+++ b/rpmio/rpmsw.c
@@ -15,23 +15,63 @@ static rpmtime_t rpmsw_cycles = 1;
/*@unchecked@*/
static int rpmsw_type = 0;
-#if defined(__i386__)
-static inline unsigned long long do_rdtsc ( void )
- /*@*/
-{
- unsigned long long x;
- __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
- return x;
-}
-#endif
+/*@unchecked@*/
+static int rpmsw_initialized = 0;
+
+#if 0 /* XXX defined(__i386__) */
+/* Swiped from glibc-2.3.2 sysdeps/i386/i686/hp-timing.h */
+
+#define HP_TIMING_ZERO(Var) (Var) = (0)
+#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var))
+
+/* It's simple arithmetic for us. */
+#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start))
+
+/* We have to jump through hoops to get this correctly implemented. */
+#define HP_TIMING_ACCUM(Sum, Diff) \
+ do { \
+ char __not_done; \
+ hp_timing_t __oldval = (Sum); \
+ hp_timing_t __diff = (Diff) - GL(dl_hp_timing_overhead); \
+ do \
+ { \
+ hp_timing_t __newval = __oldval + __diff; \
+ int __temp0, __temp1; \
+ __asm__ __volatile__ ("xchgl %4, %%ebx\n\t" \
+ "lock; cmpxchg8b %1\n\t" \
+ "sete %0\n\t" \
+ "movl %4, %%ebx" \
+ : "=q" (__not_done), "=m" (Sum), \
+ "=A" (__oldval), "=c" (__temp0), \
+ "=SD" (__temp1) \
+ : "1" (Sum), "2" (__oldval), \
+ "3" (__newval >> 32), \
+ "4" (__newval & 0xffffffff) \
+ : "memory"); \
+ } \
+ while (__not_done); \
+ } while (0)
+
+/* No threads, no extra work. */
+#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff)
+
+/* Print the time value. */
+#define HP_TIMING_PRINT(Buf, Len, Val) \
+ do { \
+ char __buf[20]; \
+ char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \
+ int __len = (Len); \
+ char *__dest = (Buf); \
+ while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \
+ *__dest++ = *__cp++; \
+ memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \
+ } while (0)
+#endif /* __i386__ */
rpmsw rpmswNow(rpmsw sw)
{
- static int oneshot = 0;
- if (oneshot == 0) {
- oneshot = 1;
+ if (!rpmsw_initialized)
rpmswInit();
- }
if (sw == NULL)
return NULL;
switch (rpmsw_type) {
@@ -39,9 +79,9 @@ rpmsw rpmswNow(rpmsw sw)
if (gettimeofday(&sw->u.tv, NULL))
return NULL;
break;
-#if defined(__i386__)
+#if defined(HP_TIMING_NOW)
case 1:
- sw->u.ticks = do_rdtsc();
+ HP_TIMING_NOW(sw->u.ticks);
break;
#endif
}
@@ -54,7 +94,7 @@ rpmsw rpmswNow(rpmsw sw)
* @param *btv begin timeval
* @return difference in milli-seconds
*/
-/*@unused@*/ static inline
+static inline
rpmtime_t tvsub(/*@null@*/ const struct timeval * etv,
/*@null@*/ const struct timeval * btv)
/*@*/
@@ -78,10 +118,10 @@ rpmtime_t rpmswDiff(rpmsw end, rpmsw begin)
case 0:
diff = tvsub(&end->u.tv, &begin->u.tv);
break;
-#if defined(__i386__)
+#if defined(HP_TIMING_NOW)
case 1:
if (end->u.ticks > begin->u.ticks)
- diff = end->u.ticks - begin->u.ticks;
+ HP_TIMING_DIFF(diff, begin->u.ticks, end->u.ticks);
break;
#endif
}
@@ -92,6 +132,7 @@ rpmtime_t rpmswDiff(rpmsw end, rpmsw begin)
return diff;
}
+#if defined(HP_TIMING_NOW)
static rpmtime_t rpmswCalibrate(void)
/*@*/
{
@@ -114,39 +155,64 @@ static rpmtime_t rpmswCalibrate(void)
}
ticks = rpmswDiff(rpmswNow(&end), &begin);
- if (ticks < 1)
- ticks = 1;
return ticks;
}
+#endif
rpmtime_t rpmswInit(void)
{
struct rpmsw_s begin, end;
+ rpmtime_t cycles, usecs;
+ int i;
+
+ rpmsw_initialized = 1;
- rpmsw_type = 0;
rpmsw_overhead = 0;
- rpmsw_cycles = 1;
+ rpmsw_cycles = 0;
-#if 0
- (void) rpmswNow(&begin);
-#if defined(__i386)
- rpmsw_type = 1;
- rpmsw_cycles = rpmswCalibrate();
- rpmsw_type = 0;
-#endif
- rpmsw_overhead = rpmswDiff(rpmswNow(&end), &begin);
-#if defined(__i386)
- rpmsw_type = 1;
- if (rpmsw_overhead > 1)
- rpmsw_cycles /= rpmsw_overhead;
-#endif
- if (rpmsw_cycles < 1)
+ /* Convergence is futile overkill ... */
+ for (i = 0; i < 1; i++) {
+#if defined(HP_TIMING_NOW)
+ rpmtime_t save_cycles = rpmsw_cycles;
+
+ /* We want cycles, not cycles/usec, here. */
rpmsw_cycles = 1;
+
+ /* Start wall clock. */
+ rpmsw_type = 0;
+ (void) rpmswNow(&begin);
+
+ /* Get no. of cycles in 20ms nanosleep */
+ rpmsw_type = 1;
+ cycles = rpmswCalibrate();
+ if (i)
+ cycles -= (save_cycles * rpmsw_overhead);
+
+ /* Compute wall clock delta in usecs. */
+ rpmsw_type = 0;
+ usecs = rpmswDiff(rpmswNow(&end), &begin);
+
+ rpmsw_type = 1;
+
+ /* Compute cycles/usec */
+ if (usecs > 1)
+ cycles /= usecs;
+
+ rpmsw_cycles = save_cycles;
+ rpmsw_cycles *= i;
+ rpmsw_cycles += cycles;
+ rpmsw_cycles /= (i+1);
#endif
- rpmsw_overhead = 0;
- (void) rpmswNow(&begin);
- rpmsw_overhead = rpmswDiff(rpmswNow(&end), &begin);
+ /* Calculate timing overhead in usecs. */
+ (void) rpmswNow(&begin);
+ usecs = rpmswDiff(rpmswNow(&end), &begin);
+
+ rpmsw_overhead *= i;
+ rpmsw_overhead += usecs;
+ rpmsw_overhead /= (i+1);
+
+ }
return rpmsw_overhead;
}
diff --git a/rpmio/rpmsw.h b/rpmio/rpmsw.h
index 677a562d1..ced72a5b3 100644
--- a/rpmio/rpmsw.h
+++ b/rpmio/rpmsw.h
@@ -7,7 +7,7 @@
/** \ingroup rpmio
*/
-typedef unsigned long rpmtime_t;
+typedef unsigned long int rpmtime_t;
/** \ingroup rpmio
*/
@@ -18,10 +18,13 @@ typedef struct rpmsw_s * rpmsw;
struct rpmsw_s {
union {
struct timeval tv;
- unsigned long long ticks;
+ unsigned long long int ticks;
+ unsigned long int tocks[2];
} u;
};
+#define RPMSW_SCALE (1000 * 1000)
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/rpmio/tsw.c b/rpmio/tsw.c
new file mode 100644
index 000000000..f9c4518e4
--- /dev/null
+++ b/rpmio/tsw.c
@@ -0,0 +1,25 @@
+#include "system.h"
+#include <rpmsw.h>
+#include "debug.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct rpmsw_s begin, end;
+ rpmtime_t diff;
+ int scale = 1000 * 1000;
+ int nsecs = 5;
+
+ diff = rpmswInit();
+
+fprintf(stderr, "*** Sleeping for %d secs ... ", nsecs);
+ (void) rpmswNow(&begin);
+ sleep(nsecs);
+ (void) rpmswNow(&end);
+
+ diff = rpmswDiff(&end, &begin);
+fprintf(stderr, "measured %u.%06u secs\n", (unsigned)diff/scale, (unsigned)diff%scale);
+
+ return 0;
+
+}