Allowing custom profiling sessions

This commit is contained in:
Francisco Javier Trujillo Mata
2024-08-24 14:30:02 +02:00
parent ef6309ed44
commit a033c3ad4e
3 changed files with 97 additions and 23 deletions

View File

@@ -11,7 +11,7 @@ CFLAGS = @PSPSDK_CFLAGS@ -std=gnu99 -Wall -Wmissing-prototypes
CCASFLAGS = $(CFLAGS) -I$(top_srcdir)/src/base -I$(top_srcdir)/src/kernel CCASFLAGS = $(CFLAGS) -I$(top_srcdir)/src/base -I$(top_srcdir)/src/kernel
libpspprofincludedir = @PSPSDK_INCLUDEDIR@ libpspprofincludedir = @PSPSDK_INCLUDEDIR@
libpspprofinclude_HEADERS = libpspprofinclude_HEADERS = pspprof.h
lib_LIBRARIES = libpspprof.a lib_LIBRARIES = libpspprof.a
libpspprof_a_SOURCES = prof.c mcount.s libpspprof_a_SOURCES = prof.c mcount.s

View File

@@ -13,6 +13,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <pspprof.h>
#define GMON_PROF_ON 0 #define GMON_PROF_ON 0
#define GMON_PROF_BUSY 1 #define GMON_PROF_BUSY 1
#define GMON_PROF_ERROR 2 #define GMON_PROF_ERROR 2
@@ -126,6 +128,15 @@ static void initialize()
memset((void *)gp.samples, '\0', gp.nsamples * (sizeof(unsigned int ))); memset((void *)gp.samples, '\0', gp.nsamples * (sizeof(unsigned int )));
gp.timer = sceKernelCreateVTimer("gprof timer", NULL); gp.timer = sceKernelCreateVTimer("gprof timer", NULL);
if (gp.timer < 0)
{
free(gp.arcs);
free(gp.samples);
gp.arcs = 0;
gp.samples = 0;
gp.state = GMON_PROF_ERROR;
return;
}
SceKernelSysClock sc; SceKernelSysClock sc;
sc.hi = 0; sc.hi = 0;
@@ -155,13 +166,17 @@ static void initialize()
} }
} }
/** Writes gmon.out dump file and stops profiling
Called from atexit() handler; will dump out a host:gmon.out file
with all collected information.
*/
__attribute__((__no_instrument_function__, __no_profile_instrument_function__)) __attribute__((__no_instrument_function__, __no_profile_instrument_function__))
void __gprof_cleanup() void gprof_start(void) {
// There is already a profiling session running, let's stop it and ignore the result
if (gp.state == GMON_PROF_ON) {
gprof_stop(NULL, 0);
}
initialize();
}
__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
void gprof_stop(const char* filename, int should_dump)
{ {
FILE *fp; FILE *fp;
int i; int i;
@@ -176,29 +191,47 @@ void __gprof_cleanup()
/* disable profiling before we make plenty of libc calls */ /* disable profiling before we make plenty of libc calls */
gp.state = GMON_PROF_OFF; gp.state = GMON_PROF_OFF;
// Delete timer
sceKernelStopVTimer(gp.timer); sceKernelStopVTimer(gp.timer);
sceKernelDeleteVTimer(gp.timer);
fp = fopen("gmon.out", "wb"); if (should_dump) {
hdr.lpc = gp.lowpc; fp = fopen(filename, "wb");
hdr.hpc = gp.highpc; hdr.lpc = gp.lowpc;
hdr.ncnt = sizeof(hdr) + (sizeof(unsigned int) * gp.nsamples); hdr.hpc = gp.highpc;
hdr.version = GMONVERSION; hdr.ncnt = sizeof(hdr) + (sizeof(unsigned int) * gp.nsamples);
hdr.profrate = SAMPLE_FREQ; hdr.version = GMONVERSION;
hdr.resv[0] = 0; hdr.profrate = SAMPLE_FREQ;
hdr.resv[1] = 0; hdr.resv[0] = 0;
hdr.resv[2] = 0; hdr.resv[1] = 0;
fwrite(&hdr, 1, sizeof(hdr), fp); hdr.resv[2] = 0;
fwrite(gp.samples, gp.nsamples, sizeof(unsigned int), fp); fwrite(&hdr, 1, sizeof(hdr), fp);
fwrite(gp.samples, gp.nsamples, sizeof(unsigned int), fp);
for (i=0; i<gp.narcs; i++) for (i=0; i<gp.narcs; i++)
{
if (gp.arcs[i].count > 0)
{ {
fwrite(gp.arcs + i, sizeof(struct rawarc), 1, fp); if (gp.arcs[i].count > 0)
{
fwrite(gp.arcs + i, sizeof(struct rawarc), 1, fp);
}
} }
fclose(fp);
} }
fclose(fp); // Free memory
free(gp.arcs);
free(gp.samples);
}
/** Writes gmon.out dump file and stops profiling
Called from atexit() handler; will dump out a gmon.out file
at cwd with all collected information.
*/
__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
void __gprof_cleanup()
{
gprof_stop("gmon.out", 1);
} }
/** Internal C handler for _mcount() /** Internal C handler for _mcount()

41
src/prof/pspprof.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* PSP Software Development Kit - https://github.com/pspdev
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* pspprof.h - Prototypes for the profiler library
*
* Copyright (c) 2006 Urchin
*
*/
#ifndef __PSPPROF_H__
#define __PSPPROF_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* Start the profiler.
* If the profiler is already running, this function stop previous one,
* and ignore the result.
* Finally, it initializes a new profiler session.
*/
__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
void gprof_start(void);
/**
* Stop the profiler.
* If the profiler is not running, this function does nothing.
* @param filename The name of the file to write the profiling data to.
* @param should_dump If 1, the profiling data will be written to the file.
* If 0, the profiling data will be discarded.
*/
__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
void gprof_stop(const char* filename, int should_dump);
#ifdef __cplusplus
}
#endif
#endif /* __PSPPROF_H__ */