Repair rdtsc stopwatch, use gettimeofday(3) for now.
authorjbj <devnull@localhost>
Tue, 25 Mar 2003 00:22:23 +0000 (00:22 +0000)
committerjbj <devnull@localhost>
Tue, 25 Mar 2003 00:22:23 +0000 (00:22 +0000)
CVS patchset: 6716
CVS date: 2003/03/25 00:22:23

lib/psm.c
rpmio/Makefile.am
rpmio/rpmsq.c
rpmio/rpmsq.h
rpmio/rpmsw.c
rpmio/rpmsw.h
rpmio/tsw.c [new file with mode: 0644]

index 706e41f..78c227b 100644 (file)
--- 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;
 }
index 2400182..1202039 100644 (file)
@@ -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
index 94dd4d0..a27c84b 100644 (file)
@@ -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@*/
index a149860..04fcf5e 100644 (file)
@@ -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;
 };
 
index df944f0..9824221 100644 (file)
@@ -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;
 }
index 677a562..ced72a5 100644 (file)
@@ -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 (file)
index 0000000..f9c4518
--- /dev/null
@@ -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;
+
+}