Reverting merge from trunk
[official-gcc.git] / libgcc / config / arc / gmon / mcount.c
blobc99dcd7bd7e09faaeb8c4b5433b66f1c772998a8
1 /*-
2 * Copyright (c) 1983, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Copyright (C) 2007-2013 Free Software Foundation, Inc.
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 * 4. 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.
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.
32 #if !defined(lint) && !defined(KERNEL) && defined(LIBC_SCCS)
33 static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
34 #endif
36 #if 0
37 #include <unistd.h>
38 #include <sys/param.h>
39 #endif
40 #include <sys/gmon.h>
42 /* This file provides the machine-dependent definitions of the _MCOUNT_DECL
43 and MCOUNT macros. */
44 #include <machine-gmon.h>
46 #include <atomic.h>
49 * mcount is called on entry to each function compiled with the profiling
50 * switch set. _mcount(), which is declared in a machine-dependent way
51 * with _MCOUNT_DECL, does the actual work and is either inlined into a
52 * C routine or called by an assembly stub. In any case, this magic is
53 * taken care of by the MCOUNT definition in <machine/profile.h>.
55 * _mcount updates data structures that represent traversals of the
56 * program's call graph edges. frompc and selfpc are the return
57 * address and function address that represents the given call graph edge.
59 * Note: the original BSD code used the same variable (frompcindex) for
60 * both frompcindex and frompc. Any reasonable, modern compiler will
61 * perform this optimization.
63 _MCOUNT_DECL(count_ptr, selfpc) /* _mcount; may be static, inline, etc */
65 register ARCINDEX *frompcindex;
66 register struct tostruct *top, *prevtop;
67 register struct gmonparam *p;
68 register ARCINDEX toindex;
70 /* Check for nested function trampoline. */
71 if (selfpc & 2)
72 selfpc = *(u_long *) (selfpc + 10);
74 p = &_gmonparam;
76 * check that we are profiling
77 * and that we aren't recursively invoked.
79 #if 0
80 if (catomic_compare_and_exchange_bool_acq (&p->state, GMON_PROF_BUSY,
81 GMON_PROF_ON))
82 return;
83 #elif defined (__ARC700__)
84 /* ??? This could temporarily lose the ERROR / OFF condition in a race,
85 but doing an actual compare_and_exchange would be too costly. It would
86 be better if we had a semaphore independent of the 'sticky' state, but
87 then we could run into ABI compatibility problems with the size of struct
88 gmonparam. */
90 u_long old_state;
92 __asm ("ex %0,%1": "=r" (old_state), "+m" (p->state)
93 : "0" (GMON_PROF_BUSY));
94 if (old_state != GMON_PROF_ON)
96 switch (old_state)
98 case GMON_PROF_OFF:
99 __asm ("ex %0,%1": "+r" (old_state), "+m" (p->state));
100 if (old_state == GMON_PROF_BUSY
101 /* Switching off while we say we are busy while profiling
102 was actually already switched off is all right. */
103 || old_state == GMON_PROF_OFF)
104 break;
105 /* It is not clear if we should allow switching on
106 profiling at this point, and how to handle further races.
107 For now, record an error in this case. */
108 /* Fall through. */
109 default: /* We expect here only GMON_PROF_ERROR. */
110 p->state = GMON_PROF_ERROR;
111 break;
112 case GMON_PROF_BUSY: break;
114 return;
117 #else /* ??? No semaphore primitives available. */
118 if (p->state != GMON_PROF_ON)
119 return;
120 p->state = GMON_PROF_BUSY;
121 #endif
123 frompcindex = count_ptr;
124 toindex = *frompcindex;
125 if (toindex == 0) {
127 * first time traversing this arc
129 toindex = ++p->tos[0].link;
130 if (toindex >= (ARCINDEX) p->tolimit)
131 /* halt further profiling */
132 goto overflow;
134 *frompcindex = toindex;
135 top = &p->tos[toindex];
136 top->selfpc = selfpc;
137 top->count = 1;
138 top->link = 0;
139 goto done;
141 top = &p->tos[toindex];
142 if (top->selfpc == selfpc) {
144 * arc at front of chain; usual case.
146 top->count++;
147 goto done;
150 * have to go looking down chain for it.
151 * top points to what we are looking at,
152 * prevtop points to previous top.
153 * we know it is not at the head of the chain.
155 for (; /* goto done */; ) {
156 if (top->link == 0) {
158 * top is end of the chain and none of the chain
159 * had top->selfpc == selfpc.
160 * so we allocate a new tostruct
161 * and link it to the head of the chain.
163 toindex = ++p->tos[0].link;
164 if (toindex >= (ARCINDEX) p->tolimit)
165 goto overflow;
167 top = &p->tos[toindex];
168 top->selfpc = selfpc;
169 top->count = 1;
170 top->link = *frompcindex;
171 *frompcindex = toindex;
172 goto done;
175 * otherwise, check the next arc on the chain.
177 prevtop = top;
178 top = &p->tos[top->link];
179 if (top->selfpc == selfpc) {
181 * there it is.
182 * increment its count
183 * move it to the head of the chain.
185 top->count++;
186 toindex = prevtop->link;
187 prevtop->link = top->link;
188 top->link = *frompcindex;
189 *frompcindex = toindex;
190 goto done;
194 done:
195 p->state = GMON_PROF_ON;
196 return;
197 overflow:
198 p->state = GMON_PROF_ERROR;
199 return;
203 * Actual definition of mcount function. Defined in <machine/profile.h>,
204 * which is included by <sys/gmon.h>.
206 MCOUNT