Subject: Re: processor speed on O2
To: Thierry Lacoste <lacoste@univ-paris12.fr>
From: Stephen M. Rumble <stephen.rumble@utoronto.ca>
List: port-sgimips
Date: 03/31/2007 16:20:56
This message is in MIME format.

--=_ysboabqkvj4
Content-Type: text/plain;
	charset=ISO-8859-1;
	DelSp="Yes";
	format="flowed"
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Quoting Thierry Lacoste <lacoste@univ-paris12.fr>:

> I'm contributing a perl agent which collects various infos about
> a computer to ease inventories. More specifically I'm writing
> the BSD part. I try to make it work on various BSDs and various
> platforms.

Unfortunately, I don't think there's really any standardisation with =20
regards to reporting CPU frequency. I think it'll be an unfortunate =20
mess of special cases for not only each BSD, but each machine port, =20
and probably even machines within ports.

> Your answer rings two bells:
> - is it possible to query the PROM from within NetBSD?

No, not from userland. Within the kernel, doing:
     ARCBIOS->GetEnvironmentVariable("cpufreq")
will return a string of the frequency in MHz, as reported by the PROM.

> - a timing loop may be a cleaner way to get the processor
>   speed that what I currently do (greping through dmesg or
> sysctl). Can you give me some pointers on how to do that?

Here's userland example (attached). I don't have any mips machines at =20
hand, so I could only test it on x86, but it seems to be reasonably =20
accurate. Just comment out the 'X86' part and '#define MIPS'. The =20
sleep time is pretty long because I don't know what would yield good =20
results on NetBSD/sgimips. It could probably be reduced by an order of =20
magnitude.

Note that this will only work on >=3D R4000 chips, I believe, as R3000 =20
and below lack a cycle counter. An alternative for the latter would be =20
to loop on instructions with known cycle times and get an idea of =20
cycle count from that.

My apologies if it doesn't compile, or I botched the mips part.

Regards,
Steve

--=_ysboabqkvj4
Content-Type: text/x-csrc;
	charset=UTF-8;
	name="mhz.c"
Content-Disposition: attachment;
	filename="mhz.c"
Content-Transfer-Encoding: quoted-printable

/*
 * PUBLIC DOMAIN
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

#define X86
//#define MIPS

#define SLEEPTIME=09500000=09/* microseconds */

#ifdef MIPS
#define MAXCYCLES =09(0xffffffffUL)
uint64_t
read_cycle_counter()
{
=09uint32_t a;

=09__asm __volatile ("mfc0 %0, $9" :: "=3Dr" (a));

=09return ((uint64_t)a);
}
#endif

#ifdef X86
#define MAXCYCLES=09(0xffffffffffffffffULL)
uint64_t
read_cycle_counter()
{
=09uint32_t hi, lo;

=09__asm__ __volatile ("rdtsc" : "=3Da" (lo), "=3Dd" (hi));

=09return ((uint64_t)hi << 32 | lo);
}
#endif

uint32_t
tvdiff(struct timeval *tv1, struct timeval *tv2)
{
=09uint64_t before, after;

=09before =3D (uint64_t)tv1->tv_sec * 1000000 + tv1->tv_usec;
=09after  =3D (uint64_t)tv2->tv_sec * 1000000 + tv2->tv_usec;

=09return (after - before);
}

int
main()
{
=09struct timeval tv1, tv2;
=09uint64_t cc1, cc2;

=09gettimeofday(&tv1, NULL);
=09cc1 =3D read_cycle_counter();
#if SLEEPTIME > 1000000
=09sleep(SLEEPTIME / 1000000);
#else
=09usleep(SLEEPTIME);
#endif
=09cc2 =3D read_cycle_counter();
=09gettimeofday(&tv2, NULL);

=09if (cc1 < cc2)
=09=09cc1 =3D cc2 - cc1;
=09else
=09=09cc1 =3D cc2 + (MAXCYCLES - cc1);

=09printf("%.02f MHz\n", (float)cc1 / tvdiff(&tv1, &tv2));

=09return (0);
}

--=_ysboabqkvj4--