diff options
-rw-r--r-- | lib/psm.c | 6 | ||||
-rw-r--r-- | rpmio/Makefile.am | 5 | ||||
-rw-r--r-- | rpmio/rpmsq.c | 24 | ||||
-rw-r--r-- | rpmio/rpmsq.h | 9 | ||||
-rw-r--r-- | rpmio/rpmsw.c | 144 | ||||
-rw-r--r-- | rpmio/rpmsw.h | 7 | ||||
-rw-r--r-- | rpmio/tsw.c | 25 |
7 files changed, 167 insertions, 53 deletions
@@ -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; + +} |