Skip to content

Commit 99d6d0a

Browse files
luismarquesaswaterman
authored andcommitted
Make performance counters always 64 bits wide (riscv-software-src#178)
This prevents the counters from easily overflowing for a 32-bit pk.
1 parent 78e61ba commit 99d6d0a

File tree

5 files changed

+93
-21
lines changed

5 files changed

+93
-21
lines changed

pk/boot.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ typedef struct {
2020
size_t brk_max;
2121
size_t mmap_max;
2222
size_t stack_top;
23-
size_t time0;
24-
size_t cycle0;
25-
size_t instret0;
23+
uint64_t time0;
24+
uint64_t cycle0;
25+
uint64_t instret0;
2626
} elf_info;
2727

2828
extern elf_info current;

pk/pk.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ static void run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top)
132132
STACK_INIT(uintptr_t);
133133

134134
if (current.cycle0) { // start timer if so requested
135-
current.time0 = rdtime();
136-
current.cycle0 = rdcycle();
137-
current.instret0 = rdinstret();
135+
current.time0 = rdtime64();
136+
current.cycle0 = rdcycle64();
137+
current.instret0 = rdinstret64();
138138
}
139139

140140
trapframe_t tf;

pk/pk.h

+58
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,64 @@ static inline int insn_len(long insn)
4141
return (insn & 0x3) < 0x3 ? 2 : 4;
4242
}
4343

44+
#if __riscv_xlen == 32
45+
46+
static inline uint64_t rdtime64()
47+
{
48+
uint32_t time;
49+
uint32_t timeh1;
50+
uint32_t timeh2;
51+
52+
do
53+
{
54+
timeh1 = read_csr(timeh);
55+
time = read_csr(time);
56+
timeh2 = read_csr(timeh);
57+
} while(timeh1 != timeh2);
58+
59+
return (((uint64_t) timeh1) << 32) | time;
60+
}
61+
62+
static inline uint64_t rdcycle64()
63+
{
64+
uint32_t cycle;
65+
uint32_t cycleh1;
66+
uint32_t cycleh2;
67+
68+
do
69+
{
70+
cycleh1 = read_csr(cycleh);
71+
cycle = read_csr(cycle);
72+
cycleh2 = read_csr(cycleh);
73+
} while(cycleh1 != cycleh2);
74+
75+
return (((uint64_t) cycleh1) << 32) | cycle;
76+
}
77+
78+
static inline uint64_t rdinstret64()
79+
{
80+
uint32_t instret;
81+
uint32_t instreth1;
82+
uint32_t instreth2;
83+
84+
do
85+
{
86+
instreth1 = read_csr(instreth);
87+
instret = read_csr(instret);
88+
instreth2 = read_csr(instreth);
89+
} while(instreth1 != instreth2);
90+
91+
return (((uint64_t) instreth1) << 32) | instret;
92+
}
93+
94+
#else
95+
96+
#define rdtime64 rdtime
97+
#define rdcycle64 rdcycle
98+
#define rdinstret64 rdinstret
99+
100+
#endif
101+
44102
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
45103

46104
#ifdef __cplusplus

pk/syscall.c

+13-12
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ typedef long (*syscall_t)(long, long, long, long, long, long, long);
1616
void sys_exit(int code)
1717
{
1818
if (current.cycle0) {
19-
size_t dt = rdtime() - current.time0;
20-
size_t dc = rdcycle() - current.cycle0;
21-
size_t di = rdinstret() - current.instret0;
22-
23-
printk("%ld ticks\n", dt);
24-
printk("%ld cycles\n", dc);
25-
printk("%ld instructions\n", di);
26-
printk("%d.%d%d CPI\n", dc/di, 10ULL*dc/di % 10, (100ULL*dc + di/2)/di % 10);
19+
uint64_t dt = rdtime64() - current.time0;
20+
uint64_t dc = rdcycle64() - current.cycle0;
21+
uint64_t di = rdinstret64() - current.instret0;
22+
23+
printk("%lld ticks\n", dt);
24+
printk("%lld cycles\n", dc);
25+
printk("%lld instructions\n", di);
26+
printk("%d.%d%d CPI\n", (int)(dc/di), (int)(10ULL*dc/di % 10),
27+
(int)((100ULL*dc + di/2)/di % 10));
2728
}
2829
shutdown(code);
2930
}
@@ -353,15 +354,15 @@ int sys_rt_sigaction(int sig, const void* act, void* oact, size_t sssz)
353354

354355
long sys_time(long* loc)
355356
{
356-
uintptr_t t = rdcycle() / CLOCK_FREQ;
357+
uint64_t t = rdcycle64() / CLOCK_FREQ;
357358
if (loc)
358359
*loc = t;
359360
return t;
360361
}
361362

362363
int sys_times(long* loc)
363364
{
364-
uintptr_t t = rdcycle();
365+
uint64_t t = rdcycle64();
365366
kassert(CLOCK_FREQ % 1000000 == 0);
366367
loc[0] = t / (CLOCK_FREQ / 1000000);
367368
loc[1] = 0;
@@ -373,7 +374,7 @@ int sys_times(long* loc)
373374

374375
int sys_gettimeofday(long* loc)
375376
{
376-
uintptr_t t = rdcycle();
377+
uint64_t t = rdcycle64();
377378
loc[0] = t / CLOCK_FREQ;
378379
loc[1] = (t % CLOCK_FREQ) / (CLOCK_FREQ / 1000000);
379380

@@ -382,7 +383,7 @@ int sys_gettimeofday(long* loc)
382383

383384
long sys_clock_gettime(int clk_id, long *loc)
384385
{
385-
uintptr_t t = rdcycle();
386+
uint64_t t = rdcycle64();
386387
loc[0] = t / CLOCK_FREQ;
387388
loc[1] = (t % CLOCK_FREQ) / (CLOCK_FREQ / 1000000000);
388389

util/snprintf.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
99
{
1010
bool format = false;
1111
bool longarg = false;
12+
bool longlongarg = false;
1213
size_t pos = 0;
1314
for( ; *s; s++)
1415
{
@@ -17,7 +18,12 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
1718
switch(*s)
1819
{
1920
case 'l':
20-
longarg = true;
21+
if (s[1] == 'l') {
22+
longlongarg = true;
23+
s++;
24+
}
25+
else
26+
longarg = true;
2127
break;
2228
case 'p':
2329
longarg = true;
@@ -36,20 +42,27 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
3642
}
3743
case 'd':
3844
{
39-
long num = longarg ? va_arg(vl, long) : va_arg(vl, int);
45+
long long num;
46+
if (longarg)
47+
num = va_arg(vl, long);
48+
else if (longlongarg)
49+
num = va_arg(vl, long long);
50+
else
51+
num = va_arg(vl, int);
4052
if (num < 0) {
4153
num = -num;
4254
if (++pos < n) out[pos-1] = '-';
4355
}
4456
long digits = 1;
45-
for (long nn = num; nn /= 10; digits++)
57+
for (long long nn = num; nn /= 10; digits++)
4658
;
4759
for (int i = digits-1; i >= 0; i--) {
4860
if (pos + i + 1 < n) out[pos + i] = '0' + (num % 10);
4961
num /= 10;
5062
}
5163
pos += digits;
5264
longarg = false;
65+
longlongarg = false;
5366
format = false;
5467
break;
5568
}

0 commit comments

Comments
 (0)