mcount.c 5.2 KB

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