40 #include "sys/profiling.h"
41 #include "profiling_arch.h"
44 #ifdef PROFILES_CONF_MAX
45 #define MAX_PROFILES PROFILES_CONF_MAX
47 #define MAX_PROFILES 0
51 #ifdef PROFILES_CONF_STACKSIZE
52 #define PROFILE_STACKSIZE PROFILES_CONF_STACKSIZE
54 #define PROFILE_STACKSIZE 0
57 static struct profile_t profile;
58 static struct profile_site_t site[MAX_PROFILES];
59 static int fine_count;
61 static struct profile_callstack_t callstack[PROFILE_STACKSIZE]
__attribute__ ((section (".noinit")));
64 void profiling_stack_trace(
void)
67 if ((stacklevel <= 0) || (stacklevel > PROFILE_STACKSIZE)) {
68 printf(
"Stack corrupted or not recorded.\n");
72 printf(
"Stacktrace: %i frames, %lu ticks/s\n", stacklevel,
CLOCK_SECOND*256l);
74 for (i=0; i<stacklevel; i++) {
75 printf(
"%i: %p->%p @%lu\n", i, ARCHADDR2ADDR(callstack[i].caller), ARCHADDR2ADDR(callstack[i].func), callstack[i].time_start);
80 static inline void profiling_internal(uint8_t
internal)
__attribute__ ((no_instrument_function));
81 static inline
void profiling_internal(uint8_t internal)
84 profile.status |= PROFILING_INTERNAL;
86 profile.status &= ~PROFILING_INTERNAL;
89 void profiling_report(
const char *name, uint8_t pretty)
94 if (!name || strchr(name,
':') || strchr(name,
'\r') || strchr(name,
'\n')) {
95 printf(
"The profile report name is invalid\n");
100 printf(
"PROF: \"%s\" %u sites %u max sites %lu ticks spent %lu ticks/s\nfrom:to:calls:time\n", name, profile.num_sites, profile.max_sites, profile.time_run,
CLOCK_SECOND*256l);
102 printf(
"PROF:%s:%u:%u:%lu:%lu\n", name, profile.num_sites, profile.max_sites, profile.time_run,
CLOCK_SECOND*256l);
104 for(i=0; i<profile.num_sites;i++) {
105 printf(
"%p:%p:%lu:%lu:%u:%u\n", ARCHADDR2ADDR(profile.sites[i].from), ARCHADDR2ADDR(profile.sites[i].addr),
106 profile.sites[i].calls, profile.sites[i].time_accum, profile.sites[i].time_min, profile.sites[i].time_max);
111 struct profile_t *profiling_get()
116 void profiling_init(
void)
118 fine_count = clock_fine_max() + 1;
120 profile.sites = site;
121 profile.max_sites = MAX_PROFILES;
122 profile.num_sites = 0;
123 profile.time_run = 0;
128 void profiling_start(
void)
131 unsigned short now_fine;
133 if (profile.status & PROFILING_STARTED)
137 now_fine = clock_fine();
139 }
while (now_fine != clock_fine());
142 profile.time_start = ((
unsigned long)now<<8) + now_fine*256/fine_count;
143 profile.status |= PROFILING_STARTED;
149 void profiling_stop(
void)
153 unsigned short now_fine;
155 if (!profile.status & PROFILING_STARTED)
159 now_fine = clock_fine();
161 }
while (now_fine != clock_fine());
164 temp = ((
unsigned long)now<<8) + now_fine*256/fine_count;
166 profile.time_run += (temp - profile.time_start);
167 profile.status &= ~PROFILING_STARTED;
171 void __cyg_profile_func_enter(
void *,
void *)
__attribute__ ((no_instrument_function));
172 void __cyg_profile_func_exit(
void *,
void *)
__attribute__ ((no_instrument_function));
173 static inline struct profile_site_t *find_or_add_site(
void *func,
void *caller, uint8_t findonly)
__attribute__ ((no_instrument_function));
175 static inline struct profile_site_t *find_or_add_site(
void *func,
void *caller, uint8_t findonly)
177 struct profile_site_t *site =
NULL;
178 int16_t lower, upper;
179 uint16_t newindex = 0, i;
182 upper = profile.num_sites-1;
184 while (lower <= upper) {
185 newindex = ((upper - lower)>>1) + lower;
186 site = &profile.sites[newindex];
187 if (func > site->addr) {
188 lower = newindex + 1;
189 }
else if (func < site->addr) {
190 upper = newindex - 1;
192 if (caller > site->from) {
193 lower = newindex + 1;
194 }
else if (caller < site->from) {
195 upper = newindex - 1;
207 if (profile.num_sites == profile.max_sites)
212 for (i = profile.num_sites; i>newindex; i--) {
213 memcpy(&profile.sites[i], &profile.sites[i-1],
sizeof(
struct profile_site_t));
216 site = &profile.sites[newindex];
221 site->time_min = 0xFFFF;
222 site->time_accum = 0;
227 void __cyg_profile_func_enter(
void *func,
void *caller)
229 struct profile_site_t *site;
231 unsigned short now_fine;
233 if (!(profile.status&PROFILING_STARTED) || (profile.status&PROFILING_INTERNAL))
236 profiling_internal(1);
238 if (stacklevel >= PROFILE_STACKSIZE)
241 site = find_or_add_site(func, caller, 0);
247 now_fine = clock_fine();
249 }
while (now_fine != clock_fine());
251 callstack[stacklevel].time_start = ((
unsigned long)now<<8) + now_fine*256/fine_count;
252 callstack[stacklevel].func = func;
253 callstack[stacklevel].caller = caller;
258 profiling_internal(0);
261 void __cyg_profile_func_exit(
void *func,
void *caller)
264 struct profile_site_t *site;
266 unsigned short now_fine;
268 if (!(profile.status&PROFILING_STARTED) || (profile.status&PROFILING_INTERNAL))
271 profiling_internal(1);
274 now_fine = clock_fine();
276 }
while (now_fine != clock_fine());
278 temp = ((
unsigned long)now<<8) + now_fine*256/fine_count;
281 if (stacklevel > 0 && callstack[stacklevel-1].func == func &&
282 callstack[stacklevel-1].caller == caller) {
283 temp = temp - callstack[stacklevel-1].time_start;
289 site = find_or_add_site(func, caller, 1);
295 site->time_accum += temp;
298 if (temp > site->time_max) {
299 site->time_max = temp;
301 site->time_max = 0xFFFF;
303 if (temp < site->time_min)
304 site->time_min = temp;
306 profiling_internal(0);
311 profiling_internal(0);