httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From w..@netscape.com (Wan-Teh Chang)
Subject Re: [PATCH] shared time again
Date Tue, 05 May 1998 16:58:51 GMT
Dean,

NSPR has two time-reporting functions for different purposes.

PR_IntervalNow() returns an unsigned, 32-bit time stamp.
This is intended to be a monotonically increasing timestamp
because we use it for timeout (interval timers).  Therefore, we want
it to be as cheap as possible, ideally just reading a counter
in user-space.  Also, this counter cannot tick too fast because we
have a constraint that the 32-bit time stamp cannot wrap around
within 5 or 6 hours.

PR_Now() returns a signed, 64-bit time, which is the number
of microseconds since the NSPR epoch (same as the Unix epoch),
midnight, 1 Jan 1970 UTC.  This one may not be monotonically
increasing because the system time may be reset at any time by
the system administrator or an NTP client/server.

So, on Unix, PR_Now() should still call gettimeofday() even
though it is expensive.  But PR_IntervalNow (or rather _PR_UNIX_GetInterval())
can call your assembly routine.

Win32 has a QueryPerformanceCounter syscall that is supposed to be
fast.  I just tried to disassemble it (want to see if it uses the same x86
RDTSC instruction and how it discovers it's not running on a Cyrix chip)
but failed :-(

Wan-Teh

Dean Gaudet wrote:

> BTW, I have a much better way to do SHARED_TIME... works for folks with
> reasonable processors that have user-space readable timestamp counters
> which work.  Intel x86 for example (AMD too I think, but not Cyrix
> due to a chip bug) has an RDTSC opcode which returns a monotonically
> increasing 64-bit cycle count.  I implemented it for fun against NSPR,
> I haven't benchmarked it much though.
>
> Dean
>
> run this to get the CPUS (cycles per microsecond) and EPOCH definitions
> for the below patch...  but you gotta run it after each reboot, because
> EPOCH changes.  A more permanent solution would be for this to be
> integrated into libc, and a /proc or sysctl interface to get CPUS and
> EPOCH.  Another improvement would be to calculate the mod 2^32 reciprocal
> of CPUS so that multiplication could be used instead of slow 64-bit
> division.
>
> calibrate.c:
>
> #include <sys/time.h>
> #include <unistd.h>
>
> typedef unsigned long long u64;
>
> extern inline u64 rdtsc(void)
> {
>     u64 r;
>
>     __asm__ __volatile__("rdtsc\n"
>         : "=A" (r)
>         : /* */
>         : "ax", "dx");
>     return r;
> }
>
> int main(int argc, char **argv)
> {
>     struct timeval stv, etv;
>     u64 scycle, ecycle;
>     u64 smicro, emicro;
>     u64 cpus;
>     u64 epoch;
>
>     gettimeofday(&stv, 0);
>     scycle = rdtsc();
>     sleep(10);
>     gettimeofday(&etv, 0);
>     ecycle = rdtsc();
>
>     smicro = (u64)stv.tv_sec * 1000000LL + stv.tv_usec;
>     emicro = (u64)etv.tv_sec * 1000000LL + etv.tv_usec;
>
>     printf("smicro = %Lu\n", smicro);
>     printf("emicro = %Lu\n", emicro);
>     printf("microseconds = %Lu\n", emicro - smicro);
>     printf("scycle = %Lu\n", scycle);
>     printf("ecycle = %Lu\n", ecycle);
>     printf("cycles = %Lu\n", ecycle - scycle);
>     cpus = (ecycle - scycle) / (emicro - smicro);
>     printf("cpus = %Lu\n", cpus);
>     epoch = smicro - scycle / cpus;
>     printf("epoch = %Lu\n", epoch);
> }
>
> --- 19980429/mozilla/nsprpub/pr/src/md/unix/unix.c.predg        Sun May  3 18:07:01 1998
> +++ 19980429/mozilla/nsprpub/pr/src/md/unix/unix.c      Sun May  3 18:17:43 1998
> @@ -2843,6 +2843,34 @@
>   *-----------------------------------------------------------------------
>   */
>
> +#if 1
> +extern __inline__ PRInt64 rdtsc(void)
> +{
> +    PRTime r;
> +
> +    __asm__ __volatile__("rdtsc\n"
> +        : "=A" (r)
> +        : /* */
> +        : "ax", "dx");
> +    return r;
> +}
> +
> +#define CPUS   267LL
> +#define EPOCH  892974059721195LL
> +
> +PR_IMPLEMENT(PRTime)
> +PR_Now(void)
> +{
> +       return rdtsc() / CPUS + EPOCH;
> +}
> +
> +PRIntervalTime _PR_UNIX_GetInterval()
> +{
> +       return rdtsc() / CPUS;
> +}
> +
> +#else
> +
>  PR_IMPLEMENT(PRTime)
>  PR_Now(void)
>  {
> @@ -2876,6 +2904,7 @@
>         ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC;  /* so's that */
>         return ticks;
>  }  /* _PR_SUNOS_GetInterval */
> +#endif
>
>  PRIntervalTime _PR_UNIX_TicksPerSecond()
>  {




Mime
View raw message