mcount.c 5.6 KB

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