"Fossies" - the Fresh Open Source Software Archive 
Member "FunctionCheck-3.2.0/src/fcmanager/fc_functions.c" (26 May 2012, 6916 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * FunctionCheck profiler
3 * (C) Copyright 2000-2012 Yannick Perret
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /** fc_functions.c: treat enter/exit actions during profile **/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <limits.h>
24 #include "fc_global.h"
25 #include "fc_com_manager.h"
26 #include "fc_functions.h"
27 #include "fc_context.h"
28 #include "fc_hash.h"
29 #include "fc_tools.h"
30
31 #ifndef LLONG_MAX
32 #define LLONG_MAX 9223372036854775807LL
33 #endif // LLONG_MAX
34
35 /* initialize a function (pre-allocated) */
36 void fc_functions_init(FC_Function *fnc)
37 {
38 fnc->symbol = NULL;
39 fnc->calls = 0;
40 fnc->local_time = fnc->total_time = 0;
41 fnc->recursive_state = 0;
42 fnc->min_time = (LLONG_MAX * 2ULL + 1);
43 fnc->max_time = 0;
44 fnc->min_ltime = (LLONG_MAX * 2ULL + 1);
45 fnc->max_ltime = 0;
46 fnc->temp_ltime = 0;
47 }
48
49 /* treat entering in a function */
50 void fc_functions_enter(void *fnc, void *call_site, unsigned long long time)
51 {
52 FC_Function tmp;
53 FC_Function *func, *pfunc;
54 unsigned long long ptime;
55
56 /* 1st check if the function exists */
57 if (fnc == NULL)
58 func = NULL;
59 else
60 func = fc_fhash_find(fc_current_context->functions, fnc);
61
62 if (func == NULL)
63 {
64 /* if not create one and insert it in the table */
65 fc_debug("enter: creating function %p", fnc);
66 tmp.symbol = fnc;
67 tmp.calls = 0;
68 tmp.local_time = 0;
69 tmp.max_time = 0;
70 tmp.min_time = (LLONG_MAX * 2ULL + 1);
71 tmp.min_ltime = (LLONG_MAX * 2ULL + 1);
72 tmp.max_ltime = 0;
73 tmp.total_time = 0;
74 tmp.recursive_state = 0;
75 if (fnc == NULL)
76 tmp.faked = 1;
77 else
78 tmp.faked = 0;
79 func = fc_fhash_insert(fc_current_context->functions, &tmp);
80 }
81 else
82 /* debug */
83 fc_debug("enter: finding function %p", fnc);
84
85 /* clear temporary local time */
86 if (func->recursive_state == 0)
87 func->temp_ltime = 0;
88
89 /* do not change the order of these instructions */
90
91 /* insert function in the stack */
92 fc_stack_push(fc_current_context->stack, func, time, call_site);
93
94 /* if we have a parent, compute local time for the parent */
95 if (fc_stack_size(fc_current_context->stack) > 1)
96 {
97 fc_stack_getp(fc_current_context->stack, &pfunc, &ptime);
98 fc_debug("enter: prev. func=%p. adding %u to local", pfunc->symbol, time - pfunc->last_time);
99 /* add the local time */
100 pfunc->temp_ltime += time - pfunc->last_time;
101 }
102
103 /* set changes */
104 func->recursive_state++;
105 func->calls++;
106 func->last_time = time; /* last active time */
107 fc_debug("enter: now: rec=%d, calls=%d, last=%u",
108 func->recursive_state, func->calls, func->last_time);
109 }
110
111 /* treat exiting a function */
112 void fc_functions_exit(void *fnc, void *call_site, unsigned long long time)
113 {
114 FC_Function *func;
115 unsigned long long delta, ftime;
116 FC_Function *pfunc;
117 unsigned long long ptime;
118 void *nuse;
119
120 /* 1st, check if the top of the stack correspond to this function */
121 fc_stack_get(fc_current_context->stack, &func, &ftime, &nuse);
122 if (func == NULL) /* empty stack! */
123 {
124 fc_message("exit from function %p but stack is empty! ignored.", fnc);
125 fc_message(" this may means that your program uses fork or");
126 fc_message(" threads in SINGLE mode or that you are in FORK");
127 fc_message(" mode with more than 16 exits after a fork()");
128 return;
129 }
130
131 if ((func->symbol != fnc) && (func->symbol != NULL))
132 {
133 /* special: if it is a faked function, we now get it's
134 real symbol address. set it and remove 'fake' flag */
135 if (func->faked)
136 {
137 fc_debug("exit from faked %p. now %p.", func->symbol, fnc);
138 func->symbol = fnc;
139 func->faked = 0;
140 }
141 else /* really a bug! */
142 {
143 fc_message("exit from function %p but top of the stack is about function %p! Ignored.", fnc, func->symbol);
144 return;
145 }
146 }
147
148 if (func->symbol == NULL)
149 {
150 /* this function is here to allow exit from functions
151 after a fork in the child context (these functions
152 cannot be known before the exit time) */
153 /* set the symbol, even if it is not exactly the good one */
154 func->symbol = fnc;
155 if (fc_stack_size(fc_current_context->stack) > 1)
156 {
157 fc_stack_getp(fc_current_context->stack, &pfunc, &ptime);
158 pfunc->symbol = call_site;
159 }
160 }
161
162 /** treat the function **/
163
164 /* compute elapsed time */
165 delta = time - ftime;
166 fc_debug("exit: from %p (delta=%u)", func->symbol, delta);
167
168 /* this function may have local time to treat */
169 func->temp_ltime += time - func->last_time;
170
171 if (func->recursive_state <= 1)
172 func->local_time += func->temp_ltime;
173
174 /* min/max local time */
175 if (func->temp_ltime > func->max_ltime)
176 func->max_ltime = func->temp_ltime;
177 if (func->temp_ltime < func->min_ltime)
178 func->min_ltime = func->temp_ltime;
179
180 /* if exist, re-set the last active time */
181 if (fc_stack_size(fc_current_context->stack) > 1)
182 {
183 fc_stack_getp(fc_current_context->stack, &pfunc, &ptime);
184 /* re-set last time */
185 fc_debug("exit: re-set last time of %p", pfunc->symbol);
186 pfunc->last_time = time;
187 }
188
189 /* treat MIN/MAX */
190 if (delta > func->max_time)
191 func->max_time = delta;
192 if (delta < func->min_time)
193 func->min_time = delta;
194
195 /* if not a recursive function */
196 /* NOTE: recursive functions MUST NOT be treated here.
197 else, a 1s fnc calling itself 4 times will have a total
198 time of 4+3+2+1=10s. it would generate erroneous total
199 execution time as a total a 4s is really spend in this
200 part of the call-tree */
201 if (func->recursive_state <= 1)
202 {
203 /* add total time */
204 fc_debug("exit: non recursive. adding total");
205 func->total_time += delta;
206 }
207
208 /* update the state of the function */
209 func->recursive_state--;
210
211 /* remove the function from the stack */
212 fc_stack_pop(fc_current_context->stack);
213 }
214
215