profile.h revision 114349
1250661Sdavidcs/*
2250661Sdavidcs * Copyright (c) 1992, 1993
3250661Sdavidcs *	The Regents of the University of California.  All rights reserved.
4250661Sdavidcs *
5250661Sdavidcs * Redistribution and use in source and binary forms, with or without
6250661Sdavidcs * modification, are permitted provided that the following conditions
7250661Sdavidcs * are met:
8250661Sdavidcs * 1. Redistributions of source code must retain the above copyright
9250661Sdavidcs *    notice, this list of conditions and the following disclaimer.
10250661Sdavidcs * 2. Redistributions in binary form must reproduce the above copyright
11250661Sdavidcs *    notice, this list of conditions and the following disclaimer in the
12250661Sdavidcs *    documentation and/or other materials provided with the distribution.
13250661Sdavidcs * 3. All advertising materials mentioning features or use of this software
14250661Sdavidcs *    must display the following acknowledgement:
15250661Sdavidcs *	This product includes software developed by the University of
16250661Sdavidcs *	California, Berkeley and its contributors.
17250661Sdavidcs * 4. Neither the name of the University nor the names of its contributors
18250661Sdavidcs *    may be used to endorse or promote products derived from this software
19250661Sdavidcs *    without specific prior written permission.
20250661Sdavidcs *
21250661Sdavidcs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22250661Sdavidcs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23250661Sdavidcs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24250661Sdavidcs * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25250661Sdavidcs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26250661Sdavidcs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27250661Sdavidcs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28250661Sdavidcs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29250661Sdavidcs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30250661Sdavidcs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31250661Sdavidcs * SUCH DAMAGE.
32250661Sdavidcs *
33250661Sdavidcs *	@(#)profile.h	8.1 (Berkeley) 6/11/93
34250661Sdavidcs * $FreeBSD: head/sys/amd64/include/profile.h 114349 2003-05-01 01:05:25Z peter $
35250661Sdavidcs */
36250661Sdavidcs
37250661Sdavidcs#ifndef _MACHINE_PROFILE_H_
38250661Sdavidcs#define	_MACHINE_PROFILE_H_
39250661Sdavidcs
40250661Sdavidcs#ifdef _KERNEL
41250661Sdavidcs
42250661Sdavidcs/*
43250661Sdavidcs * Config generates something to tell the compiler to align functions on 16
44250661Sdavidcs * byte boundaries.  A strict alignment is good for keeping the tables small.
45250661Sdavidcs */
46250661Sdavidcs#define	FUNCTION_ALIGNMENT	16
47250661Sdavidcs
48250661Sdavidcs/*
49250661Sdavidcs * The kernel uses assembler stubs instead of unportable inlines.
50250661Sdavidcs * This is mainly to save a little time when profiling is not enabled,
51250661Sdavidcs * which is the usual case for the kernel.
52250661Sdavidcs */
53250661Sdavidcs#define	_MCOUNT_DECL void mcount
54250661Sdavidcs#define	MCOUNT
55250661Sdavidcs
56250661Sdavidcs#ifdef GUPROF
57250661Sdavidcs#define	CALIB_SCALE	1000
58250661Sdavidcs#define	KCOUNT(p,index)	((p)->kcount[(index) \
59250661Sdavidcs			 / (HISTFRACTION * sizeof(HISTCOUNTER))])
60250661Sdavidcs#define	MCOUNT_DECL(s)
61250661Sdavidcs#define	MCOUNT_ENTER(s)
62250661Sdavidcs#define	MCOUNT_EXIT(s)
63250661Sdavidcs#define	PC_TO_I(p, pc)	((uintfptr_t)(pc) - (uintfptr_t)(p)->lowpc)
64250661Sdavidcs#else
65250661Sdavidcs#define	MCOUNT_DECL(s)	u_long s;
66250661Sdavidcs#ifdef SMP
67250661Sdavidcsextern int	mcount_lock;
68250661Sdavidcs#define	MCOUNT_ENTER(s)	{ s = read_rflags(); disable_intr(); \
69250661Sdavidcs 			  while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \
70250661Sdavidcs			  	/* nothing */ ; }
71250661Sdavidcs#define	MCOUNT_EXIT(s)	{ atomic_store_rel_int(&mcount_lock, 0); \
72250661Sdavidcs			  write_rflags(s); }
73250661Sdavidcs#else
74250661Sdavidcs#define	MCOUNT_ENTER(s)	{ s = read_rflags(); disable_intr(); }
75250661Sdavidcs#define	MCOUNT_EXIT(s)	(write_rflags(s))
76250661Sdavidcs#endif
77250661Sdavidcs#endif /* GUPROF */
78250661Sdavidcs
79250661Sdavidcs#else /* !_KERNEL */
80250661Sdavidcs
81250661Sdavidcs#define	FUNCTION_ALIGNMENT	4
82250661Sdavidcs
83250661Sdavidcs#define	_MCOUNT_DECL static __inline void _mcount
84250661Sdavidcs
85250661Sdavidcs#ifdef	__GNUC__
86250661Sdavidcs#define	MCOUNT								\
87250661Sdavidcsvoid									\
88250661Sdavidcsmcount()								\
89250661Sdavidcs{									\
90250661Sdavidcs	uintfptr_t selfpc, frompc;					\
91250661Sdavidcs	/*								\
92250661Sdavidcs	 * Find the return address for mcount,				\
93250661Sdavidcs	 * and the return address for mcount's caller.			\
94250661Sdavidcs	 *								\
95250661Sdavidcs	 * selfpc = pc pushed by call to mcount				\
96250661Sdavidcs	 */								\
97250661Sdavidcs	asm("movq 8(%%rbp),%0" : "=r" (selfpc));			\
98250661Sdavidcs	/*								\
99250661Sdavidcs	 * frompc = pc pushed by call to mcount's caller.		\
100250661Sdavidcs	 * The caller's stack frame has already been built, so %ebp is	\
101250661Sdavidcs	 * the caller's frame pointer.  The caller's raddr is in the	\
102250661Sdavidcs	 * caller's frame following the caller's caller's frame pointer.\
103250661Sdavidcs	 */								\
104250661Sdavidcs	asm("movq (%%rbp),%0" : "=r" (frompc));				\
105250661Sdavidcs	frompc = ((uintfptr_t *)frompc)[1];				\
106250661Sdavidcs	_mcount(frompc, selfpc);					\
107250661Sdavidcs}
108250661Sdavidcs#else	/* __GNUC__ */
109250661Sdavidcs#define	MCOUNT		\
110250661Sdavidcsvoid			\
111250661Sdavidcsmcount()		\
112250661Sdavidcs{			\
113250661Sdavidcs}
114250661Sdavidcs#endif	/* __GNUC__ */
115250661Sdavidcs
116250661Sdavidcstypedef	unsigned long	uintfptr_t;
117250661Sdavidcs
118250661Sdavidcs#endif /* _KERNEL */
119250661Sdavidcs
120250661Sdavidcs/*
121250661Sdavidcs * An unsigned integral type that can hold non-negative difference between
122250661Sdavidcs * function pointers.
123250661Sdavidcs */
124250661Sdavidcstypedef	u_int	fptrdiff_t;
125250661Sdavidcs
126250661Sdavidcs#ifdef _KERNEL
127250661Sdavidcs
128250661Sdavidcsvoid	mcount(uintfptr_t frompc, uintfptr_t selfpc);
129250661Sdavidcsvoid	kmupetext(uintfptr_t nhighpc);
130250661Sdavidcs
131250661Sdavidcs#ifdef GUPROF
132250661Sdavidcsstruct gmonparam;
133250661Sdavidcs
134250661Sdavidcsvoid	nullfunc_loop_profiled(void);
135250661Sdavidcsvoid	nullfunc_profiled(void);
136250661Sdavidcsvoid	startguprof(struct gmonparam *p);
137250661Sdavidcsvoid	stopguprof(struct gmonparam *p);
138250661Sdavidcs#else
139250661Sdavidcs#define	startguprof(p)
140250661Sdavidcs#define	stopguprof(p)
141250661Sdavidcs#endif /* GUPROF */
142250661Sdavidcs
143250661Sdavidcs#else /* !_KERNEL */
144250661Sdavidcs
145250661Sdavidcs#include <sys/cdefs.h>
146250661Sdavidcs
147250661Sdavidcs__BEGIN_DECLS
148250661Sdavidcs#ifdef __GNUC__
149250661Sdavidcsvoid	mcount(void) __asm(".mcount");
150250661Sdavidcs#endif
151250661Sdavidcsstatic void	_mcount(uintfptr_t frompc, uintfptr_t selfpc);
152250661Sdavidcs__END_DECLS
153250661Sdavidcs
154250661Sdavidcs#endif /* _KERNEL */
155250661Sdavidcs
156250661Sdavidcs#ifdef GUPROF
157250661Sdavidcs/* XXX doesn't quite work outside kernel yet. */
158250661Sdavidcsextern int	cputime_bias;
159250661Sdavidcs
160250661Sdavidcs__BEGIN_DECLS
161250661Sdavidcsint	cputime(void);
162250661Sdavidcsvoid	empty_loop(void);
163250661Sdavidcsvoid	mexitcount(uintfptr_t selfpc);
164250661Sdavidcsvoid	nullfunc(void);
165250661Sdavidcsvoid	nullfunc_loop(void);
166250661Sdavidcs__END_DECLS
167250661Sdavidcs#endif
168250661Sdavidcs
169250661Sdavidcs#endif /* !_MACHINE_PROFILE_H_ */
170250661Sdavidcs