summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs.c4
-rw-r--r--apps/codecs/SOURCES2
-rw-r--r--apps/plugin.c4
-rw-r--r--apps/plugins/SUBDIRS4
-rw-r--r--firmware/export/profile.h4
-rw-r--r--firmware/profile.c23
-rwxr-xr-xtools/profile_reader/profile_reader.pl39
7 files changed, 52 insertions, 28 deletions
diff --git a/apps/codecs.c b/apps/codecs.c
index c31fd843b3..24490dd04b 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -138,8 +138,8 @@ struct codec_api ci = {
138#ifdef RB_PROFILE 138#ifdef RB_PROFILE
139 profile_thread, 139 profile_thread,
140 profstop, 140 profstop,
141 profile_func_enter, 141 __cyg_profile_func_enter,
142 profile_func_exit, 142 __cyg_profile_func_exit,
143#endif 143#endif
144 144
145#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 145#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 25ca5490d4..3038903f9e 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -7,7 +7,9 @@ wav.c
7a52.c 7a52.c
8mpc.c 8mpc.c
9wavpack.c 9wavpack.c
10#ifndef RB_PROFILE
10alac.c 11alac.c
12#endif
11wma.c 13wma.c
12#if MEMORYSIZE > 1 14#if MEMORYSIZE > 1
13aac.c 15aac.c
diff --git a/apps/plugin.c b/apps/plugin.c
index a220e8c429..24082de637 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -335,8 +335,8 @@ static const struct plugin_api rockbox_api = {
335#ifdef RB_PROFILE 335#ifdef RB_PROFILE
336 profile_thread, 336 profile_thread,
337 profstop, 337 profstop,
338 profile_func_enter, 338 __cyg_profile_func_enter,
339 profile_func_exit, 339 __cyg_profile_func_exit,
340#endif 340#endif
341 341
342#ifdef SIMULATOR 342#ifdef SIMULATOR
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS
index 94614e2f12..1b3e2af252 100644
--- a/apps/plugins/SUBDIRS
+++ b/apps/plugins/SUBDIRS
@@ -33,14 +33,18 @@ pacbox
33/* For all the color targets */ 33/* For all the color targets */
34#if defined(HAVE_LCD_COLOR) || defined(MROBE_100) || \ 34#if defined(HAVE_LCD_COLOR) || defined(MROBE_100) || \
35 (LCD_DEPTH == 2) && !defined(ARCHOS_AV300) 35 (LCD_DEPTH == 2) && !defined(ARCHOS_AV300)
36#ifndef RB_PROFILE
36doom 37doom
37#endif 38#endif
39#endif
38 40
39/* For all the swcodec targets */ 41/* For all the swcodec targets */
40#if CONFIG_CODEC == SWCODEC 42#if CONFIG_CODEC == SWCODEC
41midi 43midi
42/* beatbox */ 44/* beatbox */
45#ifndef RB_PROFILE
43mpegplayer 46mpegplayer
44#endif 47#endif
48#endif
45 49
46#endif /* IRIVER_IFP7XX_SERIES */ 50#endif /* IRIVER_IFP7XX_SERIES */
diff --git a/firmware/export/profile.h b/firmware/export/profile.h
index d173f4b6e0..18a6f8679f 100644
--- a/firmware/export/profile.h
+++ b/firmware/export/profile.h
@@ -39,9 +39,9 @@ void profile_thread_stopped(int current_thread)
39void profile_thread_started(int current_thread) 39void profile_thread_started(int current_thread)
40 NO_PROF_ATTR; 40 NO_PROF_ATTR;
41 41
42void profile_func_exit(void *this_fn, void *call_site) 42void __cyg_profile_func_exit(void *this_fn, void *call_site)
43 NO_PROF_ATTR ICODE_ATTR; 43 NO_PROF_ATTR ICODE_ATTR;
44void profile_func_enter(void *this_fn, void *call_site) 44void __cyg_profile_func_enter(void *this_fn, void *call_site)
45 NO_PROF_ATTR ICODE_ATTR; 45 NO_PROF_ATTR ICODE_ATTR;
46 46
47#endif /*_SYS_PROFILE_H*/ 47#endif /*_SYS_PROFILE_H*/
diff --git a/firmware/profile.c b/firmware/profile.c
index f84eebe3f1..cb68f18d8e 100644
--- a/firmware/profile.c
+++ b/firmware/profile.c
@@ -62,7 +62,6 @@
62#include <sys/types.h> 62#include <sys/types.h>
63#include "profile.h" 63#include "profile.h"
64 64
65
66/* PFD is Profiled Function Data */ 65/* PFD is Profiled Function Data */
67 66
68/* Indices are shorts which means that we use 4k of RAM */ 67/* Indices are shorts which means that we use 4k of RAM */
@@ -75,7 +74,7 @@
75 * for profiling, and allows for profiling sections of code with up-to 74 * for profiling, and allows for profiling sections of code with up-to
76 * 1024 function caller->callee pairs 75 * 1024 function caller->callee pairs
77 */ 76 */
78#define NUMPFDS 1024 77#define NUMPFDS 512
79 78
80struct pfd_struct { 79struct pfd_struct {
81 void *self_pc; 80 void *self_pc;
@@ -141,7 +140,7 @@ void profile_thread_started(int current_thread) {
141 if (profiling < PROF_ERROR) { 140 if (profiling < PROF_ERROR) {
142 /* After we de-mask, if profiling is active, reactivate the timer */ 141 /* After we de-mask, if profiling is active, reactivate the timer */
143 timer_register(0, profile_timer_unregister, 142 timer_register(0, profile_timer_unregister,
144 TIMER_FREQ/10000, 0, profile_timer_tick); 143 TIMER_FREQ/10000, 0, profile_timer_tick IF_COP(, 0 ) );
145 } 144 }
146 } 145 }
147} 146}
@@ -168,9 +167,9 @@ void profstart(int current_thread) {
168 last_pfd = (struct pfd_struct*)0; 167 last_pfd = (struct pfd_struct*)0;
169 pfds[0].link = 0; 168 pfds[0].link = 0;
170 pfds[0].self_pc = 0; 169 pfds[0].self_pc = 0;
171 memset(&indices,0,INDEX_SIZE * sizeof(unsigned short)); 170 memset(indices,0,INDEX_SIZE * sizeof(unsigned short));
172 timer_register( 171 timer_register(
173 0, profile_timer_unregister, TIMER_FREQ/10000, 0, profile_timer_tick); 172 0, profile_timer_unregister, TIMER_FREQ/10000, 0, profile_timer_tick IF_COP(, 0 ) );
174 profiling = PROF_ON; 173 profiling = PROF_ON;
175} 174}
176 175
@@ -179,7 +178,7 @@ static void write_function_recursive(int fd, struct pfd_struct *pfd, int depth){
179 fdprintf(fd,"0x%08lX\t%08ld\t%08ld\t%04d\n", (size_t)pfd->self_pc, 178 fdprintf(fd,"0x%08lX\t%08ld\t%08ld\t%04d\n", (size_t)pfd->self_pc,
180 pfd->count, pfd->time, depth); 179 pfd->count, pfd->time, depth);
181 if (link > 0 && link < NUMPFDS) { 180 if (link > 0 && link < NUMPFDS) {
182 write_function_recursive(fd, &pfds[link], depth++); 181 write_function_recursive(fd, &pfds[link], ++depth);
183 } 182 }
184} 183}
185 184
@@ -206,7 +205,7 @@ void profstop() {
206 } 205 }
207 } 206 }
208 fdprintf(fd,"DEBUG PROFILE DATA FOLLOWS\n"); 207 fdprintf(fd,"DEBUG PROFILE DATA FOLLOWS\n");
209 fdprintf(fd,"INDEX\tLOCATION\tSELF_PC\t\tCOUNT\t\tTIME\t\tLINK\tCALLER\n"); 208 fdprintf(fd,"INDEX\tLOCATION\tSELF_PC\t\tCOUNT\t\tTIME\t\tLINK\tCALLER_IDX\n");
210 for (i = 0; i < NUMPFDS; i++) { 209 for (i = 0; i < NUMPFDS; i++) {
211 struct pfd_struct *my_last_pfd = &pfds[i]; 210 struct pfd_struct *my_last_pfd = &pfds[i];
212 if (my_last_pfd->self_pc != 0) { 211 if (my_last_pfd->self_pc != 0) {
@@ -214,7 +213,7 @@ void profstop() {
214 "%04d\t0x%08lX\t0x%08lX\t0x%08lX\t0x%08lX\t%04d\t0x%08lX\n", 213 "%04d\t0x%08lX\t0x%08lX\t0x%08lX\t0x%08lX\t%04d\t0x%08lX\n",
215 i, (size_t)my_last_pfd, (size_t)my_last_pfd->self_pc, 214 i, (size_t)my_last_pfd, (size_t)my_last_pfd->self_pc,
216 my_last_pfd->count, my_last_pfd->time, my_last_pfd->link, 215 my_last_pfd->count, my_last_pfd->time, my_last_pfd->link,
217 (size_t)my_last_pfd->caller); 216 (size_t)my_last_pfd->caller );
218 } 217 }
219 } 218 }
220 fdprintf(fd,"INDEX_ADDRESS=INDEX\n"); 219 fdprintf(fd,"INDEX_ADDRESS=INDEX\n");
@@ -224,7 +223,7 @@ void profstop() {
224 close(fd); 223 close(fd);
225} 224}
226 225
227void profile_func_exit(void *self_pc, void *call_site) { 226void __cyg_profile_func_exit(void *self_pc, void *call_site) {
228 (void)call_site; 227 (void)call_site;
229 (void)self_pc; 228 (void)self_pc;
230 /* When we started timing, we set the time to the tick at that time 229 /* When we started timing, we set the time to the tick at that time
@@ -255,7 +254,7 @@ void profile_func_exit(void *self_pc, void *call_site) {
255 pfd = &pfds[temp];\ 254 pfd = &pfds[temp];\
256 pfd->self_pc = self_pc; pfd->count = 1; pfd->time = 0 255 pfd->self_pc = self_pc; pfd->count = 1; pfd->time = 0
257 256
258void profile_func_enter(void *self_pc, void *from_pc) { 257void __cyg_profile_func_enter(void *self_pc, void *from_pc) {
259 struct pfd_struct *pfd; 258 struct pfd_struct *pfd;
260 struct pfd_struct *prev_pfd; 259 struct pfd_struct *prev_pfd;
261 unsigned short *pfd_index_pointer; 260 unsigned short *pfd_index_pointer;
@@ -339,3 +338,7 @@ overflow:
339 profiling = PROF_ERROR; 338 profiling = PROF_ERROR;
340 return; 339 return;
341} 340}
341
342
343
344
diff --git a/tools/profile_reader/profile_reader.pl b/tools/profile_reader/profile_reader.pl
index 6a45ddef02..ca40a901d8 100755
--- a/tools/profile_reader/profile_reader.pl
+++ b/tools/profile_reader/profile_reader.pl
@@ -36,11 +36,11 @@ sub read_map {
36 return %retval; 36 return %retval;
37} 37}
38 38
39# string (filename.[ao]), hash(string:number) 39# string (filename.(a|o|elf)), hash(number:string), string(objdump_tool)
40# return hash(number:string) 40# return hash(number:string)
41sub read_library { 41sub read_library {
42 open(OBJECT_FILE,"objdump -t $_[0] |") || 42 open(OBJECT_FILE,"$_[2] -t $_[0] |") ||
43 error("Couldn't pipe objdump for $_[0]"); 43 error("Couldn't pipe objdump for $_[0]\nCommand was: $_[2] -t $_[0]");
44 my $library = $_[1]; 44 my $library = $_[1];
45 my %library = %$library; 45 my %library = %$library;
46 my %retval; 46 my %retval;
@@ -62,7 +62,7 @@ sub read_library {
62 if ($parts[3] eq $parts[5]) { 62 if ($parts[3] eq $parts[5]) {
63 next; 63 next;
64 } 64 }
65 if ($parts[3] =~ m/\.(text|data|rodata|bss|icode|idata|irodata|ibss)/) { 65 if ($parts[3] =~ m/\.(text|data|rodata|bss|icode|idata|irodata|ibss|iram)/) {
66 my $region = $parts[3]; 66 my $region = $parts[3];
67 my $symbolOffset = hex("0x" . $parts[0]); 67 my $symbolOffset = hex("0x" . $parts[0]);
68 my $sectionOffset = hex($library{$object . $region}); 68 my $sectionOffset = hex($library{$object . $region});
@@ -139,8 +139,16 @@ sub print_sorted {
139 my $totalCalls = 0; 139 my $totalCalls = 0;
140 my $totalTicks = 0; 140 my $totalTicks = 0;
141 $pfds = 0; 141 $pfds = 0;
142
143 # we use a key sort, which means numerical fields need to be
144 # numerically sortable by an alphanumeric sort - we can simply
145 # do this by giving the numeric keys trailing zeros. Note that
146 # simple string concatenation (what this used to do) would not do this
142 foreach $element(@pfds) { 147 foreach $element(@pfds) {
143 $elements{@$element[$sort_index] . @$element[2]} = $element; 148 $ne = $element;
149 @$ne[0] = sprintf( "%08d", @$element[0]);
150 @$ne[1] = sprintf( "%08d", @$element[1]);
151 $elements{@$ne[$sort_index] . @$element[2]} = $element;
144 $pfds++; 152 $pfds++;
145 $totalCalls += @$element[0]; 153 $totalCalls += @$element[0];
146 $totalTicks += @$element[1]; 154 $totalTicks += @$element[1];
@@ -174,13 +182,17 @@ sub usage {
174 print STDERR ("Error: @_\n"); 182 print STDERR ("Error: @_\n");
175 } 183 }
176 print STDERR ("USAGE:\n"); 184 print STDERR ("USAGE:\n");
177 print STDERR ("$0 profile.out map obj[...] [map obj[...]...] sort[...]\n"); 185 print STDERR ("$0 profile.out objdump_tool map obj[...] [map obj[...]...] sort[...]\n");
178 print STDERR 186 print STDERR
179 ("\tprofile.out output from the profiler, extension is .out\n"); 187 ("\tprofile.out output from the profiler, extension is .out\n");
188 print STDERR
189 ("\tobjdump_tool name of objdump executable for this platform\n");
190 print STDERR
191 ("\t e.g. arm-elf-objdump\n");
180 print STDERR 192 print STDERR
181 ("\tmap map file, extension is .map\n"); 193 ("\tmap map file, extension is .map\n");
182 print STDERR 194 print STDERR
183 ("\tobj library or object file, extension is .a or .o\n"); 195 ("\tobj library or object file, extension is .a or .o or .elf\n");
184 print STDERR 196 print STDERR
185 ("\tformat 0-2[_p] 0: by calls, 1: by ticks, 2: by name\n"); 197 ("\tformat 0-2[_p] 0: by calls, 1: by ticks, 2: by name\n");
186 print STDERR 198 print STDERR
@@ -195,13 +207,13 @@ sub usage {
195if ($ARGV[0] =~ m/-(h|help|-help)/) { 207if ($ARGV[0] =~ m/-(h|help|-help)/) {
196 usage(); 208 usage();
197} 209}
198if (@ARGV < 2) { 210if (@ARGV < 3) {
199 usage("Requires at least 2 arguments"); 211 usage("Requires at least 3 arguments");
200} 212}
201if ($ARGV[0] !~ m/\.out$/) { 213if ($ARGV[0] !~ m/\.out$/) {
202 usage("Profile file must end in .out"); 214 usage("Profile file must end in .out");
203} 215}
204my $i = 1; 216my $i = 2;
205my %symbols; 217my %symbols;
206{ 218{
207 my %map; 219 my %map;
@@ -209,12 +221,12 @@ my %symbols;
209 my $file = $ARGV[$i]; 221 my $file = $ARGV[$i];
210 if ($file =~ m/\.map$/) { 222 if ($file =~ m/\.map$/) {
211 %map = read_map($file); 223 %map = read_map($file);
212 } elsif ($file =~ m/\.[ao]$/) { 224 } elsif ($file =~ m/\.(a|o|elf)$/) {
213 if (!%map) { 225 if (!%map) {
214 usage("No map file found before first object file"); 226 usage("No map file found before first object file");
215 } 227 }
216 my @parts = split(/\//,$file); 228 my @parts = split(/\//,$file);
217 my %new_symbols = read_library($file,$map{$parts[$#parts]}); 229 my %new_symbols = read_library($file,$map{$parts[$#parts]},$ARGV[1]);
218 %symbols = merge_hashes(\%symbols,\%new_symbols); 230 %symbols = merge_hashes(\%symbols,\%new_symbols);
219 } else { 231 } else {
220 last; 232 last;
@@ -224,6 +236,9 @@ my %symbols;
224if (!%symbols) { 236if (!%symbols) {
225 warning("No symbols found"); 237 warning("No symbols found");
226} 238}
239if ($i >= @ARGV) {
240 error("You forgot to specify any sort ordering on output (e.g. 0, 1_p, 2)");
241}
227my @pfds = create_list($ARGV[0],\%symbols); 242my @pfds = create_list($ARGV[0],\%symbols);
228for (; $i < @ARGV; $i++) { 243for (; $i < @ARGV; $i++) {
229 print_sorted(\@pfds,split("_",$ARGV[$i])); 244 print_sorted(\@pfds,split("_",$ARGV[$i]));