Annotation of sys/lib/libkern/mcount.c, Revision 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