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
[email protected]