On Thu, Feb 02, 2006 at 04:17:56AM -0800, Roman wrote:
> I don't think it's filesystem related, i.e. there is not much I/O happening 
> at the time. Maybe NetBSD's /bin/sh is a lot faster than Solaris 
> /bin/{sh,ksh,bash}, maybe NetBSD's fork() is a lot faster. I didn't benchmark 
> the two operating systems. I'm hoping to conduct some benchmarks soon and 
> will post the results.
> 
> This brings me to another question: newer x86 CPUs have a time stamp counter, 
> wich can be accessed with rdtsc assembly instruction. I think ultrasparc CPUs 
> have a similar counter, accessed via %tick register. This is useful in 
> benchmarks when measuring high resolution timing evens.
> 
> On x86 with GCC I use the following function to take a time stamp:
> 
> uint64_t rdtsc(void) {
>         /*
>         ** rdtsc sets register %edx to the high-order 32 bits of the counter
>         ** and register %eax to the low-order 32 bits. Those values are stored
>         ** in an array of two 32 bit integers, and returned as a single 64 bit
>         ** value.
>         */
> 
>         union {
>                 uint64_t u64ts;
>                 uint32_t u32arr[2]; 
>         } un_rdtsc;
> 
>         __asm__ __volatile__ ("rdtsc; movl %%edx,%0; movl %%eax,%1"
>                 : "=r" (un_rdtsc.u32arr[1]), "=r" (un_rdtsc.u32arr[0])
>                 : /* No input */
>                 : "%edx", "%eax");
>         
>         return(un_rdtsc.u64ts);
> }
> 
> The above function will work with GCC, but I think it will not compile
> with SunPro compiler. Does anyone have any suggestions on how I could
> convert such a function into portable x86 and sparc assembly code
> (using rdtsc for x86 and %tick for sparc)?

Using RDTSC/%tick is fraught with complications.  In particular, there is
no guarantee that the values will be synchronized between different CPUs in
a multi-CPU box.  In addition, %tick is a privileged register on SPARC.

I'd recommend using gethrtime(3C);  it's guaranteed to be in sync, and is
in easily processed nanoseconds.


If you *MUST* use rdtsc, here's an assembly file for i386 and amd64:

% cat Makefile
ASFLAGS=-D_ASM
% cat rdtsc.S
#include <sys/asm_linkage.h>

#if defined(__amd64)
        ENTRY(rdtsc)
        rdtsc                   / %edx:%eax = RDTSC
        shlq    $32, %rdx
        orq     %rdx, %rax
        ret
        SET_SIZE(rdtsc)

#elif defined(__i386)
        ENTRY(rdtsc)
        rdtsc                   / %edx:%eax = RDTSC
        ret
        SET_SIZE(rdtsc)

#else
#error undefined architecture
#endif
% make rdtsc.o
cc  -D_ASM   -c -o rdtsc.o rdtsc.S
% 

This is derived from:

http://cvs.opensolaris.org/source/xref/on/usr/src/uts/intel/ia32/ml/ia32.il#293
http://cvs.opensolaris.org/source/xref/on/usr/src/uts/intel/amd64/ml/amd64.il#286


In addition, the GCC code above seems rather complex;  why not just:

#include <sys/types.h>

uint64_t rdtsc(void)
{
        uint64_t v;
        __asm__ __volatile__ ("rdtsc" : "=A" (v));
        return (v);
}

Cheers,
- jonathan

-- 
Jonathan Adams, Solaris Kernel Development
_______________________________________________
perf-discuss mailing list
perf-discuss@opensolaris.org

Reply via email to