profile.h revision 129408
11543Srgrimes/* 21543Srgrimes * Copyright (c) 1992, 1993 31543Srgrimes * The Regents of the University of California. All rights reserved. 41543Srgrimes * 51543Srgrimes * Redistribution and use in source and binary forms, with or without 61543Srgrimes * modification, are permitted provided that the following conditions 71543Srgrimes * are met: 81543Srgrimes * 1. Redistributions of source code must retain the above copyright 91543Srgrimes * notice, this list of conditions and the following disclaimer. 101543Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111543Srgrimes * notice, this list of conditions and the following disclaimer in the 121543Srgrimes * documentation and/or other materials provided with the distribution. 131543Srgrimes * 4. Neither the name of the University nor the names of its contributors 141543Srgrimes * may be used to endorse or promote products derived from this software 151543Srgrimes * without specific prior written permission. 161543Srgrimes * 171543Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181543Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191543Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201543Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211543Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221543Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231543Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241543Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251543Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261543Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271543Srgrimes * SUCH DAMAGE. 281543Srgrimes * 291543Srgrimes * @(#)profile.h 8.1 (Berkeley) 6/11/93 3050477Speter * $FreeBSD: head/sys/amd64/include/profile.h 129408 2004-05-18 22:52:32Z peter $ 311543Srgrimes */ 321543Srgrimes 3313107Sbde#ifndef _MACHINE_PROFILE_H_ 3413107Sbde#define _MACHINE_PROFILE_H_ 352166Spaul 3655205Speter#ifdef _KERNEL 3737542Sbde 3813157Sbde/* 3922639Sbde * Config generates something to tell the compiler to align functions on 16 4022639Sbde * byte boundaries. A strict alignment is good for keeping the tables small. 4122639Sbde */ 4222639Sbde#define FUNCTION_ALIGNMENT 16 4322639Sbde 4422639Sbde/* 4513157Sbde * The kernel uses assembler stubs instead of unportable inlines. 4613157Sbde * This is mainly to save a little time when profiling is not enabled, 4713157Sbde * which is the usual case for the kernel. 4813157Sbde */ 4913157Sbde#define _MCOUNT_DECL void mcount 5013157Sbde#define MCOUNT 511543Srgrimes 5217879Sbde#ifdef GUPROF 5317879Sbde#define CALIB_SCALE 1000 5417879Sbde#define KCOUNT(p,index) ((p)->kcount[(index) \ 5522639Sbde / (HISTFRACTION * sizeof(HISTCOUNTER))]) 5617879Sbde#define MCOUNT_DECL(s) 5717879Sbde#define MCOUNT_ENTER(s) 5817879Sbde#define MCOUNT_EXIT(s) 5937629Sbde#define PC_TO_I(p, pc) ((uintfptr_t)(pc) - (uintfptr_t)(p)->lowpc) 6017879Sbde#else 6117879Sbde#define MCOUNT_DECL(s) u_long s; 6228921Sfsmp#ifdef SMP 6390024Sbdeextern int mcount_lock; 64114349Speter#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); \ 6579734Sjhb while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \ 6678908Sjhb /* nothing */ ; } 6778908Sjhb#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \ 68114349Speter write_rflags(s); } 6928921Sfsmp#else 70114349Speter#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); } 71114349Speter#define MCOUNT_EXIT(s) (write_rflags(s)) 7228921Sfsmp#endif 7317879Sbde#endif /* GUPROF */ 7417879Sbde 7555205Speter#else /* !_KERNEL */ 7613157Sbde 7722639Sbde#define FUNCTION_ALIGNMENT 4 7822639Sbde 79129408Speter#define _MCOUNT_DECL \ 80129408Speterstatic void _mcount(uintfptr_t frompc, uintfptr_t selfpc) __unused; \ 81129408Speterstatic void _mcount 8213157Sbde 8395195Smarkm#ifdef __GNUC__ 84129408Speter#define MCOUNT __asm (" \n\ 85129408Speter .globl .mcount \n\ 86129408Speter .type .mcount @function \n\ 87129408Speter.mcount: \n\ 88129408Speter pushq %rbp \n\ 89129408Speter movq %rsp, %rbp \n\ 90129408Speter pushq %rdi \n\ 91129408Speter pushq %rsi \n\ 92129408Speter pushq %rdx \n\ 93129408Speter pushq %rcx \n\ 94129408Speter pushq %r8 \n\ 95129408Speter pushq %r9 \n\ 96129408Speter movq 8(%rbp),%rsi \n\ 97129408Speter movq (%rbp),%rdi \n\ 98129408Speter movq 8(%rdi),%rdi \n\ 99129408Speter call _mcount \n\ 100129408Speter popq %r9 \n\ 101129408Speter popq %r8 \n\ 102129408Speter popq %rcx \n\ 103129408Speter popq %rdx \n\ 104129408Speter popq %rsi \n\ 105129408Speter popq %rdi \n\ 106129408Speter leave \n\ 107129408Speter ret \n\ 108129408Speter .size .mcount, . - .mcount"); 109129408Speter#if 0 110129408Speter/* 111129408Speter * We could use this, except it doesn't preserve the registers that were 112129408Speter * being passed with arguments to the function that we were inserted 113129408Speter * into. I've left it here as documentation of what the code above is 114129408Speter * supposed to do. 115129408Speter */ 11695195Smarkm#define MCOUNT \ 11795195Smarkmvoid \ 11895195Smarkmmcount() \ 11995195Smarkm{ \ 12095195Smarkm uintfptr_t selfpc, frompc; \ 12195195Smarkm /* \ 12295195Smarkm * Find the return address for mcount, \ 12395195Smarkm * and the return address for mcount's caller. \ 12495195Smarkm * \ 12595195Smarkm * selfpc = pc pushed by call to mcount \ 12695195Smarkm */ \ 127115659Sobrien __asm("movq 8(%%rbp),%0" : "=r" (selfpc)); \ 12895195Smarkm /* \ 12995195Smarkm * frompc = pc pushed by call to mcount's caller. \ 13095195Smarkm * The caller's stack frame has already been built, so %ebp is \ 13195195Smarkm * the caller's frame pointer. The caller's raddr is in the \ 13295195Smarkm * caller's frame following the caller's caller's frame pointer.\ 13395195Smarkm */ \ 134129408Speter __asm("movq (%%rbp),%0" : "=r" (frompc)); \ 13595195Smarkm frompc = ((uintfptr_t *)frompc)[1]; \ 13695195Smarkm _mcount(frompc, selfpc); \ 1371543Srgrimes} 138129408Speter#endif 13995195Smarkm#else /* __GNUC__ */ 140103965Smarkm#define MCOUNT \ 14195195Smarkmvoid \ 14295195Smarkmmcount() \ 14395195Smarkm{ \ 14495195Smarkm} 14595195Smarkm#endif /* __GNUC__ */ 14637542Sbde 147114349Spetertypedef unsigned long uintfptr_t; 14837542Sbde 14955205Speter#endif /* _KERNEL */ 1502166Spaul 15113107Sbde/* 15213107Sbde * An unsigned integral type that can hold non-negative difference between 15313107Sbde * function pointers. 15413107Sbde */ 15531723Steggetypedef u_int fptrdiff_t; 15613107Sbde 15755205Speter#ifdef _KERNEL 15819000Sbde 15992761Salfredvoid mcount(uintfptr_t frompc, uintfptr_t selfpc); 16092761Salfredvoid kmupetext(uintfptr_t nhighpc); 16119000Sbde 16219000Sbde#ifdef GUPROF 16319000Sbdestruct gmonparam; 16419000Sbde 16592761Salfredvoid nullfunc_loop_profiled(void); 16692761Salfredvoid nullfunc_profiled(void); 16792761Salfredvoid startguprof(struct gmonparam *p); 16892761Salfredvoid stopguprof(struct gmonparam *p); 16913157Sbde#else 17019000Sbde#define startguprof(p) 17119000Sbde#define stopguprof(p) 17219000Sbde#endif /* GUPROF */ 17319000Sbde 17455205Speter#else /* !_KERNEL */ 17519000Sbde 17619000Sbde#include <sys/cdefs.h> 17719000Sbde 17819000Sbde__BEGIN_DECLS 17933047Sbde#ifdef __GNUC__ 18092761Salfredvoid mcount(void) __asm(".mcount"); 18133047Sbde#endif 18219000Sbde__END_DECLS 18313157Sbde 18455205Speter#endif /* _KERNEL */ 18519000Sbde 18613157Sbde#ifdef GUPROF 18719000Sbde/* XXX doesn't quite work outside kernel yet. */ 18819000Sbdeextern int cputime_bias; 18919000Sbde 19019000Sbde__BEGIN_DECLS 19192761Salfredint cputime(void); 19292761Salfredvoid empty_loop(void); 19392761Salfredvoid mexitcount(uintfptr_t selfpc); 19492761Salfredvoid nullfunc(void); 19592761Salfredvoid nullfunc_loop(void); 19619000Sbde__END_DECLS 19713157Sbde#endif 19813107Sbde 19913157Sbde#endif /* !_MACHINE_PROFILE_H_ */ 200