Don Burns (don_burns++at++peru.engr.sgi.com)
Mon, 29 Mar 1999 12:31:34 -0800 (PST)
> i had done some fiddlin' a few weeks ago trying to get better resolution
> than sginap provides, and so i tested nanosleep and usleep. my conclusion
> was that their resolution (at least in the default setup in IRIX 6.5.1)
> is 10 milliseconds, just like sginap. here is some sample data:
> --> so how does one use these routines at their high resolution potential?
I say bypass the ole kernel, avoid scheduling, thumb your nose at system calls
and go staight to the horse's mouth and read the user-mapped hi resolution
clock. The worst you'll get is a TLB miss and the time it takes to read a long
word.
Here's a C++ class to help out. Here's how to use it:
unsigned long t0, t1, dt;
*t = new HiResolutionTimer;
t0 = t->tic();
t1 = t->tic();
dt = t->deltan( t0, t1 );
printf( "Nanosecs between clock ticks : %d\n", dt );
-don
#ifndef _HI_RES_TIMER_H
#define _HI_RES_TIMER_H
class HiResolutionTimer {
private :
double microseconds_per_click;
double nanoseconds_per_click;
unsigned long *clk;
int cycleCntrSize;
static unsigned long dummy;
public:
HiResolutionTimer( void );
~HiResolutionTimer( void );
inline unsigned long tic( void ) { return *clk; }
unsigned long deltau( unsigned long t1, unsigned long t2 );
unsigned long deltan( unsigned long t1, unsigned long t2 );
};
#endif
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/syssgi.h>
#include <sys/immu.h>
#include "timer.h"
unsigned long HiResolutionTimer::dummy = 0;
HiResolutionTimer::HiResolutionTimer( void )
{
__psunsigned_t phys_addr, raddr;
unsigned int cycleval;
volatile unsigned long counter_value, *iotimer_addr;
int fd, poffmask;
poffmask = getpagesize() - 1;
phys_addr = syssgi( SGI_QUERY_CYCLECNTR, &cycleval );
microseconds_per_click = (double)cycleval/1e6;
nanoseconds_per_click = (double)cycleval/1e3;
raddr = phys_addr & ~poffmask;
clk = &dummy;
if( (fd = open( "/dev/mmem", O_RDONLY )) < 0 )
{
perror( "/dev/mmem" );
return;
}
iotimer_addr = (volatile unsigned long *)mmap(
(void *)0L,
(size_t)poffmask,
(int)PROT_READ,
(int)MAP_PRIVATE, fd, (off_t)raddr);
iotimer_addr = (unsigned long *)(
(__psunsigned_t)iotimer_addr + (phys_addr & poffmask)
);
cycleCntrSize = syssgi( SGI_CYCLECNTR_SIZE );
if( cycleCntrSize > 32 )
++iotimer_addr;
clk = (unsigned long *)iotimer_addr;
}
unsigned long HiResolutionTimer::deltau( unsigned long t1, unsigned long t2 )
{
unsigned long delta = t2 - t1;
return (unsigned long )((double)delta * microseconds_per_click);
}
unsigned long HiResolutionTimer::deltan( unsigned long t1, unsigned long t2 )
{
unsigned long delta = t2 - t1;
return (unsigned long )((double)delta * nanoseconds_per_click);
}
This archive was generated by hypermail 2.0b2 on Mon Mar 29 1999 - 12:31:42 PST