Annotation of sys/lib/libkern/mcount.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mcount.c,v 1.8 2004/08/07 00:38:32 deraadt Exp $ */
2: /* $NetBSD: mcount.c,v 1.3.6.1 1996/06/12 04:23:01 cgd Exp $ */
3:
4: /*-
5: * Copyright (c) 1983, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #if !defined(lint) && !defined(_KERNEL) && defined(LIBC_SCCS)
34: #if 0
35: static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
36: #else
37: static char rcsid[] = "$OpenBSD: mcount.c,v 1.8 2004/08/07 00:38:32 deraadt Exp $";
38: #endif
39: #endif
40:
41: #include <sys/param.h>
42: #include <sys/gmon.h>
43:
44: /*
45: * mcount is called on entry to each function compiled with the profiling
46: * switch set. _mcount(), which is declared in a machine-dependent way
47: * with _MCOUNT_DECL, does the actual work and is either inlined into a
48: * C routine or called by an assembly stub. In any case, this magic is
49: * taken care of by the MCOUNT definition in <machine/profile.h>.
50: *
51: * _mcount updates data structures that represent traversals of the
52: * program's call graph edges. frompc and selfpc are the return
53: * address and function address that represents the given call graph edge.
54: *
55: * Note: the original BSD code used the same variable (frompcindex) for
56: * both frompcindex and frompc. Any reasonable, modern compiler will
57: * perform this optimization.
58: *
59: * XXX - the unused attribute is there because some archs define _mcount
60: * as static and gcc doesn't check for function calls in assembler
61: * stubs.
62: */
63: _MCOUNT_DECL(u_long frompc, u_long selfpc) __attribute__((unused));
64: _MCOUNT_DECL(u_long frompc, u_long selfpc) /* _mcount; may be static, inline, etc */
65: {
66: u_short *frompcindex;
67: struct tostruct *top, *prevtop;
68: struct gmonparam *p;
69: long toindex;
70: #ifdef _KERNEL
71: int s;
72: #endif
73:
74: p = &_gmonparam;
75: /*
76: * check that we are profiling
77: * and that we aren't recursively invoked.
78: */
79: if (p->state != GMON_PROF_ON)
80: return;
81: #ifdef _KERNEL
82: MCOUNT_ENTER;
83: #else
84: p->state = GMON_PROF_BUSY;
85: #endif
86: /*
87: * check that frompcindex is a reasonable pc value.
88: * for example: signal catchers get called from the stack,
89: * not from text space. too bad.
90: */
91: frompc -= p->lowpc;
92: if (frompc > p->textsize)
93: goto done;
94:
95: #if (HASHFRACTION & (HASHFRACTION - 1)) == 0
96: if (p->hashfraction == HASHFRACTION)
97: frompcindex =
98: &p->froms[frompc / (HASHFRACTION * sizeof(*p->froms))];
99: else
100: #endif
101: frompcindex =
102: &p->froms[frompc / (p->hashfraction * sizeof(*p->froms))];
103: toindex = *frompcindex;
104: if (toindex == 0) {
105: /*
106: * first time traversing this arc
107: */
108: toindex = ++p->tos[0].link;
109: if (toindex >= p->tolimit)
110: /* halt further profiling */
111: goto overflow;
112:
113: *frompcindex = toindex;
114: top = &p->tos[toindex];
115: top->selfpc = selfpc;
116: top->count = 1;
117: top->link = 0;
118: goto done;
119: }
120: top = &p->tos[toindex];
121: if (top->selfpc == selfpc) {
122: /*
123: * arc at front of chain; usual case.
124: */
125: top->count++;
126: goto done;
127: }
128: /*
129: * have to go looking down chain for it.
130: * top points to what we are looking at,
131: * prevtop points to previous top.
132: * we know it is not at the head of the chain.
133: */
134: for (; /* goto done */; ) {
135: if (top->link == 0) {
136: /*
137: * top is end of the chain and none of the chain
138: * had top->selfpc == selfpc.
139: * so we allocate a new tostruct
140: * and link it to the head of the chain.
141: */
142: toindex = ++p->tos[0].link;
143: if (toindex >= p->tolimit)
144: goto overflow;
145:
146: top = &p->tos[toindex];
147: top->selfpc = selfpc;
148: top->count = 1;
149: top->link = *frompcindex;
150: *frompcindex = toindex;
151: goto done;
152: }
153: /*
154: * otherwise, check the next arc on the chain.
155: */
156: prevtop = top;
157: top = &p->tos[top->link];
158: if (top->selfpc == selfpc) {
159: /*
160: * there it is.
161: * increment its count
162: * move it to the head of the chain.
163: */
164: top->count++;
165: toindex = prevtop->link;
166: prevtop->link = top->link;
167: top->link = *frompcindex;
168: *frompcindex = toindex;
169: goto done;
170: }
171:
172: }
173: done:
174: #ifdef _KERNEL
175: MCOUNT_EXIT;
176: #else
177: p->state = GMON_PROF_ON;
178: #endif
179: return;
180: overflow:
181: p->state = GMON_PROF_ERROR;
182: #ifdef _KERNEL
183: MCOUNT_EXIT;
184: #endif
185: return;
186: }
187:
188: /*
189: * Actual definition of mcount function. Defined in <machine/profile.h>,
190: * which is included by <sys/gmon.h>.
191: */
192: MCOUNT
CVSweb