Skip to content

Commit 067010f

Browse files
Cleanup continues
1 parent b0083a2 commit 067010f

File tree

1 file changed

+114
-113
lines changed

1 file changed

+114
-113
lines changed

cores/rp2040/gprof_gmon.c

Lines changed: 114 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ struct tostruct {
143143
*/
144144
struct gmonparam {
145145
int state;
146-
uint16_t *kcount; /* histogram PC sample array */
146+
uint16_t *kcount; /* histogram PC sample array */
147147
size_t kcountsize; /* size of kcount[] array in bytes */
148-
uint16_t *froms; /* array of hashed 'from' addresses. The 16bit value is an index into the tos[] array */
148+
uint16_t *froms; /* array of hashed 'from' addresses. The 16bit value is an index into the tos[] array */
149149
size_t fromssize; /* size of froms[] array in bytes */
150150
struct tostruct *tos; /* to struct, contains histogram counter */
151151
size_t tossize; /* size of tos[] array in bytes */
@@ -174,33 +174,33 @@ static struct profinfo prof = {
174174
PROFILE_NOT_INIT, 0, 0, 0, 0
175175
};
176176

177-
/* convert an addr to an index */
178-
#define PROFIDX(pc, base, scale) \
179-
({ \
180-
size_t i = (pc - base) / 2; \
181-
if (sizeof (unsigned long long int) > sizeof (size_t)) \
182-
i = (unsigned long long int) i * scale / 65536; \
183-
else \
184-
i = i / 65536 * scale + i % 65536 * scale / 65536; \
185-
i; \
186-
})
187-
188-
/* convert an index into an address */
189-
#define PROFADDR(idx, base, scale) \
190-
((base) \
191-
+ ((((unsigned long long)(idx) << 16) \
192-
/ (unsigned long long)(scale)) << 1))
193-
177+
static struct gmonparam _gmonparam = { GMON_PROF_OFF, NULL, 0, NULL, 0, NULL, 0, 0L, 0, 0, 0};
178+
static bool already_setup = false; /* flag to indicate if we need to init */
179+
static bool _perf_in_setup = false; // Are we currently trying to initialize? (avoid infinite recursion)
180+
static int s_scale = 0;
181+
#define SCALE_1_TO_1 0x10000L
182+
int __profileMemSize = 0; // Memory allocated by the profiler to store tables
183+
184+
185+
// Convert an addr to an index
186+
static inline size_t profidx(size_t pc, size_t base, size_t scale) {
187+
size_t i = (pc - base) / 2;
188+
if (sizeof (unsigned long long int) > sizeof (size_t)) {
189+
return (unsigned long long int) i * scale / 65536;
190+
} else {
191+
return i / 65536 * scale + i % 65536 * scale / 65536;
192+
}
193+
}
194194

195195
/* Sample the current program counter */
196-
void __no_inline_not_in_flash_func(_SystickHandler)(void) {
196+
static void __no_inline_not_in_flash_func(_SystickHandler)(void) {
197197
static size_t pc, idx; // Ensure in heap, not on stack
198198
extern volatile bool __otherCoreIdled;
199199

200200
if (!__otherCoreIdled && (prof.state == PROFILE_ON)) {
201201
pc = ((uint32_t*)(__builtin_frame_address(0)))[14]; /* get SP and use it to get the return address from stack */
202202
if ((pc >= prof.lowpc) && (pc < prof.highpc)) {
203-
idx = PROFIDX(pc, prof.lowpc, prof.scale);
203+
idx = profidx(pc, prof.lowpc, prof.scale);
204204
prof.counter[idx]++;
205205
}
206206
}
@@ -218,6 +218,11 @@ static int __no_inline_not_in_flash_func(profile_on)(struct profinfo *p) {
218218
return 0; /* ok */
219219
}
220220

221+
// Convert an index into an address
222+
static inline size_t profaddr(size_t idx, size_t base, size_t scale) {
223+
return base + ((((unsigned long long)(idx) << 16) / (unsigned long long)(scale)) << 1);
224+
}
225+
221226
/*
222227
start or stop profiling
223228
@@ -230,7 +235,7 @@ static int __no_inline_not_in_flash_func(profile_on)(struct profinfo *p) {
230235
a scale of 1 maps each bin to 128k address). Scale may be 1 - 65536,
231236
or zero to turn off profiling
232237
*/
233-
int __no_inline_not_in_flash_func(profile_ctl)(struct profinfo *p, char *samples, size_t size, size_t offset, uint32_t scale) {
238+
static int __no_inline_not_in_flash_func(profile_ctl)(struct profinfo *p, char *samples, size_t size, size_t offset, uint32_t scale) {
234239
size_t maxbin;
235240

236241
if (scale > 65536) {
@@ -243,7 +248,7 @@ int __no_inline_not_in_flash_func(profile_ctl)(struct profinfo *p, char *samples
243248
maxbin = size >> 1;
244249
prof.counter = (uint16_t*)samples;
245250
prof.lowpc = offset;
246-
prof.highpc = PROFADDR(maxbin, offset, scale);
251+
prof.highpc = profaddr(maxbin, offset, scale);
247252
prof.scale = scale;
248253
return profile_on(p);
249254
}
@@ -254,36 +259,13 @@ int __no_inline_not_in_flash_func(profile_ctl)(struct profinfo *p, char *samples
254259
Every SLEEPTIME interval, the user's program counter (PC) is examined:
255260
offset is subtracted and the result is multiplied by scale.
256261
The word pointed to by this address is incremented. */
257-
int __no_inline_not_in_flash_func(profil)(char *samples, size_t size, size_t offset, uint32_t scale) {
262+
static int __no_inline_not_in_flash_func(profil)(char *samples, size_t size, size_t offset, uint32_t scale) {
258263
return profile_ctl(&prof, samples, size, offset, scale);
259264
}
260265

261266

262-
// These are referenced by RP2040Support.cpp and called by the runtime init SDK
263-
#if defined(__riscv)
264-
void runtime_init_setup_profiling() {
265-
// TODO - is there an equivalent? Or do we need to build a timer IRQ here?
266-
}
267-
#else
268-
#include <hardware/exception.h>
269-
#include <hardware/structs/systick.h>
270-
void runtime_init_setup_profiling() {
271-
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
272-
systick_hw->csr = 0x7;
273-
systick_hw->rvr = (F_CPU / GMON_HZ) - 1;
274-
}
275-
#endif
276-
277-
278-
static struct gmonparam _gmonparam = { GMON_PROF_OFF, NULL, 0, NULL, 0, NULL, 0, 0L, 0, 0, 0};
279-
static char already_setup = 0; /* flag to indicate if we need to init */
280-
static int s_scale;
281-
/* see profil(2) where this is described (incorrectly) */
282-
#define SCALE_1_TO_1 0x10000L
283-
284267
static void moncontrol(int mode);
285268

286-
int __profileMemSize = 0;
287269

288270
void __no_inline_not_in_flash_func(monstartup)(size_t lowpc, size_t highpc) {
289271
register size_t o;
@@ -314,7 +296,7 @@ void __no_inline_not_in_flash_func(monstartup)(size_t lowpc, size_t highpc) {
314296
#endif
315297
if (cp == NULL) {
316298
// OOM
317-
already_setup = 0;
299+
already_setup = false;
318300
return;
319301
}
320302

@@ -339,68 +321,6 @@ void __no_inline_not_in_flash_func(monstartup)(size_t lowpc, size_t highpc) {
339321
}
340322

341323

342-
typedef int (*profileWriteCB)(const void *data, int len);
343-
void _writeProfile(profileWriteCB writeCB) {
344-
struct gmonhdr { // GMON.OUT header
345-
size_t lpc; /* base pc address of sample buffer */
346-
size_t hpc; /* max pc address of sampled buffer */
347-
int ncnt; /* size of sample buffer (plus this header) */
348-
int version; /* version number */
349-
int profrate; /* profiling clock rate */
350-
int spare[3]; /* reserved */
351-
};
352-
const unsigned int GMONVERSION = 0x00051879;
353-
struct rawarc { // Per-arc on-disk data format
354-
size_t raw_frompc;
355-
size_t raw_selfpc;
356-
long raw_count;
357-
};
358-
int fromindex;
359-
int endfrom;
360-
size_t frompc;
361-
int toindex;
362-
struct rawarc rawarc;
363-
const int BS = 64;
364-
struct rawarc rawarcbuff[BS];
365-
int rawarcbuffptr = 0;
366-
struct gmonparam *p = &_gmonparam;
367-
struct gmonhdr gmonhdr, *hdr;
368-
369-
moncontrol(0); /* stop */
370-
371-
hdr = (struct gmonhdr *)&gmonhdr;
372-
hdr->lpc = p->lowpc;
373-
hdr->hpc = p->highpc;
374-
hdr->ncnt = p->kcountsize + sizeof(gmonhdr);
375-
hdr->version = GMONVERSION;
376-
hdr->profrate = GMON_HZ;
377-
writeCB((void *)hdr, sizeof * hdr);
378-
writeCB((void *)p->kcount, p->kcountsize);
379-
endfrom = p->fromssize / sizeof(*p->froms);
380-
for (fromindex = 0; fromindex < endfrom; fromindex++) {
381-
if (p->froms[fromindex] == 0) {
382-
continue;
383-
}
384-
frompc = p->lowpc;
385-
frompc += fromindex * HASHFRACTION * sizeof(*p->froms);
386-
for (toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].link) {
387-
rawarc.raw_frompc = frompc;
388-
rawarc.raw_selfpc = GETSELFPC(&p->tos[toindex]);
389-
rawarc.raw_count = GETCOUNT(&p->tos[toindex]);
390-
// Buffer up writes because Semihosting is really slow per write call
391-
rawarcbuff[rawarcbuffptr++] = rawarc;
392-
if (rawarcbuffptr == BS) {
393-
writeCB((void *)rawarcbuff, BS * sizeof(struct rawarc));
394-
rawarcbuffptr = 0;
395-
}
396-
}
397-
}
398-
// Write any remaining bits
399-
if (rawarcbuffptr) {
400-
writeCB((void *)rawarcbuff, rawarcbuffptr * sizeof(struct rawarc));
401-
}
402-
}
403-
404324
/*
405325
Control profiling
406326
profiling is what mcount checks to see if
@@ -419,7 +339,9 @@ static void __no_inline_not_in_flash_func(moncontrol)(int mode) {
419339
p->state = GMON_PROF_OFF;
420340
}
421341
}
422-
static bool _perf_in_setup = false;
342+
343+
344+
// Called by the GCC function shim (gprof_shim.S) on function entry to record an arc hit
423345
void __no_inline_not_in_flash_func(_mcount_internal)(uint32_t *frompcindex, uint32_t *selfpc) {
424346
register struct tostruct *top;
425347
register struct tostruct *prevtop;
@@ -434,7 +356,7 @@ void __no_inline_not_in_flash_func(_mcount_internal)(uint32_t *frompcindex, uint
434356
if (!already_setup) {
435357
extern char __flash_binary_start; // Start of flash
436358
extern char __etext; /* end of text/code symbol, defined by linker */
437-
already_setup = 1;
359+
already_setup = true;
438360
_perf_in_setup = true;
439361
monstartup((uint32_t)&__flash_binary_start, (uint32_t)&__etext);
440362
_perf_in_setup = false;
@@ -546,5 +468,84 @@ void __no_inline_not_in_flash_func(_mcount_internal)(uint32_t *frompcindex, uint
546468

547469
void __no_inline_not_in_flash_func(_monInit)(void) {
548470
_gmonparam.state = GMON_PROF_OFF;
549-
already_setup = 0;
471+
already_setup = false;
472+
}
473+
474+
475+
// Write out the GMON.OUT file using internal state
476+
void _writeProfile(int (*writeCB)(const void *data, int len)) {
477+
struct gmonhdr { // GMON.OUT header
478+
size_t lpc; // base pc address of sample buffer
479+
size_t hpc; // max pc address of sampled buffer
480+
int ncnt; // size of sample buffer (plus this header)
481+
int version; // version number
482+
int profrate; // profiling clock rate
483+
int spare[3]; // reserved
484+
};
485+
const unsigned int GMONVERSION = 0x00051879;
486+
struct rawarc { // Per-arc on-disk data format
487+
size_t raw_frompc;
488+
size_t raw_selfpc;
489+
long raw_count;
490+
};
491+
int fromindex;
492+
int endfrom;
493+
size_t frompc;
494+
int toindex;
495+
struct rawarc rawarc;
496+
const int BS = 64;
497+
struct rawarc rawarcbuff[BS];
498+
int rawarcbuffptr = 0;
499+
struct gmonparam *p = &_gmonparam;
500+
struct gmonhdr hdr;
501+
502+
moncontrol(0); // Stop
503+
504+
hdr.lpc = p->lowpc;
505+
hdr.hpc = p->highpc;
506+
hdr.ncnt = p->kcountsize + sizeof(hdr);
507+
hdr.version = GMONVERSION;
508+
hdr.profrate = GMON_HZ;
509+
writeCB((void *)&hdr, sizeof(hdr));
510+
writeCB((void *)p->kcount, p->kcountsize);
511+
endfrom = p->fromssize / sizeof(*p->froms);
512+
for (fromindex = 0; fromindex < endfrom; fromindex++) {
513+
if (p->froms[fromindex] == 0) {
514+
continue;
515+
}
516+
frompc = p->lowpc;
517+
frompc += fromindex * HASHFRACTION * sizeof(*p->froms);
518+
for (toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].link) {
519+
rawarc.raw_frompc = frompc;
520+
rawarc.raw_selfpc = GETSELFPC(&p->tos[toindex]);
521+
rawarc.raw_count = GETCOUNT(&p->tos[toindex]);
522+
// Buffer up writes because Semihosting is really slow per write call
523+
rawarcbuff[rawarcbuffptr++] = rawarc;
524+
if (rawarcbuffptr == BS) {
525+
writeCB((void *)rawarcbuff, BS * sizeof(struct rawarc));
526+
rawarcbuffptr = 0;
527+
}
528+
}
529+
}
530+
// Write any remaining bits
531+
if (rawarcbuffptr) {
532+
writeCB((void *)rawarcbuff, rawarcbuffptr * sizeof(struct rawarc));
533+
}
550534
}
535+
536+
537+
// These are referenced by RP2040Support.cpp and called by the runtime init SDK
538+
// Install a periodic PC sampler at the specified frequency
539+
#if defined(__riscv)
540+
void runtime_init_setup_profiling() {
541+
// TODO - is there an equivalent? Or do we need to build a timer IRQ here?
542+
}
543+
#else
544+
#include <hardware/exception.h>
545+
#include <hardware/structs/systick.h>
546+
void runtime_init_setup_profiling() {
547+
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
548+
systick_hw->csr = 0x7;
549+
systick_hw->rvr = (F_CPU / GMON_HZ) - 1;
550+
}
551+
#endif

0 commit comments

Comments
 (0)