blob: 9dfdd31cbec55bd674aab308cd38b39299a2c7ff [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*--------------------------------------------------------------------*/
2/*--- Callgrind ---*/
3/*--- events.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Callgrind, a Valgrind tool for call tracing.
8
sewardj4d474d02008-02-11 11:34:59 +00009 Copyright (C) 2002-2008, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +000010
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307, USA.
25
26 The GNU General Public License is contained in the file COPYING.
27*/
28
29#include "global.h"
30
31#define MAX_EVENTTYPE 20
32
33static EventType eventtype[MAX_EVENTTYPE];
34static Int eventtype_count = 0;
35
36EventType* CLG_(register_eventtype)(Char* name)
37{
38 EventType* et;
39
40 if (eventtype_count == MAX_EVENTTYPE) {
41 VG_(printf)("\nMore than %d event types used!\n"
42 "Increase MAX_EVENTTYPE in ct_events.c and recomile this tool!\n",
43 MAX_EVENTTYPE);
44 VG_(tool_panic)("Too many event types requested.");
45 }
46
47 et = &(eventtype[eventtype_count]);
48 et->id = eventtype_count;
sewardj9c606bd2008-09-18 18:12:50 +000049 et->name = (UChar*) VG_(strdup)("cl.events.re.1", name);
weidendoa17f2a32006-03-20 10:27:30 +000050 et->description = 0;
51
52 eventtype_count++;
53
54 return et;
55}
56
57
58EventType* CLG_(get_eventtype)(Char* name)
59{
60 Int i;
61
62 for(i=0;i<eventtype_count;i++)
63 if (VG_(strcmp)(eventtype[i].name, name) == 0)
64 return eventtype+i;
65 return 0;
66}
67
68EventType* CLG_(get_eventtype_byindex)(Int id)
69{
70 if ((id >= 0) && (id < eventtype_count))
71 return eventtype+id;
72 return 0;
73}
74
75/* Allocate space for an event set */
76EventSet* CLG_(get_eventset)(Char* n, Int capacity)
77{
78 EventSet* es;
79
sewardj9c606bd2008-09-18 18:12:50 +000080 es = (EventSet*) CLG_MALLOC("cl.events.geSet.1",
81 sizeof(EventSet) +
weidendoa17f2a32006-03-20 10:27:30 +000082 capacity * sizeof(EventSetEntry));
83 es->capacity = capacity;
84 es->size = 0;
85 es->name = n;
86
87 return es;
88}
89
90/* Incorporate a event type into a set, get start offset */
91Int CLG_(add_eventtype)(EventSet* es, EventType* t)
92{
93 Int offset = es->size;
94 if (es->capacity - offset < 1) return -1;
95
96 es->size++;
97 es->e[offset].type = t;
98 es->e[offset].nextTop = es->size;
99
100 return offset;
101}
102
103/* Incorporate one event set into another, get start offset */
104Int CLG_(add_eventset)(EventSet* dst, EventSet* src)
105{
106 Int offset = dst->size, i;
107 if (!src || (src->size == 0)) return offset;
108
109 if (dst->capacity - offset < src->size) return -1;
110
111 for(i=0;i<src->size;i++) {
112 dst->e[offset+i].type = src->e[i].type;
113 dst->e[offset+i].nextTop = src->e[i].nextTop + offset;
114 }
115 dst->size += src->size;
116
117 return offset;
118}
119
120/* Incorporate two event types into a set, with second < first */
121Int CLG_(add_dep_event2)(EventSet* es, EventType* e1, EventType* e2)
122{
123 Int offset = es->size;
124
125 if (es->capacity - offset < 2) return -1;
126
127 es->size += 2;
128 es->e[offset].type = e1;
129 es->e[offset].nextTop = es->size;
130 es->e[offset+1].type = e2;
131 es->e[offset+1].nextTop = es->size;
132
133 return offset;
134}
135
136/* Incorporate 3 event types into a set, with third < second < first */
137Int CLG_(add_dep_event3)(EventSet* es,
138 EventType* e1, EventType* e2, EventType* e3)
139{
140 Int offset = es->size;
141
142 if (es->capacity - offset < 3) return -1;
143
144 es->size += 3;
145 es->e[offset].type = e1;
146 es->e[offset].nextTop = es->size;
147 es->e[offset+1].type = e2;
148 es->e[offset+1].nextTop = es->size;
149 es->e[offset+2].type = e3;
150 es->e[offset+2].nextTop = es->size;
151
152 return offset;
153}
154
155Int CLG_(add_dep_event4)(EventSet* es,
156 EventType* e1, EventType* e2,
157 EventType* e3, EventType* e4)
158{
159 Int offset = es->size;
160
161 if (es->capacity - offset < 4) return -1;
162
163 es->size += 4;
164 es->e[offset].type = e1;
165 es->e[offset].nextTop = es->size;
166 es->e[offset+1].type = e2;
167 es->e[offset+1].nextTop = es->size;
168 es->e[offset+2].type = e3;
169 es->e[offset+2].nextTop = es->size;
170 es->e[offset+3].type = e4;
171 es->e[offset+3].nextTop = es->size;
172
173 return offset;
174}
175
176/* Returns number of characters written */
177Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
178{
179 Int i, pos = 0;
180
181 for(i=0; i< es->size; i++) {
182 if (pos>0) buf[pos++] = ' ';
sewardjbbaef872008-11-01 23:55:32 +0000183 pos += VG_(sprintf)(buf + pos, "%s", es->e[i].type->name);
weidendoa17f2a32006-03-20 10:27:30 +0000184 }
185 buf[pos] = 0;
186
187 return pos;
188}
189
190/* Get cost array for an event set */
191ULong* CLG_(get_eventset_cost)(EventSet* es)
192{
193 return CLG_(get_costarray)(es->capacity);
194}
195
196/* Set all costs of an event set to zero */
197void CLG_(init_cost)(EventSet* es, ULong* cost)
198{
199 Int i;
200
201 if (!cost) return;
202
203 for(i=0;i<es->capacity;i++)
204 cost[i] = 0;
205}
206
207/* Set all costs of an event set to zero */
208void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
209{
210 Int i;
211
212 CLG_ASSERT(cost != 0);
213 if (!(*cost))
214 *cost = CLG_(get_eventset_cost)(es);
215
216 for(i=0;i<es->capacity;i++)
217 (*cost)[i] = 0;
218}
219
220void CLG_(zero_cost)(EventSet* es, ULong* cost)
221{
222 Int i;
223
224 if (!cost) return;
225
226 for(i=0;i<es->size;i++)
227 cost[i] = 0;
228}
229
230Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
231{
232 Int i = 0;
233
234 if (!cost) return True;
235
236 while(i<es->size) {
237 if (cost[i] != 0) return False;
238 i = es->e[i].nextTop;
239 }
240 return True;
241}
242
243Bool CLG_(is_equal_cost)(EventSet* es, ULong* c1, ULong* c2)
244{
245 Int i = 0;
246
247 if (!c1) return CLG_(is_zero_cost)(es,c2);
248 if (!c2) return CLG_(is_zero_cost)(es,c1);
249
250 while(i<es->size) {
251 if (c1[i] != c2[i]) return False;
252 if (c1[i] == 0)
253 i = es->e[i].nextTop;
254 else
255 i++;
256 }
257 return True;
258}
259
260void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
261{
262 Int i;
263
264 if (!src) {
265 CLG_(zero_cost)(es, dst);
266 return;
267 }
268 CLG_ASSERT(dst != 0);
269
270 for(i=0;i<es->size;i++)
271 dst[i] = src[i];
272}
273
274void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
275{
276 Int i;
277 ULong* dst;
278
279 CLG_ASSERT(pdst != 0);
280
281 if (!src) {
282 CLG_(zero_cost)(es, *pdst);
283 return;
284 }
285 dst = *pdst;
286 if (!dst)
287 dst = *pdst = CLG_(get_eventset_cost)(es);
288
289 for(i=0;i<es->size;i++)
290 dst[i] = src[i];
291}
292
293void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
294{
295 Int i = 0;
296
297 if (!src) return;
298 CLG_ASSERT(dst != 0);
299
300 while(i<es->size) {
301 if (src[i] == 0)
302 i = es->e[i].nextTop;
303 else {
304 dst[i] += src[i];
305 i++;
306 }
307 }
308}
309
310void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
311{
312 Int i;
313 ULong* dst;
314
315 if (!src) return;
316 CLG_ASSERT(pdst != 0);
317
318 dst = *pdst;
319 if (!dst) {
320 dst = *pdst = CLG_(get_eventset_cost)(es);
321 CLG_(copy_cost)(es,dst,src);
322 return;
323 }
324
325 i = 0;
326 while(i<es->size) {
327 if (src[i] == 0)
328 i = es->e[i].nextTop;
329 else {
330 dst[i] += src[i];
331 i++;
332 }
333 }
334}
335
336/* Adds src to dst and zeros src. Returns false if nothing changed */
337Bool CLG_(add_and_zero_cost)(EventSet* es, ULong* dst, ULong* src)
338{
339 Int i = 0, j = 0;
340
341 CLG_DEBUGIF(6) {
342 CLG_DEBUG(6, " add_and_zero_cost(%s, dst %p, src %p)\n", es->name, dst, src);
343 CLG_(print_cost)(-5, es, src);
344 }
345
346 if (!es || !src) return False;
347
348 while(i<es->size) {
349 if (src[i] == 0)
350 i = es->e[i].nextTop;
351 else {
352 dst[i] += src[i];
353 src[i] = 0;
354 i++;
355 j++;
356 }
357 }
358
359 return (j>0);
360}
361
362/* Adds src to dst and zeros src. Returns false if nothing changed */
363Bool CLG_(add_and_zero_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
364{
365 Int i;
366 ULong* dst;
367
368 if (!src) return False;
369
370 i = 0;
371 while(1) {
372 if (i >= es->size) return False;
373 if (src[i] != 0) break;
374 i = es->e[i].nextTop;
375 }
376
377 CLG_ASSERT(pdst != 0);
378 dst = *pdst;
379 if (!dst) {
380 dst = *pdst = CLG_(get_eventset_cost)(es);
381 CLG_(copy_cost)(es,dst,src);
382 CLG_(zero_cost)(es,src);
383 return True;
384 }
385
386 dst[i] += src[i];
387 src[i] = 0;
388 i++;
389
390 while(i<es->size) {
391 if (src[i] == 0)
392 i = es->e[i].nextTop;
393 else {
394 dst[i] += src[i];
395 src[i] = 0;
396 }
397 }
398
399 return True;
400}
401
402/* Adds difference of new and old to dst, and set old to new.
403 * Returns false if nothing changed */
404Bool CLG_(add_diff_cost)(EventSet* es, ULong* dst, ULong* old, ULong* new)
405{
406 Int i = 0, j = 0;
407
408 while(i<es->size) {
409 if (new[i] == old[i])
410 i = es->e[i].nextTop;
411 else {
412 dst[i] += new[i] - old[i];
413 old[i] = new[i];
414 i++;
415 j++;
416 }
417 }
418
419 return (j>0);
420}
421
422/* Adds difference of new and old to dst, and set old to new.
423 * Returns false if nothing changed */
424Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst,
425 ULong* old, ULong* new)
426{
427 Int i;
428 ULong* dst;
429
430 if (!old && !new) return False;
431 CLG_ASSERT(old && new);
432
433 i = 0;
434 while(1) {
435 if (i >= es->size) return False;
436 if (old[i] != new[i]) break;
437 i = es->e[i].nextTop;
438 }
439
440 CLG_ASSERT(pdst != 0);
441 dst = *pdst;
442 if (!dst) {
443 dst = *pdst = CLG_(get_eventset_cost)(es);
444 CLG_(zero_cost)(es,dst);
445 }
446
447 dst[i] += new[i] - old[i];
448 old[i] = new[i];
449 i++;
450
451 while(i<es->size) {
452 if (new[i] == old[i])
453 i = es->e[i].nextTop;
454 else {
455 dst[i] += new[i] - old[i];
456 old[i] = new[i];
457 i++;
458 }
459 }
460
461 return True;
462}
463
464/* Returns number of characters written */
465Int CLG_(sprint_cost)(Char* buf, EventSet* es, ULong* c)
466{
467 Int i, pos, skipped = 0;
468
469 if (!c || es->size==0) return 0;
470
471 /* At least one entry */
472 pos = VG_(sprintf)(buf, "%llu", c[0]);
473 i = 1;
474
475 while(i<es->size) {
476 if (c[i] == 0) {
477 skipped += es->e[i].nextTop - i;
478 i = es->e[i].nextTop;
479 }
480 else {
481 while(skipped>0) {
482 buf[pos++] = ' ';
483 buf[pos++] = '0';
484 skipped--;
485 }
486 buf[pos++] = ' ';
487 pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
488 i++;
489 }
490 }
491
492 return pos;
493}
494
495
496/* Allocate space for an event mapping */
497EventMapping* CLG_(get_eventmapping)(EventSet* es)
498{
499 EventMapping* em;
500
501 CLG_ASSERT(es != 0);
502
sewardj9c606bd2008-09-18 18:12:50 +0000503 em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
504 sizeof(EventMapping) +
weidendoa17f2a32006-03-20 10:27:30 +0000505 es->capacity * sizeof(Int));
506 em->capacity = es->capacity;
507 em->size = 0;
508 em->set = es;
509
510 return em;
511}
512
513void CLG_(append_event)(EventMapping* em, Char* n)
514{
515 Int i;
516
517 CLG_ASSERT(em != 0);
518
519 for(i=0; i<em->set->size; i++)
520 if (VG_(strcmp)(n, em->set->e[i].type->name)==0)
521 break;
522
523 if (i == em->set->size) return;
524
525 CLG_ASSERT(em->capacity > em->size);
526
527 em->index[em->size] = i;
528 em->size++;
529}
530
531
532/* Returns number of characters written */
533Int CLG_(sprint_eventmapping)(Char* buf, EventMapping* em)
534{
535 Int i, pos = 0;
536
537 CLG_ASSERT(em != 0);
538
539 for(i=0; i< em->size; i++) {
540 if (pos>0) buf[pos++] = ' ';
sewardjbbaef872008-11-01 23:55:32 +0000541 pos += VG_(sprintf)(buf + pos, "%s", em->set->e[em->index[i]].type->name);
weidendoa17f2a32006-03-20 10:27:30 +0000542 }
543 buf[pos] = 0;
544
545 return pos;
546}
547
548/* Returns number of characters written */
549Int CLG_(sprint_mappingcost)(Char* buf, EventMapping* em, ULong* c)
550{
551 Int i, pos, skipped = 0;
552
553 if (!c || em->size==0) return 0;
554
555 /* At least one entry */
556 pos = VG_(sprintf)(buf, "%llu", c[em->index[0]]);
557 i = 1;
558
559 while(i<em->size) {
560 if (c[em->index[i]] == 0) {
561 skipped++;
562 i++;
563 }
564 else {
565 while(skipped>0) {
566 buf[pos++] = ' ';
567 buf[pos++] = '0';
568 skipped--;
569 }
570 buf[pos++] = ' ';
571 pos += VG_(sprintf)(buf+pos, "%llu", c[em->index[i]]);
572 i++;
573 }
574 }
575
576 return pos;
577}