2 * Helper code to output instrumentation results
3 * @author Matthias Braun, Steven Schaefer
9 /* Prevent the compiler from mangling the name of this function. */
10 void __init_firmprof(const char*, unsigned int*, size_t)
11 asm("__init_firmprof");
13 typedef struct _profile_counter_t {
17 struct _profile_counter_t *next;
20 static profile_counter_t *counters = NULL;
23 * Write counter values to profiling output file.
24 * We define our output format to be a sequence of 32-bit unsigned integer
25 * values stored in little endian format.
27 void write_little_endian(unsigned *counter, unsigned len, FILE *f)
31 for (i = 0; i < len; ++i) {
32 unsigned v = counter[i];
33 unsigned char bytes[4];
35 bytes[0] = ((v >> 0) & 0xff);
36 bytes[1] = ((v >> 8) & 0xff);
37 bytes[2] = ((v >> 16) & 0xff);
38 bytes[3] = ((v >> 24) & 0xff);
40 fwrite(bytes, 1, 4, f);
44 static void write_profiles(void)
46 profile_counter_t *counter = counters;
47 while (counter != NULL) {
48 profile_counter_t *next = counter->next;
49 FILE *f = fopen(counter->filename, "wb");
51 perror("Warning: couldn't open file for writing profiling data");
54 write_little_endian(counter->counters, counter->len, f);
63 * Register a new profile counter. This is called by separate constructors
64 * for each translation unit. Incidentally, referring to this function as
65 * "__init_firmprof" is perfectly linker friendly.
67 void __init_firmprof(const char *filename,
68 unsigned int *counts, size_t len)
70 static int initialized = 0;
71 profile_counter_t *counter;
75 atexit(write_profiles);
78 counter = (profile_counter_t*) malloc(sizeof(*counter));
82 counter->filename = filename;
83 counter->counters = counts;
84 counter->next = counters;