From 58550067673ef1af57be0eb5f9565d6007e8acda Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Tue, 21 Nov 2000 19:55:21 +0000 Subject: [PATCH] Add a consistent API to a feature that most modern CPUs have; a fast counter register in-CPU. This is to be used as a fast "timer", where linearity is more important than time, and multiple lines in the linearity caused by multiple CPUs in an SMP machine is not a problem. This adds no code whatsoever to the FreeBSD kernel until it is actually used, and then as a single-instruction inline routine (except for the 80386 and 80486 where it is some more inline code around nanotime(9). Reviewed by: bde, kris, jhb --- share/man/man9/get_cyclecount.9 | 97 +++++++++++++++++++++++++++++++ share/man/man9/get_cyclecounter.9 | 97 +++++++++++++++++++++++++++++++ sys/alpha/include/cpu.h | 10 ++++ sys/amd64/include/cpu.h | 21 +++++++ sys/i386/include/cpu.h | 21 +++++++ sys/ia64/include/cpu.h | 10 ++++ 6 files changed, 256 insertions(+) create mode 100644 share/man/man9/get_cyclecount.9 create mode 100644 share/man/man9/get_cyclecounter.9 diff --git a/share/man/man9/get_cyclecount.9 b/share/man/man9/get_cyclecount.9 new file mode 100644 index 00000000000..9bcc887ae2c --- /dev/null +++ b/share/man/man9/get_cyclecount.9 @@ -0,0 +1,97 @@ +.\" Copyright (c) 2000 Mark R V Murray +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd November 20, 2000 +.Dt get_cyclecounter 9 +.Os +.Sh NAME +.Nm get_cyclecounter +.Nd get the CPU's fast counter register contents +.Sh SYNOPSIS +.Fd #include +.Fd #include +.Ft u_int64_t +.Fn get_cyclecounter "void" +.Sh DESCRIPTION +The +.Fn get_cyclecounter +functon uses a register +available in most modern CPUs +to return a value +that is monotonically increasing +inside each CPU. +.Pp +In SMP systems, +there will be a number of +separate monotonic sequences, +one for each CPU running. +The value in the SMP case is +selected from one of these sequences, +dependent on which CPU +was scheduled to service the request. +.Pp +The speed and maximum value +of each counter +is CPU-dependant. +Some CPUs +(such as the +.Tn Intel +80386 and 80486) +do not have such a register, +so +.Fn get_cyclecounter +on these platforms +returns the number of nanoseconds +represented by the +structure returned by +.Xr nanotime 9 . +.Pp +The +.Tn Pentium +processors all use the +.Li TSC +register. +.Pp +The +.Tn Alpha processors use the +.Li PCC +register. +.Pp +The +.Tn IA64 +processors use the +.Li AR.ITC +register. +.Sh SEE ALSO +.Xr nanotime 9 +.Sh HISTORY +The +.Nm +function first appeared in +.Fx 5.0 +.Sh AUTHORS +This manual page was written by +.An Mark Murray Aq markm@FreeBSD.org . diff --git a/share/man/man9/get_cyclecounter.9 b/share/man/man9/get_cyclecounter.9 new file mode 100644 index 00000000000..9bcc887ae2c --- /dev/null +++ b/share/man/man9/get_cyclecounter.9 @@ -0,0 +1,97 @@ +.\" Copyright (c) 2000 Mark R V Murray +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd November 20, 2000 +.Dt get_cyclecounter 9 +.Os +.Sh NAME +.Nm get_cyclecounter +.Nd get the CPU's fast counter register contents +.Sh SYNOPSIS +.Fd #include +.Fd #include +.Ft u_int64_t +.Fn get_cyclecounter "void" +.Sh DESCRIPTION +The +.Fn get_cyclecounter +functon uses a register +available in most modern CPUs +to return a value +that is monotonically increasing +inside each CPU. +.Pp +In SMP systems, +there will be a number of +separate monotonic sequences, +one for each CPU running. +The value in the SMP case is +selected from one of these sequences, +dependent on which CPU +was scheduled to service the request. +.Pp +The speed and maximum value +of each counter +is CPU-dependant. +Some CPUs +(such as the +.Tn Intel +80386 and 80486) +do not have such a register, +so +.Fn get_cyclecounter +on these platforms +returns the number of nanoseconds +represented by the +structure returned by +.Xr nanotime 9 . +.Pp +The +.Tn Pentium +processors all use the +.Li TSC +register. +.Pp +The +.Tn Alpha processors use the +.Li PCC +register. +.Pp +The +.Tn IA64 +processors use the +.Li AR.ITC +register. +.Sh SEE ALSO +.Xr nanotime 9 +.Sh HISTORY +The +.Nm +function first appeared in +.Fx 5.0 +.Sh AUTHORS +This manual page was written by +.An Mark Murray Aq markm@FreeBSD.org . diff --git a/sys/alpha/include/cpu.h b/sys/alpha/include/cpu.h index a45b4d10558..a0be38fe0f5 100644 --- a/sys/alpha/include/cpu.h +++ b/sys/alpha/include/cpu.h @@ -173,6 +173,16 @@ void syscall __P((u_int64_t, struct trapframe *)); void trap __P((unsigned long, unsigned long, unsigned long, unsigned long, struct trapframe *)); +/* + * Return contents of in-cpu fast counter as a sort of "bogo-time" + * for non-critical timing. + */ +static __inline u_int64_t +get_cyclecount(void) +{ + return (alpha_rpcc()); +} + #endif /* _KERNEL */ #endif /* _ALPHA_CPU_H_ */ diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h index 7b090b66c81..669af64c1b4 100644 --- a/sys/amd64/include/cpu.h +++ b/sys/amd64/include/cpu.h @@ -47,6 +47,8 @@ #include #include #include +#include +#include /* * definitions of cpu-dependent requirements @@ -133,6 +135,25 @@ extern char etext[]; void fork_trampoline __P((void)); void fork_return __P((struct proc *, struct trapframe)); + +/* + * Return contents of in-cpu fast counter as a sort of "bogo-time" + * for non-critical timing. + */ +static __inline u_int64_t +get_cyclecount(void) +{ +#if defined(I386_CPU) || defined(I486_CPU) + struct timespec tv; + + if ((cpu_feature & CPUID_TSC) == 0) { + nanotime(&tv); + return (tv.tv_sec * (u_int64_t)1000000000 + tv.tv_nsec); + } +#endif + return (rdtsc()); +} + #endif #endif /* !_MACHINE_CPU_H_ */ diff --git a/sys/i386/include/cpu.h b/sys/i386/include/cpu.h index 7b090b66c81..669af64c1b4 100644 --- a/sys/i386/include/cpu.h +++ b/sys/i386/include/cpu.h @@ -47,6 +47,8 @@ #include #include #include +#include +#include /* * definitions of cpu-dependent requirements @@ -133,6 +135,25 @@ extern char etext[]; void fork_trampoline __P((void)); void fork_return __P((struct proc *, struct trapframe)); + +/* + * Return contents of in-cpu fast counter as a sort of "bogo-time" + * for non-critical timing. + */ +static __inline u_int64_t +get_cyclecount(void) +{ +#if defined(I386_CPU) || defined(I486_CPU) + struct timespec tv; + + if ((cpu_feature & CPUID_TSC) == 0) { + nanotime(&tv); + return (tv.tv_sec * (u_int64_t)1000000000 + tv.tv_nsec); + } +#endif + return (rdtsc()); +} + #endif #endif /* !_MACHINE_CPU_H_ */ diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h index d72f1d2388e..c6ebd1c6145 100644 --- a/sys/ia64/include/cpu.h +++ b/sys/ia64/include/cpu.h @@ -166,6 +166,16 @@ void switch_trampoline __P((void)); /* MAGIC */ void syscall __P((int, u_int64_t *, struct trapframe *)); void trap __P((int vector, int imm, struct trapframe *framep)); +/* + * Return contents of in-cpu fast counter as a sort of "bogo-time" + * for non-critical timing. + */ +static __inline u_int64_t +get_cyclecount(void) +{ + return (ia64_get_itc()); +} + #endif /* _KERNEL */ #endif /* _MACHINE_CPU_H_ */