PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
prof.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <stdlib.h>
12#include <malloc.h>
13#include <stdint.h>
14#include <stdio.h>
15#include <string.h>
16
17#define GMON_PROF_ON 0
18#define GMON_PROF_BUSY 1
19#define GMON_PROF_ERROR 2
20#define GMON_PROF_OFF 3
21
22#define GMONVERSION 0x00051879
23
24#include <kernel.h>
25#include <timer_alarm.h>
26#include <ps2prof.h>
27
29struct gmonhdr
30{
31 int lpc; /* lowest pc address */
32 int hpc; /* highest pc address */
33 int ncnt; /* size of samples + size of header */
34 int version; /* version number */
35 int profrate; /* profiling clock rate */
36 int resv[3]; /* reserved */
37};
38
40struct rawarc
41{
42 unsigned int frompc;
43 unsigned int selfpc;
44 unsigned int count;
45};
46
49{
50 int state;
51 unsigned int lowpc;
52 unsigned int highpc;
53 unsigned int textsize;
54 unsigned int hashfraction;
55
56 int narcs;
57 struct rawarc *arcs;
58
59 int nsamples;
60 unsigned int *samples;
61
62 int timerId;
63
64 unsigned int pc;
65};
66
68static struct gmonparam gp;
69
71#define HISTFRACTION 4
72
74#define SAMPLE_FREQ 1000
75
77extern int _ftext;
78extern int _etext;
79
82__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
83static uint64_t timer_handler(int id, uint64_t scheduled_time, uint64_t actual_time, void *arg, void *pc_value)
84{
85 struct gmonparam *current_gp = (struct gmonparam *)arg;
86
87 unsigned int frompc = current_gp->pc;
88
89 if (current_gp->state == GMON_PROF_ON) {
90 /* call might come from stack */
91 if (frompc >= current_gp->lowpc && frompc <= current_gp->highpc) {
92 int e = (frompc - current_gp->lowpc) / current_gp->hashfraction;
93 current_gp->samples[e]++;
94 }
95 }
96
97
98 current_gp->timerId = iSetTimerAlarm(USec2TimerBusClock(SAMPLE_FREQ), &timer_handler, arg);
99 return 0;
100}
101
109__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
110void __gprof_init()
111{
112 memset(&gp, '\0', sizeof(gp));
113 gp.state = GMON_PROF_ON;
114 gp.lowpc = (unsigned int)&_ftext;
115 gp.highpc = (unsigned int)&_etext;
116 gp.textsize = gp.highpc - gp.lowpc;
117 gp.hashfraction = HISTFRACTION;
118
119 gp.narcs = (gp.textsize + gp.hashfraction - 1) / gp.hashfraction;
120 gp.arcs = (struct rawarc *)malloc(sizeof(struct rawarc) * gp.narcs);
121 if (gp.arcs == NULL) {
122 gp.state = GMON_PROF_ERROR;
123 return;
124 }
125
126 gp.nsamples = (gp.textsize + gp.hashfraction - 1) / gp.hashfraction;
127 gp.samples = (unsigned int *)malloc(sizeof(unsigned int) * gp.nsamples);
128 if (gp.samples == NULL) {
129 free(gp.arcs);
130 gp.arcs = 0;
131 gp.state = GMON_PROF_ERROR;
132 return;
133 }
134
135 memset((void *)gp.arcs, '\0', gp.narcs * (sizeof(struct rawarc)));
136 memset((void *)gp.samples, '\0', gp.nsamples * (sizeof(unsigned int)));
137
138
139 gp.state = GMON_PROF_ON;
140 gp.timerId = SetTimerAlarm(USec2TimerBusClock(SAMPLE_FREQ), &timer_handler, &gp);
141 if (gp.timerId < 0) {
142 free(gp.arcs);
143 free(gp.samples);
144 gp.arcs = 0;
145 gp.samples = 0;
146 gp.state = GMON_PROF_ERROR;
147 return;
148 }
149}
150
151__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
152void gprof_start(void)
153{
154 // There is already a profiling session running, let's stop it and ignore the result
155 if (gp.state == GMON_PROF_ON) {
156 gprof_stop(NULL, 0);
157 }
158 __gprof_init();
159}
160
161__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
162void gprof_stop(const char *filename, int should_dump)
163{
164 FILE *fp;
165 int i;
166 struct gmonhdr hdr;
167
168 if (gp.state != GMON_PROF_ON) {
169 /* profiling was disabled anyway */
170 return;
171 }
172
173 /* disable profiling before we make plenty of libc calls */
174 gp.state = GMON_PROF_OFF;
175
176 ReleaseTimerAlarm(gp.timerId);
177
178 if (should_dump) {
179 fp = fopen(filename, "wb");
180 hdr.lpc = gp.lowpc;
181 hdr.hpc = gp.highpc;
182 hdr.ncnt = sizeof(hdr) + (sizeof(unsigned int) * gp.nsamples);
183 hdr.version = GMONVERSION;
184 hdr.profrate = SAMPLE_FREQ;
185 hdr.resv[0] = 0;
186 hdr.resv[1] = 0;
187 hdr.resv[2] = 0;
188 fwrite(&hdr, 1, sizeof(hdr), fp);
189 fwrite(gp.samples, gp.nsamples, sizeof(unsigned int), fp);
190
191 for (i = 0; i < gp.narcs; i++) {
192 if (gp.arcs[i].count > 0) {
193 fwrite(gp.arcs + i, sizeof(struct rawarc), 1, fp);
194 }
195 }
196
197 fclose(fp);
198 }
199
200 // free memory
201 free(gp.arcs);
202 free(gp.samples);
203}
204
209__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
210void __gprof_cleanup()
211{
212 gprof_stop("gmon.out", 1);
213}
214
224__attribute__((__no_instrument_function__, __no_profile_instrument_function__))
225void __mcount(unsigned int frompc, unsigned int selfpc)
226{
227 int e;
228 struct rawarc *arc;
229
230 if (gp.state != GMON_PROF_ON) {
231 /* returned off for some reason */
232 return;
233 }
234
235 frompc = frompc & 0x0FFFFFFF;
236 selfpc = selfpc & 0x0FFFFFFF;
237
238 /* call might come from stack */
239 if (frompc >= gp.lowpc && frompc <= gp.highpc) {
240 gp.pc = selfpc;
241 e = (frompc - gp.lowpc) / gp.hashfraction;
242 arc = gp.arcs + e;
243 arc->frompc = frompc;
244 arc->selfpc = selfpc;
245 arc->count++;
246 }
247}
typedef __attribute__
Definition tlbfunc.c:60
Definition prof.c:30
Definition prof.c:41