mcount.c revision 1.7.2.2 1 1.7.2.2 uwe /* $NetBSD: mcount.c,v 1.7.2.2 2006/10/27 22:14:14 uwe Exp $ */
2 1.7.2.2 uwe
3 1.7.2.2 uwe /*
4 1.7.2.2 uwe * Copyright (c) 2003, 2004 Wasabi Systems, Inc.
5 1.7.2.2 uwe * All rights reserved.
6 1.7.2.2 uwe *
7 1.7.2.2 uwe * Written by Nathan J. Williams for Wasabi Systems, Inc.
8 1.7.2.2 uwe *
9 1.7.2.2 uwe * Redistribution and use in source and binary forms, with or without
10 1.7.2.2 uwe * modification, are permitted provided that the following conditions
11 1.7.2.2 uwe * are met:
12 1.7.2.2 uwe * 1. Redistributions of source code must retain the above copyright
13 1.7.2.2 uwe * notice, this list of conditions and the following disclaimer.
14 1.7.2.2 uwe * 2. Redistributions in binary form must reproduce the above copyright
15 1.7.2.2 uwe * notice, this list of conditions and the following disclaimer in the
16 1.7.2.2 uwe * documentation and/or other materials provided with the distribution.
17 1.7.2.2 uwe * 3. All advertising materials mentioning features or use of this software
18 1.7.2.2 uwe * must display the following acknowledgement:
19 1.7.2.2 uwe * This product includes software developed for the NetBSD Project by
20 1.7.2.2 uwe * Wasabi Systems, Inc.
21 1.7.2.2 uwe * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 1.7.2.2 uwe * or promote products derived from this software without specific prior
23 1.7.2.2 uwe * written permission.
24 1.7.2.2 uwe *
25 1.7.2.2 uwe * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 1.7.2.2 uwe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 1.7.2.2 uwe * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 1.7.2.2 uwe * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 1.7.2.2 uwe * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 1.7.2.2 uwe * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 1.7.2.2 uwe * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 1.7.2.2 uwe * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 1.7.2.2 uwe * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 1.7.2.2 uwe * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 1.7.2.2 uwe * POSSIBILITY OF SUCH DAMAGE.
36 1.7.2.2 uwe */
37 1.7.2.2 uwe
38 1.7.2.2 uwe /*-
39 1.7.2.2 uwe * Copyright (c) 1983, 1992, 1993
40 1.7.2.2 uwe * The Regents of the University of California. All rights reserved.
41 1.7.2.2 uwe *
42 1.7.2.2 uwe * Redistribution and use in source and binary forms, with or without
43 1.7.2.2 uwe * modification, are permitted provided that the following conditions
44 1.7.2.2 uwe * are met:
45 1.7.2.2 uwe * 1. Redistributions of source code must retain the above copyright
46 1.7.2.2 uwe * notice, this list of conditions and the following disclaimer.
47 1.7.2.2 uwe * 2. Redistributions in binary form must reproduce the above copyright
48 1.7.2.2 uwe * notice, this list of conditions and the following disclaimer in the
49 1.7.2.2 uwe * documentation and/or other materials provided with the distribution.
50 1.7.2.2 uwe * 3. Neither the name of the University nor the names of its contributors
51 1.7.2.2 uwe * may be used to endorse or promote products derived from this software
52 1.7.2.2 uwe * without specific prior written permission.
53 1.7.2.2 uwe *
54 1.7.2.2 uwe * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 1.7.2.2 uwe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 1.7.2.2 uwe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 1.7.2.2 uwe * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 1.7.2.2 uwe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 1.7.2.2 uwe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 1.7.2.2 uwe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 1.7.2.2 uwe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 1.7.2.2 uwe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 1.7.2.2 uwe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 1.7.2.2 uwe * SUCH DAMAGE.
65 1.7.2.2 uwe */
66 1.7.2.2 uwe
67 1.7.2.2 uwe /* If building a standalone libkern, don't include mcount. */
68 1.7.2.2 uwe #if (!defined(_KERNEL) || defined(GPROF)) && !defined(_STANDALONE)
69 1.7.2.2 uwe
70 1.7.2.2 uwe #ifdef _KERNEL_OPT
71 1.7.2.2 uwe #include "opt_multiprocessor.h"
72 1.7.2.2 uwe #endif
73 1.7.2.2 uwe
74 1.7.2.2 uwe #include <sys/cdefs.h>
75 1.7.2.2 uwe #if !defined(lint) && !defined(_KERNEL) && defined(LIBC_SCCS)
76 1.7.2.2 uwe #if 0
77 1.7.2.2 uwe static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
78 1.7.2.2 uwe #else
79 1.7.2.2 uwe __RCSID("$NetBSD: mcount.c,v 1.7.2.2 2006/10/27 22:14:14 uwe Exp $");
80 1.7.2.2 uwe #endif
81 1.7.2.2 uwe #endif
82 1.7.2.2 uwe
83 1.7.2.2 uwe #include <sys/param.h>
84 1.7.2.2 uwe #include <sys/gmon.h>
85 1.7.2.2 uwe
86 1.7.2.2 uwe #ifndef _KERNEL
87 1.7.2.2 uwe #include "reentrant.h"
88 1.7.2.2 uwe #endif
89 1.7.2.2 uwe
90 1.7.2.2 uwe #ifdef _REENTRANT
91 1.7.2.2 uwe extern thread_key_t _gmonkey;
92 1.7.2.2 uwe extern struct gmonparam _gmondummy;
93 1.7.2.2 uwe struct gmonparam *_m_gmon_alloc(void);
94 1.7.2.2 uwe #endif
95 1.7.2.2 uwe
96 1.7.2.2 uwe _MCOUNT_DECL __P((u_long, u_long))
97 1.7.2.2 uwe #ifdef _KERNEL
98 1.7.2.2 uwe __attribute__((__no_instrument_function__))
99 1.7.2.2 uwe #endif
100 1.7.2.2 uwe __used;
101 1.7.2.2 uwe
102 1.7.2.2 uwe /*
103 1.7.2.2 uwe * mcount is called on entry to each function compiled with the profiling
104 1.7.2.2 uwe * switch set. _mcount(), which is declared in a machine-dependent way
105 1.7.2.2 uwe * with _MCOUNT_DECL, does the actual work and is either inlined into a
106 1.7.2.2 uwe * C routine or called by an assembly stub. In any case, this magic is
107 1.7.2.2 uwe * taken care of by the MCOUNT definition in <machine/profile.h>.
108 1.7.2.2 uwe *
109 1.7.2.2 uwe * _mcount updates data structures that represent traversals of the
110 1.7.2.2 uwe * program's call graph edges. frompc and selfpc are the return
111 1.7.2.2 uwe * address and function address that represents the given call graph edge.
112 1.7.2.2 uwe *
113 1.7.2.2 uwe * Note: the original BSD code used the same variable (frompcindex) for
114 1.7.2.2 uwe * both frompcindex and frompc. Any reasonable, modern compiler will
115 1.7.2.2 uwe * perform this optimization.
116 1.7.2.2 uwe */
117 1.7.2.2 uwe _MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */
118 1.7.2.2 uwe u_long frompc, selfpc;
119 1.7.2.2 uwe {
120 1.7.2.2 uwe u_short *frompcindex;
121 1.7.2.2 uwe struct tostruct *top, *prevtop;
122 1.7.2.2 uwe struct gmonparam *p;
123 1.7.2.2 uwe long toindex;
124 1.7.2.2 uwe #ifdef _KERNEL
125 1.7.2.2 uwe int s;
126 1.7.2.2 uwe #endif
127 1.7.2.2 uwe
128 1.7.2.2 uwe #if defined(_REENTRANT) && !defined(_KERNEL)
129 1.7.2.2 uwe if (__isthreaded) {
130 1.7.2.2 uwe p = thr_getspecific(_gmonkey);
131 1.7.2.2 uwe if (p == NULL) {
132 1.7.2.2 uwe /* Prevent recursive calls while allocating */
133 1.7.2.2 uwe thr_setspecific(_gmonkey, &_gmondummy);
134 1.7.2.2 uwe p = _m_gmon_alloc();
135 1.7.2.2 uwe }
136 1.7.2.2 uwe } else
137 1.7.2.2 uwe #endif
138 1.7.2.2 uwe p = &_gmonparam;
139 1.7.2.2 uwe /*
140 1.7.2.2 uwe * check that we are profiling
141 1.7.2.2 uwe * and that we aren't recursively invoked.
142 1.7.2.2 uwe */
143 1.7.2.2 uwe if (p->state != GMON_PROF_ON)
144 1.7.2.2 uwe return;
145 1.7.2.2 uwe #ifdef _KERNEL
146 1.7.2.2 uwe MCOUNT_ENTER;
147 1.7.2.2 uwe #endif
148 1.7.2.2 uwe p->state = GMON_PROF_BUSY;
149 1.7.2.2 uwe /*
150 1.7.2.2 uwe * check that frompcindex is a reasonable pc value.
151 1.7.2.2 uwe * for example: signal catchers get called from the stack,
152 1.7.2.2 uwe * not from text space. too bad.
153 1.7.2.2 uwe */
154 1.7.2.2 uwe frompc -= p->lowpc;
155 1.7.2.2 uwe if (frompc > p->textsize)
156 1.7.2.2 uwe goto done;
157 1.7.2.2 uwe
158 1.7.2.2 uwe #if (HASHFRACTION & (HASHFRACTION - 1)) == 0
159 1.7.2.2 uwe if (p->hashfraction == HASHFRACTION)
160 1.7.2.2 uwe frompcindex =
161 1.7.2.2 uwe &p->froms[
162 1.7.2.2 uwe (size_t)(frompc / (HASHFRACTION * sizeof(*p->froms)))];
163 1.7.2.2 uwe else
164 1.7.2.2 uwe #endif
165 1.7.2.2 uwe frompcindex =
166 1.7.2.2 uwe &p->froms[
167 1.7.2.2 uwe (size_t)(frompc / (p->hashfraction * sizeof(*p->froms)))];
168 1.7.2.2 uwe toindex = *frompcindex;
169 1.7.2.2 uwe if (toindex == 0) {
170 1.7.2.2 uwe /*
171 1.7.2.2 uwe * first time traversing this arc
172 1.7.2.2 uwe */
173 1.7.2.2 uwe toindex = ++p->tos[0].link;
174 1.7.2.2 uwe if (toindex >= p->tolimit)
175 1.7.2.2 uwe /* halt further profiling */
176 1.7.2.2 uwe goto overflow;
177 1.7.2.2 uwe
178 1.7.2.2 uwe *frompcindex = (u_short)toindex;
179 1.7.2.2 uwe top = &p->tos[(size_t)toindex];
180 1.7.2.2 uwe top->selfpc = selfpc;
181 1.7.2.2 uwe top->count = 1;
182 1.7.2.2 uwe top->link = 0;
183 1.7.2.2 uwe goto done;
184 1.7.2.2 uwe }
185 1.7.2.2 uwe top = &p->tos[(size_t)toindex];
186 1.7.2.2 uwe if (top->selfpc == selfpc) {
187 1.7.2.2 uwe /*
188 1.7.2.2 uwe * arc at front of chain; usual case.
189 1.7.2.2 uwe */
190 1.7.2.2 uwe top->count++;
191 1.7.2.2 uwe goto done;
192 1.7.2.2 uwe }
193 1.7.2.2 uwe /*
194 1.7.2.2 uwe * have to go looking down chain for it.
195 1.7.2.2 uwe * top points to what we are looking at,
196 1.7.2.2 uwe * prevtop points to previous top.
197 1.7.2.2 uwe * we know it is not at the head of the chain.
198 1.7.2.2 uwe */
199 1.7.2.2 uwe for (; /* goto done */; ) {
200 1.7.2.2 uwe if (top->link == 0) {
201 1.7.2.2 uwe /*
202 1.7.2.2 uwe * top is end of the chain and none of the chain
203 1.7.2.2 uwe * had top->selfpc == selfpc.
204 1.7.2.2 uwe * so we allocate a new tostruct
205 1.7.2.2 uwe * and link it to the head of the chain.
206 1.7.2.2 uwe */
207 1.7.2.2 uwe toindex = ++p->tos[0].link;
208 1.7.2.2 uwe if (toindex >= p->tolimit)
209 1.7.2.2 uwe goto overflow;
210 1.7.2.2 uwe
211 1.7.2.2 uwe top = &p->tos[(size_t)toindex];
212 1.7.2.2 uwe top->selfpc = selfpc;
213 1.7.2.2 uwe top->count = 1;
214 1.7.2.2 uwe top->link = *frompcindex;
215 1.7.2.2 uwe *frompcindex = (u_short)toindex;
216 1.7.2.2 uwe goto done;
217 1.7.2.2 uwe }
218 1.7.2.2 uwe /*
219 1.7.2.2 uwe * otherwise, check the next arc on the chain.
220 1.7.2.2 uwe */
221 1.7.2.2 uwe prevtop = top;
222 1.7.2.2 uwe top = &p->tos[top->link];
223 1.7.2.2 uwe if (top->selfpc == selfpc) {
224 1.7.2.2 uwe /*
225 1.7.2.2 uwe * there it is.
226 1.7.2.2 uwe * increment its count
227 1.7.2.2 uwe * move it to the head of the chain.
228 1.7.2.2 uwe */
229 1.7.2.2 uwe top->count++;
230 1.7.2.2 uwe toindex = prevtop->link;
231 1.7.2.2 uwe prevtop->link = top->link;
232 1.7.2.2 uwe top->link = *frompcindex;
233 1.7.2.2 uwe *frompcindex = (u_short)toindex;
234 1.7.2.2 uwe goto done;
235 1.7.2.2 uwe }
236 1.7.2.2 uwe
237 1.7.2.2 uwe }
238 1.7.2.2 uwe done:
239 1.7.2.2 uwe p->state = GMON_PROF_ON;
240 1.7.2.2 uwe #ifdef _KERNEL
241 1.7.2.2 uwe MCOUNT_EXIT;
242 1.7.2.2 uwe #endif
243 1.7.2.2 uwe return;
244 1.7.2.2 uwe overflow:
245 1.7.2.2 uwe p->state = GMON_PROF_ERROR;
246 1.7.2.2 uwe #ifdef _KERNEL
247 1.7.2.2 uwe MCOUNT_EXIT;
248 1.7.2.2 uwe #endif
249 1.7.2.2 uwe return;
250 1.7.2.2 uwe }
251 1.7.2.2 uwe
252 1.7.2.2 uwe #ifdef MCOUNT
253 1.7.2.2 uwe /*
254 1.7.2.2 uwe * Actual definition of mcount function. Defined in <machine/profile.h>,
255 1.7.2.2 uwe * which is included by <sys/gmon.h>.
256 1.7.2.2 uwe */
257 1.7.2.2 uwe MCOUNT
258 1.7.2.2 uwe #endif
259 1.7.2.2 uwe
260 1.7.2.2 uwe #endif /* (!_KERNEL || GPROF) && !_STANDALONE */
261