Re: nanosleep & sginap

New Message Reply Date view Thread view Subject view Author view

Don Burns (don_burns++at++peru.engr.sgi.com)
Mon, 29 Mar 1999 12:31:34 -0800 (PST)


ken "fire a few neurons" lindsay sez:

> 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);
}


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Mar 29 1999 - 12:31:42 PST

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.