-rw-r--r-- 2560 nttcompiler-20220411/cpucycles/arm1176/cpucycles.c
/*
cpucycles/arm1176.c version 20200114
D. J. Bernstein
Public domain.
Target: ARM1176 core, as in Raspberry Pi 1A, 1A+, 1B, 1B+, CM1, 0, 0W.
Need kernel to do asm volatile("mcr p15,0,%0,c15,c9,0" :: "r"(1));
since hardware does not allow user access to cycle counter by default.
*/
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include "cpucycles.h"
static unsigned int readticks(void)
{
static int enabled;
unsigned int r;
if (!enabled) {
asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r"(r));
asm volatile("mcr p15, 0, %0, c15, c12, 0" :: "r"(r|1));
enabled = 1;
}
asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r"(r));
return r;
}
/* startup state: all prev are 0 */
/* XXX: gettimeofday() clock assumed to not be 1970 */
/* previous observation of 32-bit cycle counter */
static long long cycles32prev;
/* previous observation of gettimeofday() */
static long long usecprev;
static long long secprev;
/* previous computed 64-bit cycle counter */
static unsigned long long cycles64prev;
/* previous computed cycles per second */
static long long cyclespersec;
long long cpucycles(void)
{
unsigned int cycles32now;
struct timeval t;
long long usecnow;
long long secnow;
long long usecdiff;
long long secdiff;
unsigned long long cycles32diff;
unsigned long long guesscycles;
cycles32now = readticks();
gettimeofday(&t,(struct timezone *) 0);
usecnow = t.tv_usec;
secnow = t.tv_sec;
cycles32diff = (unsigned int) (cycles32now - cycles32prev); /* unsigned change in number of cycles mod 2^32 */
usecdiff = usecnow - usecprev; /* signed change in number of usec mod 10^9 */
secdiff = secnow - secprev; /* signed change in number of sec */
if ((secdiff == 0 && usecdiff < 20000) || (secdiff == 1 && usecdiff < -980000))
return cycles64prev + cycles32diff;
cycles32prev = cycles32now;
usecprev = usecnow;
secprev = secnow;
usecdiff += 1000000 * (long long) secdiff;
if (usecdiff > 0 && usecdiff < 30000) {
/* XXX: assuming cycles do not increase by 2^32 in <0.03 seconds */
cyclespersec = 1000000 * (unsigned long long) cycles32diff;
cyclespersec /= usecdiff;
} else {
guesscycles = (usecdiff * cyclespersec) / 1000000;
while (cycles32diff + 2147483648ULL < guesscycles) cycles32diff += 4294967296ULL;
/* XXX: could do longer-term extrapolation here */
}
cycles64prev += cycles32diff;
return cycles64prev;
}
long long cpucycles_persecond(void)
{
while (!cyclespersec) cpucycles();
return cyclespersec;
}