Repair rdtsc stopwatch, use gettimeofday(3) for now.
CVS patchset: 6716 CVS date: 2003/03/25 00:22:23
This commit is contained in:
parent
0b8c3f8319
commit
d79b053df3
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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@*/
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
144
rpmio/rpmsw.c
144
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
Loading…
Reference in New Issue