From 8be6dace2bc14f1cd052e5bf5a868d62885110c1 Mon Sep 17 00:00:00 2001 From: bde Date: Wed, 26 May 2004 09:43:38 +0000 Subject: [PATCH] Quick fix for overflow when tsc_freq >= 2^31. "int profrate" in struct gmon and struct gmonhdr was originally just to represent the kernel (profiling) clock frequency and it remains poorly suited to representing the frequencies of fast counters like the TSC. It broke a year or two ago. This quick fix keeps it working for another year or month or two until TSC frequencies can exceed 2^32, by dividing the frequency by 2. Dividing the frequency by 4 would work for a little longer but would lose a little too much precision. --- sys/amd64/amd64/prof_machdep.c | 13 ++++++++++--- sys/i386/isa/prof_machdep.c | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/sys/amd64/amd64/prof_machdep.c b/sys/amd64/amd64/prof_machdep.c index 640368bfa276..60e34e8c1d4b 100644 --- a/sys/amd64/amd64/prof_machdep.c +++ b/sys/amd64/amd64/prof_machdep.c @@ -220,8 +220,15 @@ cputime() #ifndef SMP if (cputime_clock == CPUTIME_CLOCK_TSC) { - count = (u_int)rdtsc(); - delta = (int)(count - prev_count); + /* + * Scale the TSC a little to make cputime()'s frequency + * fit in an int, assuming that the TSC frequency fits + * in a u_int. Use a fixed scale since dynamic scaling + * would be slower and we can't really use the low bit + * of precision. + */ + count = (u_int)rdtsc() & ~1u; + delta = (int)(count - prev_count) >> 1; prev_count = count; return (delta); } @@ -330,7 +337,7 @@ startguprof(gp) gp->profrate = timer_freq << CPUTIME_CLOCK_I8254_SHIFT; #ifndef SMP if (cputime_clock == CPUTIME_CLOCK_TSC) - gp->profrate = tsc_freq; + gp->profrate = tsc_freq >> 1; #if defined(PERFMON) && defined(I586_PMC_GUPROF) else if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { if (perfmon_avail() && diff --git a/sys/i386/isa/prof_machdep.c b/sys/i386/isa/prof_machdep.c index 31b1c2a16059..57d234262b78 100644 --- a/sys/i386/isa/prof_machdep.c +++ b/sys/i386/isa/prof_machdep.c @@ -190,8 +190,15 @@ cputime() #if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) if (cputime_clock == CPUTIME_CLOCK_TSC) { - count = (u_int)rdtsc(); - delta = (int)(count - prev_count); + /* + * Scale the TSC a little to make cputime()'s frequency + * fit in an int, assuming that the TSC frequency fits + * in a u_int. Use a fixed scale since dynamic scaling + * would be slower and we can't really use the low bit + * of precision. + */ + count = (u_int)rdtsc() & ~1u; + delta = (int)(count - prev_count) >> 1; prev_count = count; return (delta); } @@ -300,7 +307,7 @@ startguprof(gp) gp->profrate = timer_freq << CPUTIME_CLOCK_I8254_SHIFT; #if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) if (cputime_clock == CPUTIME_CLOCK_TSC) - gp->profrate = tsc_freq; + gp->profrate = tsc_freq >> 1; #if defined(PERFMON) && defined(I586_PMC_GUPROF) else if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { if (perfmon_avail() &&