Module Name: src Committed By: yamt Date: Sat Feb 5 14:04:40 UTC 2011
Modified Files: src/sys/arch/x86/x86: tprof_amdpmi.c tprof_pmi.c src/sys/dev/tprof: tprof.c tprof.h tprof_ioctl.h Added Files: src/sys/dev/tprof: tprof_types.h Log Message: tprof: record pid and userland events. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/x86/tprof_amdpmi.c cvs rdiff -u -r1.11 -r1.12 src/sys/arch/x86/x86/tprof_pmi.c cvs rdiff -u -r1.7 -r1.8 src/sys/dev/tprof/tprof.c cvs rdiff -u -r1.4 -r1.5 src/sys/dev/tprof/tprof.h cvs rdiff -u -r1.1 -r1.2 src/sys/dev/tprof/tprof_ioctl.h cvs rdiff -u -r0 -r1.1 src/sys/dev/tprof/tprof_types.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/x86/tprof_amdpmi.c diff -u src/sys/arch/x86/x86/tprof_amdpmi.c:1.2 src/sys/arch/x86/x86/tprof_amdpmi.c:1.3 --- src/sys/arch/x86/x86/tprof_amdpmi.c:1.2 Fri Mar 13 11:10:20 2009 +++ src/sys/arch/x86/x86/tprof_amdpmi.c Sat Feb 5 14:04:40 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: tprof_amdpmi.c,v 1.2 2009/03/13 11:10:20 yamt Exp $ */ +/* $NetBSD: tprof_amdpmi.c,v 1.3 2011/02/05 14:04:40 yamt Exp $ */ /*- * Copyright (c)2008,2009 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tprof_amdpmi.c,v 1.2 2009/03/13 11:10:20 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tprof_amdpmi.c,v 1.3 2011/02/05 14:04:40 yamt Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -39,6 +39,8 @@ #include <dev/tprof/tprof.h> +#include <uvm/uvm.h> /* VM_MIN_KERNEL_ADDRESS */ + #include <x86/tprof.h> #include <x86/nmi.h> @@ -100,7 +102,7 @@ event_hi = event >> 8; event_lo = event & 0xff; - pesr = PESR_OS | PESR_INT | + pesr = PESR_USR | PESR_OS | PESR_INT | __SHIFTIN(event_lo, PESR_EVENT_MASK_LO) | __SHIFTIN(event_hi, PESR_EVENT_MASK_HI) | __SHIFTIN(0, PESR_COUNTER_MASK) | @@ -146,6 +148,7 @@ #else /* defined(__x86_64__) */ tfi.tfi_pc = tf->tf_eip; #endif /* defined(__x86_64__) */ + tfi.tfi_inkernel = tfi.tfi_pc >= VM_MIN_KERNEL_ADDRESS; tprof_sample(tprof_cookie, &tfi); /* reset counter */ Index: src/sys/arch/x86/x86/tprof_pmi.c diff -u src/sys/arch/x86/x86/tprof_pmi.c:1.11 src/sys/arch/x86/x86/tprof_pmi.c:1.12 --- src/sys/arch/x86/x86/tprof_pmi.c:1.11 Sun May 9 20:32:41 2010 +++ src/sys/arch/x86/x86/tprof_pmi.c Sat Feb 5 14:04:40 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: tprof_pmi.c,v 1.11 2010/05/09 20:32:41 rmind Exp $ */ +/* $NetBSD: tprof_pmi.c,v 1.12 2011/02/05 14:04:40 yamt Exp $ */ /*- * Copyright (c)2008,2009 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tprof_pmi.c,v 1.11 2010/05/09 20:32:41 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tprof_pmi.c,v 1.12 2011/02/05 14:04:40 yamt Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -40,6 +40,8 @@ #include <dev/tprof/tprof.h> +#include <uvm/uvm.h> /* VM_MIN_KERNEL_ADDRESS */ + #include <x86/tprof.h> #include <x86/nmi.h> @@ -126,10 +128,10 @@ cccr = CCCR_ENABLE | __SHIFTIN(cccr_escr_select, CCCR_ESCR_SELECT) | CCCR_MUST_BE_SET; if (ci->ci_smt_id == 0) { - escr |= ESCR_T0_OS; + escr |= ESCR_T0_OS | ESCR_T0_USR; cccr |= CCCR_OVF_PMI_T0; } else { - escr |= ESCR_T1_OS; + escr |= ESCR_T1_OS | ESCR_T0_USR; cccr |= CCCR_OVF_PMI_T1; } @@ -189,6 +191,7 @@ #else /* defined(__x86_64__) */ tfi.tfi_pc = tf->tf_eip; #endif /* defined(__x86_64__) */ + tfi.tfi_inkernel = tfi.tfi_pc >= VM_MIN_KERNEL_ADDRESS; tprof_sample(tprof_cookie, &tfi); /* reset counter */ Index: src/sys/dev/tprof/tprof.c diff -u src/sys/dev/tprof/tprof.c:1.7 src/sys/dev/tprof/tprof.c:1.8 --- src/sys/dev/tprof/tprof.c:1.7 Wed Aug 11 11:36:02 2010 +++ src/sys/dev/tprof/tprof.c Sat Feb 5 14:04:40 2011 @@ -1,7 +1,7 @@ -/* $NetBSD: tprof.c,v 1.7 2010/08/11 11:36:02 pgoyette Exp $ */ +/* $NetBSD: tprof.c,v 1.8 2011/02/05 14:04:40 yamt Exp $ */ /*- - * Copyright (c)2008,2009 YAMAMOTO Takashi, + * Copyright (c)2008,2009,2010 YAMAMOTO Takashi, * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tprof.c,v 1.7 2010/08/11 11:36:02 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tprof.c,v 1.8 2011/02/05 14:04:40 yamt Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -38,6 +38,7 @@ #include <sys/callout.h> #include <sys/kmem.h> #include <sys/module.h> +#include <sys/proc.h> #include <sys/workqueue.h> #include <sys/queue.h> @@ -55,12 +56,10 @@ * L: tprof_lock * R: tprof_reader_lock * S: tprof_startstop_lock + * s: writer should hold tprof_startstop_lock and tprof_lock + * reader should hold tprof_startstop_lock or tprof_lock */ -typedef struct { - uintptr_t s_pc; /* program counter */ -} tprof_sample_t; - typedef struct tprof_buf { u_int b_used; u_int b_size; @@ -89,7 +88,7 @@ } tprof_backend_t; static kmutex_t tprof_lock; -static bool tprof_running; +static bool tprof_running; /* s: */ static u_int tprof_nworker; /* L: # of running worker LWPs */ static lwp_t *tprof_owner; static STAILQ_HEAD(, tprof_buf) tprof_list; /* L: global buffer list */ @@ -318,8 +317,6 @@ static void tprof_stop(void) { - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; tprof_backend_t *tb; KASSERT(mutex_owned(&tprof_startstop_lock)); @@ -335,15 +332,10 @@ mutex_enter(&tprof_lock); tprof_running = false; cv_broadcast(&tprof_reader_cv); - mutex_exit(&tprof_lock); - - for (CPU_INFO_FOREACH(cii, ci)) { - mutex_enter(&tprof_lock); - while (tprof_nworker > 0) { - cv_wait(&tprof_cv, &tprof_lock); - } - mutex_exit(&tprof_lock); + while (tprof_nworker > 0) { + cv_wait(&tprof_cv, &tprof_lock); } + mutex_exit(&tprof_lock); tprof_stop1(); done: @@ -400,7 +392,7 @@ * tprof_sample: record a sample on the per-cpu buffer. * * be careful; can be called in NMI context. - * we are assuming that curcpu() is safe. + * we are bluntly assuming that curcpu() and curlwp->l_proc->p_pid are safe. */ void @@ -408,6 +400,7 @@ { tprof_cpu_t * const c = tprof_curcpu(); tprof_buf_t * const buf = c->c_buf; + tprof_sample_t *sp; const uintptr_t pc = tfi->tfi_pc; u_int idx; @@ -416,7 +409,10 @@ buf->b_overflow++; return; } - buf->b_data[idx].s_pc = pc; + sp = &buf->b_data[idx]; + sp->s_pid = curlwp->l_proc->p_pid; + sp->s_flags = (tfi->tfi_inkernel) ? TPROF_SAMPLE_INKERNEL : 0; + sp->s_pc = pc; buf->b_used = idx + 1; } Index: src/sys/dev/tprof/tprof.h diff -u src/sys/dev/tprof/tprof.h:1.4 src/sys/dev/tprof/tprof.h:1.5 --- src/sys/dev/tprof/tprof.h:1.4 Wed Nov 18 12:24:05 2009 +++ src/sys/dev/tprof/tprof.h Sat Feb 5 14:04:40 2011 @@ -1,7 +1,7 @@ -/* $NetBSD: tprof.h,v 1.4 2009/11/18 12:24:05 yamt Exp $ */ +/* $NetBSD: tprof.h,v 1.5 2011/02/05 14:04:40 yamt Exp $ */ /*- - * Copyright (c)2008,2009 YAMAMOTO Takashi, + * Copyright (c)2008,2009,2010 YAMAMOTO Takashi, * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,6 +29,14 @@ #ifndef _DEV_TPROF_TPROF_H_ #define _DEV_TPROF_TPROF_H_ +/* + * definitions used by backend drivers + */ + +#include <sys/types.h> + +#include <dev/tprof/tprof_types.h> + typedef struct tprof_backend_cookie tprof_backend_cookie_t; typedef struct tprof_backend_ops { @@ -37,12 +45,13 @@ void (*tbo_stop)(tprof_backend_cookie_t *); } tprof_backend_ops_t; -#define TPROF_BACKEND_VERSION 2 +#define TPROF_BACKEND_VERSION 3 int tprof_backend_register(const char *, const tprof_backend_ops_t *, int); int tprof_backend_unregister(const char *); typedef struct { - uintptr_t tfi_pc; + uintptr_t tfi_pc; /* program counter */ + bool tfi_inkernel; /* if tfi_pc is in the kernel address space */ } tprof_frame_info_t; void tprof_sample(tprof_backend_cookie_t *, const tprof_frame_info_t *); Index: src/sys/dev/tprof/tprof_ioctl.h diff -u src/sys/dev/tprof/tprof_ioctl.h:1.1 src/sys/dev/tprof/tprof_ioctl.h:1.2 --- src/sys/dev/tprof/tprof_ioctl.h:1.1 Tue Jan 1 21:28:38 2008 +++ src/sys/dev/tprof/tprof_ioctl.h Sat Feb 5 14:04:40 2011 @@ -1,7 +1,7 @@ -/* $NetBSD: tprof_ioctl.h,v 1.1 2008/01/01 21:28:38 yamt Exp $ */ +/* $NetBSD: tprof_ioctl.h,v 1.2 2011/02/05 14:04:40 yamt Exp $ */ /*- - * Copyright (c)2008 YAMAMOTO Takashi, + * Copyright (c)2008,2010 YAMAMOTO Takashi, * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,9 +29,15 @@ #ifndef _DEV_TPROF_TPROF_IOCTL_H_ #define _DEV_TPROF_TPROF_IOCTL_H_ +/* + * definitions for userland consumer + */ + #include <sys/ioccom.h> -#define TPROF_VERSION 1 +#include <dev/tprof/tprof_types.h> + +#define TPROF_VERSION 2 #define TPROF_IOC_GETVERSION _IOR('T', 1, int) Added files: Index: src/sys/dev/tprof/tprof_types.h diff -u /dev/null src/sys/dev/tprof/tprof_types.h:1.1 --- /dev/null Sat Feb 5 14:04:40 2011 +++ src/sys/dev/tprof/tprof_types.h Sat Feb 5 14:04:40 2011 @@ -0,0 +1,54 @@ +/* $NetBSD: tprof_types.h,v 1.1 2011/02/05 14:04:40 yamt Exp $ */ + +/*- + * Copyright (c)2010 YAMAMOTO Takashi, + * 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. + */ + +#ifndef _DEV_TPROF_TPROF_TYPES_H_ +#define _DEV_TPROF_TPROF_TYPES_H_ + +/* + * definitions used by both of kernel and userland + */ + +#if defined(_KERNEL) +#include <sys/types.h> +#else /* defined(_KERNEL) */ +#include <stdint.h> +#endif /* defined(_KERNEL) */ + +typedef struct { + uint32_t s_pid; /* process id */ + uint32_t s_flags; /* flags */ + uintptr_t s_pc; /* program counter */ +} tprof_sample_t; + +/* + * s_flags + */ + +#define TPROF_SAMPLE_INKERNEL 1 /* s_pc is in kernel address space */ + +#endif /* _DEV_TPROF_TPROF_TYPES_H_ */