source: CIVL/examples/compare/provesa/ADFirstAidKit/profile.c@ bb03188

main test-branch
Last change on this file since bb03188 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 8.1 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <signal.h>
5#include <sys/types.h>
6#include <unistd.h>
7#include <time.h>
8#include <unistd.h>
9
10// Access to the cycle counter
11#define rdtscll(val) \
12 __asm__ __volatile__ ("rdtsc" : "=A" (val))
13
14#define ENABLE_LINE_RECORDING 1
15
16unsigned long long int mytime_() {
17 unsigned long long int time;
18
19 rdtscll(time);
20 return time ;
21}
22
23// Access to stacks size
24extern long int bigStackSize;
25extern long int smallstacksize_();
26
27
28// Declaration of the event list data structures
29#define ARRAY_SIZE 100000
30struct event {
31 int kind;
32 char *function;
33 int len;
34 unsigned long long int time;
35 int stacksize;
36#ifdef ENABLE_LINE_RECORDING
37 int line;
38#endif
39};
40
41struct list_node {
42 struct event array[ARRAY_SIZE];
43 struct list_node *next;
44};
45static struct list_node hdcell = { .next = 0 };
46static struct list_node *tlcell = &hdcell;
47static int cell_index = 0;
48
49// Function to traverse the list of events
50static void traverse_event_list(void (*process)(struct event *ev, void *data), void *data) {
51 struct list_node *c = &hdcell;
52
53 while (c) {
54 int max = c->next ? ARRAY_SIZE : cell_index;
55 int i;
56 for (i = 0; i < max; ++i)
57 process(&c->array[i], data);
58 c = c->next;
59 }
60}
61
62
63// Declaration of profiling functions
64#if 1
65#define profiledebug
66#else
67#define profiledebug(type) \
68 printf("%50s %02u %022llu %010lu %li\n", buffer, type, mytime_(), bigStackSize, smallstacksize_());
69#endif
70enum { BEGIN = 1, END, ENDFWD, BEGINSNAPSHOT, ENDSNAPSHOT, ENDORIG };
71
72int init = 0;
73unsigned long long int beginning_of_time = 0;
74inline static void profile_real(char *function, int flen, int kind) {
75 static struct list_node *new = 0;
76 if (cell_index >= ARRAY_SIZE) {
77 new = (struct list_node*)calloc(1, sizeof(struct list_node));
78 tlcell->next = new;
79 tlcell = new;
80 new->next = 0;
81 cell_index = 0;
82 }
83 static unsigned long long int time;
84 time = mytime_();
85 if (init == 0)
86 beginning_of_time = time, init = 1;
87 tlcell->array[cell_index].kind = kind;
88 tlcell->array[cell_index].function = function;
89 tlcell->array[cell_index].len = flen;
90 tlcell->array[cell_index].time = time - beginning_of_time;
91 tlcell->array[cell_index].stacksize = bigStackSize + smallstacksize_();
92 #if 0
93 printf("%016llu %09lu %02hhu ", time-beginning_of_time, bigStackSize + smallstacksize_(), kind);
94 fwrite(function, 1, flen, stdout);
95 printf("\n");
96 #endif
97 cell_index++;
98}
99
100#define declare_profile(suffix,type) \
101void profile##suffix##_(char *function, int flen) {\
102 profile_real(function, flen, type);\
103}
104
105declare_profile(begin,BEGIN)
106declare_profile(end,END)
107declare_profile(endfwd,ENDFWD)
108declare_profile(beginsnapshot,BEGINSNAPSHOT)
109declare_profile(endsnapshot,ENDSNAPSHOT)
110declare_profile(endorig,ENDORIG)
111
112#ifdef ENABLE_LINE_RECORDING
113static int current_line_number = 0;
114
115void profileline_(int *line) {
116 current_line_number = *line;
117}
118#endif
119
120// Hashtable data structure
121#define hashtbl_size 4093
122struct hash_cell {
123 char *function;
124 int len;
125} hashtbl[hashtbl_size];
126// Count of the used element in the hashtable
127int hashtbl_count;
128
129// Simple hash function
130static inline unsigned int hash(unsigned int u) {
131 return ((u % hashtbl_size) * 1024 ) % hashtbl_size;
132}
133
134// Simple hash function on strings
135static inline unsigned int hash_string(char *string, int flen) {
136 unsigned int ret = 0x55555555;
137 while (flen--)
138 ret *= ((unsigned char)*string++ * hashtbl_size);
139 return hash(ret);
140}
141
142// Min macro
143#define min(a,b) (a < b ? a : b)
144
145// Get the id of a string address, allocate a bucket if new
146static int get(char *function, int flen) {
147 int h = hash_string(function, flen);
148 while (hashtbl[h].function) {
149 if (strncmp(hashtbl[h].function, function, min(flen, hashtbl[h].len)) == 0)
150 break;
151 h = hash(h);
152 }
153 hashtbl[h].function = function;
154 hashtbl[h].len = flen;
155 return h;
156}
157
158// Functions to serialize integers and known length strings
159static inline void fwrite_int(FILE *f, int i) {
160 fwrite(&i, sizeof(int), 1, f);
161}
162static inline void fwrite_llint(FILE *f, unsigned long long int i) {
163 fwrite(&i, sizeof(unsigned long long int), 1, f);
164}
165static inline void fwrite_string(FILE *f, char *str, int len) {
166 fwrite_int(f, len);
167 fwrite(str, (unsigned int) len, 1, f);
168}
169
170// Function to build the hashtable of function names
171static void add_event_to_hashtable(struct event *ev, void *data);
172static void build_hashtable() {
173
174 // Initialize the hashtable
175 memset(hashtbl, 0, sizeof(struct hash_cell)*hashtbl_size);
176 /** Fill the hashtbl */
177 traverse_event_list(add_event_to_hashtable, 0);
178 /** Compute the size of the hashtbl */
179 hashtbl_count = 0;
180 int i;
181 for (i=0; i < hashtbl_size; ++i)
182 if (hashtbl[i].function)
183 hashtbl_count++;
184}
185static void add_event_to_hashtable(struct event *ev, void *data) {
186 int h = get(ev->function, ev->len);
187}
188
189
190// Serialize event list into a file named tapenade.prof
191struct print_args {
192 FILE *prof;
193 struct event **stack;
194 int *stack_counter;
195};
196static void print_an_event(struct event *ev, void *data);
197void printprofile_() {
198 int i = 0;
199 FILE *prof = fopen("tapenade.prof", "w");
200 if (!prof) {
201 perror("Can't open tapenade.prof");
202 exit(1);
203 }
204 // Compress the output;
205 // Generate a hashtable of the functions name
206 // use it to make a map from function name
207 // to numeric id
208 build_hashtable();
209
210 // Position at the beginning
211 fseek(prof, 0, SEEK_SET);
212
213 // Dump the hash table
214 fwrite_int(prof, hashtbl_count);
215 for (i=0; i < hashtbl_size; ++i)
216 if (hashtbl[i].function) {
217 fwrite_int(prof, i);
218 char *string = hashtbl[i].function;
219 int string_length = hashtbl[i].len;
220 fwrite_string(prof, string, string_length);
221 }
222
223 // Dump the events
224 struct list_node *c = &hdcell;
225 struct event *stack[1000];
226 int stack_counter = -1;
227 struct print_args args = {
228 .prof = prof,
229 .stack = stack,
230 .stack_counter = &stack_counter
231 };
232 traverse_event_list(print_an_event, &args);
233
234 // For program that aborts too abruptly ( with STOP )
235 // Use the return stack image to recreate EXIT events
236 for (i=stack_counter; i>-1;i--) {
237 struct event *cur = stack[i];
238 int h = get(cur->function, cur->len);
239 fwrite_int(prof, h);
240 fwrite_int(prof, 2); // Explicit ending
241 fwrite_llint(prof, cur->time);
242 fwrite_int(prof, cur->stacksize);
243 }
244 fclose(prof);
245}
246void halt_();
247// Utility function for printprofile
248static void print_an_event(struct event *ev, void *data) {
249 struct print_args *args = (struct print_args*)data;
250 static unsigned long long int last_time = 0;
251
252 int h = get(ev->function, ev->len);
253 // Keep trace of the return stack depth and values
254 switch (ev->kind) {
255 case 1:
256 *(args->stack_counter) += 1;
257 args->stack[*(args->stack_counter)] = ev;
258 break;
259 case 2:
260 *(args->stack_counter) -= 1;
261 break;
262 }
263//DEBUG printf("Time: %llu\n", ev->time - begin_time);
264 if (last_time && ev->time <= last_time) {
265 printf("Erreur time <= last_time: %llu <= %llu\n", time, last_time);
266 halt_();
267 }
268 fwrite_int(args->prof, h);
269 fwrite_int(args->prof, ev->kind);
270 fwrite_llint(args->prof, ev->time);
271 fwrite_int(args->prof, ev->stacksize);
272 last_time = ev->time;
273}
274
275#include <signal.h>
276void halt_() {
277 kill(getpid(), SIGTRAP);
278}
Note: See TracBrowser for help on using the repository browser.