From 075220991889433d0d34a124dd2ab289daff651b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 8 Jun 2006 18:25:48 +0000 Subject: [PATCH] Add an option, DEBUG_PCTRACK, which will record the program counter of the code being interrupted from the statistics clock interrupt. --- sys/conf/options | 5 ++- sys/kern/kern_clock.c | 72 +++++++++++++++++++++++++++++++++++++++++-- sys/sys/kinfo.h | 22 ++++++++++++- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/sys/conf/options b/sys/conf/options index 8e4f3fe62e..b1472d8727 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/options,v 1.191.2.53 2003/06/04 17:56:58 sam Exp $ -# $DragonFly: src/sys/conf/options,v 1.48 2006/05/29 07:29:12 dillon Exp $ +# $DragonFly: src/sys/conf/options,v 1.49 2006/06/08 18:25:45 dillon Exp $ # # On the handling of kernel options # @@ -403,6 +403,9 @@ DEBUG_INTERRUPTS opt_global.h SOCKBUF_DEBUG opt_global.h PANIC_DEBUG opt_global.h +# Sample system/interrupt PC +DEBUG_PCTRACK opt_pctrack.h + # These are VM related options NO_SWAPPING opt_vm.h PQ_CACHESIZE opt_vmpage.h diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index b6a8f0dc90..58af3d8a1f 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -70,11 +70,12 @@ * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/kern_clock.c,v 1.105.2.10 2002/10/17 13:19:40 maxim Exp $ - * $DragonFly: src/sys/kern/kern_clock.c,v 1.52 2006/06/01 16:49:59 dillon Exp $ + * $DragonFly: src/sys/kern/kern_clock.c,v 1.53 2006/06/08 18:25:46 dillon Exp $ */ #include "opt_ntp.h" #include "opt_polling.h" +#include "opt_pctrack.h" #include #include @@ -107,6 +108,10 @@ extern void init_device_poll(void); #endif +#ifdef DEBUG_PCTRACK +static void do_pctrack(struct intrframe *frame, int which); +#endif + static void initclocks (void *dummy); SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) @@ -116,6 +121,11 @@ SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) * just compare relative times against the total by delta. */ struct kinfo_cputime cputime_percpu[MAXCPU]; +#ifdef DEBUG_PCTRACK +struct kinfo_pcheader cputime_pcheader = { PCTRACK_SIZE, PCTRACK_ARYSIZE }; +struct kinfo_pctrack cputime_pctrack[MAXCPU][PCTRACK_SIZE]; +#endif + #ifdef SMP static int sysctl_cputime(SYSCTL_HANDLER_ARGS) @@ -616,16 +626,72 @@ statclock(systimer_t info, struct intrframe *frame) td->td_sticks += bump; if (frame && CLKF_INTR(frame)) { +#ifdef DEBUG_PCTRACK + do_pctrack(frame, PCTRACK_INT); +#endif cpu_time.cp_intr += bump; } else { - if (td == &mycpu->gd_idlethread) + if (td == &mycpu->gd_idlethread) { cpu_time.cp_idle += bump; - else + } else { +#ifdef DEBUG_PCTRACK + if (frame) + do_pctrack(frame, PCTRACK_SYS); +#endif cpu_time.cp_sys += bump; + } } } } +#ifdef DEBUG_PCTRACK +/* + * Sample the PC when in the kernel or in an interrupt. User code can + * retrieve the information and generate a histogram or other output. + */ + +static void +do_pctrack(struct intrframe *frame, int which) +{ + struct kinfo_pctrack *pctrack; + + pctrack = &cputime_pctrack[mycpu->gd_cpuid][which]; + pctrack->pc_array[pctrack->pc_index & PCTRACK_ARYMASK] = + (void *)CLKF_PC(frame); + ++pctrack->pc_index; +} + +static int +sysctl_pctrack(SYSCTL_HANDLER_ARGS) +{ + struct kinfo_pcheader head; + int error; + int cpu; + int ntrack; + + head.pc_ntrack = PCTRACK_SIZE; + head.pc_arysize = PCTRACK_ARYSIZE; + + if ((error = SYSCTL_OUT(req, &head, sizeof(head))) != 0) + return (error); + + for (cpu = 0; cpu < ncpus; ++cpu) { + for (ntrack = 0; ntrack < PCTRACK_SIZE; ++ntrack) { + error = SYSCTL_OUT(req, &cputime_pctrack[cpu][ntrack], + sizeof(struct kinfo_pctrack)); + if (error) + break; + } + if (error) + break; + } + return (error); +} +SYSCTL_PROC(_kern, OID_AUTO, pctrack, (CTLTYPE_OPAQUE|CTLFLAG_RD), 0, 0, + sysctl_pctrack, "S,kinfo_pcheader", "CPU PC tracking"); + +#endif + /* * The scheduler clock typically runs at a 50Hz rate. NOTE! systimer, * the MP lock might not be held. We can safely manipulate parts of curproc diff --git a/sys/sys/kinfo.h b/sys/sys/kinfo.h index 2fec8a55b3..7899b7e59c 100644 --- a/sys/sys/kinfo.h +++ b/sys/sys/kinfo.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/kinfo.h,v 1.6 2006/05/20 02:42:13 dillon Exp $ + * $DragonFly: src/sys/sys/kinfo.h,v 1.7 2006/06/08 18:25:48 dillon Exp $ */ #ifndef _SYS_KINFO_H_ @@ -69,6 +69,26 @@ struct kinfo_cputime { uint64_t cp_idle; }; +/* + * CPU system/interrupt program counter sampler + */ +#define PCTRACK_ARYSIZE 32 /* must be a power of 2 */ +#define PCTRACK_ARYMASK (PCTRACK_ARYSIZE - 1) + +struct kinfo_pcheader { + int pc_ntrack; /* number of tracks per cpu (2) */ + int pc_arysize; /* size of storage array (32) */ +}; + +struct kinfo_pctrack { + int pc_index; + void *pc_array[PCTRACK_ARYSIZE]; +}; + +#define PCTRACK_SYS 0 +#define PCTRACK_INT 1 +#define PCTRACK_SIZE 2 + struct kinfo_clockinfo { int ci_hz; /* clock frequency */ int ci_tick; /* micro-seconds per hz tick */ -- 2.41.0