blob: 0b62b4f878c3cd1188a52002cd147424e6fcbae1 [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;
49 et->name = (UChar*) VG_(strdup)(name);
50 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
80 es = (EventSet*) CLG_MALLOC(sizeof(EventSet) +
81 capacity * sizeof(EventSetEntry));
82 es->capacity = capacity;
83 es->size = 0;
84 es->name = n;
85
86 return es;
87}
88
89/* Incorporate a event type into a set, get start offset */
90Int CLG_(add_eventtype)(EventSet* es, EventType* t)
91{
92 Int offset = es->size;
93 if (es->capacity - offset < 1) return -1;
94
95 es->size++;
96 es->e[offset].type = t;
97 es->e[offset].nextTop = es->size;
98
99 return offset;
100}
101
102/* Incorporate one event set into another, get start offset */
103Int CLG_(add_eventset)(EventSet* dst, EventSet* src)
104{
105 Int offset = dst->size, i;
106 if (!src || (src->size == 0)) return offset;
107
108 if (dst->capacity - offset < src->size) return -1;
109
110 for(i=0;i<src->size;i++) {
111 dst->e[offset+i].type = src->e[i].type;
112 dst->e[offset+i].nextTop = src->e[i].nextTop + offset;
113 }
114 dst->size += src->size;
115
116 return offset;
117}
118
119/* Incorporate two event types into a set, with second < first */
120Int CLG_(add_dep_event2)(EventSet* es, EventType* e1, EventType* e2)
121{
122 Int offset = es->size;
123
124 if (es->capacity - offset < 2) return -1;
125
126 es->size += 2;
127 es->e[offset].type = e1;
128 es->e[offset].nextTop = es->size;
129 es->e[offset+1].type = e2;
130 es->e[offset+1].nextTop = es->size;
131
132 return offset;
133}
134
135/* Incorporate 3 event types into a set, with third < second < first */
136Int CLG_(add_dep_event3)(EventSet* es,
137 EventType* e1, EventType* e2, EventType* e3)
138{
139 Int offset = es->size;
140
141 if (es->capacity - offset < 3) return -1;
142
143 es->size += 3;
144 es->e[offset].type = e1;
145 es->e[offset].nextTop = es->size;
146 es->e[offset+1].type = e2;
147 es->e[offset+1].nextTop = es->size;
148 es->e[offset+2].type = e3;
149 es->e[offset+2].nextTop = es->size;
150
151 return offset;
152}
153
154Int CLG_(add_dep_event4)(EventSet* es,
155 EventType* e1, EventType* e2,
156 EventType* e3, EventType* e4)
157{
158 Int offset = es->size;
159
160 if (es->capacity - offset < 4) return -1;
161
162 es->size += 4;
163 es->e[offset].type = e1;
164 es->e[offset].nextTop = es->size;
165 es->e[offset+1].type = e2;
166 es->e[offset+1].nextTop = es->size;
167 es->e[offset+2].type = e3;
168 es->e[offset+2].nextTop = es->size;
169 es->e[offset+3].type = e4;
170 es->e[offset+3].nextTop = es->size;
171
172 return offset;
173}
174
175/* Returns number of characters written */
176Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
177{
178 Int i, pos = 0;
179
180 for(i=0; i< es->size; i++) {
181 if (pos>0) buf[pos++] = ' ';
182 pos += VG_(sprintf)(buf + pos, es->e[i].type->name);
183 }
184 buf[pos] = 0;
185
186 return pos;
187}
188
189/* Get cost array for an event set */
190ULong* CLG_(get_eventset_cost)(EventSet* es)
191{
192 return CLG_(get_costarray)(es->capacity);
193}
194
195/* Set all costs of an event set to zero */
196void CLG_(init_cost)(EventSet* es, ULong* cost)
197{
198 Int i;
199
200 if (!cost) return;
201
202 for(i=0;i<es->capacity;i++)
203 cost[i] = 0;
204}
205
206/* Set all costs of an event set to zero */
207void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
208{
209 Int i;
210
211 CLG_ASSERT(cost != 0);
212 if (!(*cost))
213 *cost = CLG_(get_eventset_cost)(es);
214
215 for(i=0;i<es->capacity;i++)
216 (*cost)[i] = 0;
217}
218
219void CLG_(zero_cost)(EventSet* es, ULong* cost)
220{
221 Int i;
222
223 if (!cost) return;
224
225 for(i=0;i<es->size;i++)
226 cost[i] = 0;
227}
228
229Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
230{
231 Int i = 0;
232
233 if (!cost) return True;
234
235 while(i<es->size) {
236 if (cost[i] != 0) return False;
237 i = es->e[i].nextTop;
238 }
239 return True;
240}
241
242Bool CLG_(is_equal_cost)(EventSet* es, ULong* c1, ULong* c2)
243{
244 Int i = 0;
245
246 if (!c1) return CLG_(is_zero_cost)(es,c2);
247 if (!c2) return CLG_(is_zero_cost)(es,c1);
248
249 while(i<es->size) {
250 if (c1[i] != c2[i]) return False;
251 if (c1[i] == 0)
252 i = es->e[i].nextTop;
253 else
254 i++;
255 }
256 return True;
257}
258
259void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
260{
261 Int i;
262
263 if (!src) {
264 CLG_(zero_cost)(es, dst);
265 return;
266 }
267 CLG_ASSERT(dst != 0);
268
269 for(i=0;i<es->size;i++)
270 dst[i] = src[i];
271}
272
273void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
274{
275 Int i;
276 ULong* dst;
277
278 CLG_ASSERT(pdst != 0);
279
280 if (!src) {
281 CLG_(zero_cost)(es, *pdst);
282 return;
283 }
284 dst = *pdst;
285 if (!dst)
286 dst = *pdst = CLG_(get_eventset_cost)(es);
287
288 for(i=0;i<es->size;i++)
289 dst[i] = src[i];
290}
291
292void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
293{
294 Int i = 0;
295
296 if (!src) return;
297 CLG_ASSERT(dst != 0);
298
299 while(i<es->size) {
300 if (src[i] == 0)
301 i = es->e[i].nextTop;
302 else {
303 dst[i] += src[i];
304 i++;
305 }
306 }
307}
308
309void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
310{
311 Int i;
312 ULong* dst;
313
314 if (!src) return;
315 CLG_ASSERT(pdst != 0);
316
317 dst = *pdst;
318 if (!dst) {
319 dst = *pdst = CLG_(get_eventset_cost)(es);
320 CLG_(copy_cost)(es,dst,src);
321 return;
322 }
323
324 i = 0;
325 while(i<es->size) {
326 if (src[i] == 0)
327 i = es->e[i].nextTop;
328 else {
329 dst[i] += src[i];
330 i++;
331 }
332 }
333}
334
335/* Adds src to dst and zeros src. Returns false if nothing changed */
336Bool CLG_(add_and_zero_cost)(EventSet* es, ULong* dst, ULong* src)
337{
338 Int i = 0, j = 0;
339
340 CLG_DEBUGIF(6) {
341 CLG_DEBUG(6, " add_and_zero_cost(%s, dst %p, src %p)\n", es->name, dst, src);
342 CLG_(print_cost)(-5, es, src);
343 }
344
345 if (!es || !src) return False;
346
347 while(i<es->size) {
348 if (src[i] == 0)
349 i = es->e[i].nextTop;
350 else {
351 dst[i] += src[i];
352 src[i] = 0;
353 i++;
354 j++;
355 }
356 }
357
358 return (j>0);
359}
360
361/* Adds src to dst and zeros src. Returns false if nothing changed */
362Bool CLG_(add_and_zero_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
363{
364 Int i;
365 ULong* dst;
366
367 if (!src) return False;
368
369 i = 0;
370 while(1) {
371 if (i >= es->size) return False;
372 if (src[i] != 0) break;
373 i = es->e[i].nextTop;
374 }
375
376 CLG_ASSERT(pdst != 0);
377 dst = *pdst;
378 if (!dst) {
379 dst = *pdst = CLG_(get_eventset_cost)(es);
380 CLG_(copy_cost)(es,dst,src);
381 CLG_(zero_cost)(es,src);
382 return True;
383 }
384
385 dst[i] += src[i];
386 src[i] = 0;
387 i++;
388
389 while(i<es->size) {
390 if (src[i] == 0)
391 i = es->e[i].nextTop;
392 else {
393 dst[i] += src[i];
394 src[i] = 0;
395 }
396 }
397
398 return True;
399}
400
401/* Adds difference of new and old to dst, and set old to new.
402 * Returns false if nothing changed */
403Bool CLG_(add_diff_cost)(EventSet* es, ULong* dst, ULong* old, ULong* new)
404{
405 Int i = 0, j = 0;
406
407 while(i<es->size) {
408 if (new[i] == old[i])
409 i = es->e[i].nextTop;
410 else {
411 dst[i] += new[i] - old[i];
412 old[i] = new[i];
413 i++;
414 j++;
415 }
416 }
417
418 return (j>0);
419}
420
421/* Adds difference of new and old to dst, and set old to new.
422 * Returns false if nothing changed */
423Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst,
424 ULong* old, ULong* new)
425{
426 Int i;
427 ULong* dst;
428
429 if (!old && !new) return False;
430 CLG_ASSERT(old && new);
431
432 i = 0;
433 while(1) {
434 if (i >= es->size) return False;
435 if (old[i] != new[i]) break;
436 i = es->e[i].nextTop;
437 }
438
439 CLG_ASSERT(pdst != 0);
440 dst = *pdst;
441 if (!dst) {
442 dst = *pdst = CLG_(get_eventset_cost)(es);
443 CLG_(zero_cost)(es,dst);
444 }
445
446 dst[i] += new[i] - old[i];
447 old[i] = new[i];
448 i++;
449
450 while(i<es->size) {
451 if (new[i] == old[i])
452 i = es->e[i].nextTop;
453 else {
454 dst[i] += new[i] - old[i];
455 old[i] = new[i];
456 i++;
457 }
458 }
459
460 return True;
461}
462
463/* Returns number of characters written */
464Int CLG_(sprint_cost)(Char* buf, EventSet* es, ULong* c)
465{
466 Int i, pos, skipped = 0;
467
468 if (!c || es->size==0) return 0;
469
470 /* At least one entry */
471 pos = VG_(sprintf)(buf, "%llu", c[0]);
472 i = 1;
473
474 while(i<es->size) {
475 if (c[i] == 0) {
476 skipped += es->e[i].nextTop - i;
477 i = es->e[i].nextTop;
478 }
479 else {
480 while(skipped>0) {
481 buf[pos++] = ' ';
482 buf[pos++] = '0';
483 skipped--;
484 }
485 buf[pos++] = ' ';
486 pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
487 i++;
488 }
489 }
490
491 return pos;
492}
493
494
495/* Allocate space for an event mapping */
496EventMapping* CLG_(get_eventmapping)(EventSet* es)
497{
498 EventMapping* em;
499
500 CLG_ASSERT(es != 0);
501
502 em = (EventMapping*) CLG_MALLOC(sizeof(EventMapping) +
503 es->capacity * sizeof(Int));
504 em->capacity = es->capacity;
505 em->size = 0;
506 em->set = es;
507
508 return em;
509}
510
511void CLG_(append_event)(EventMapping* em, Char* n)
512{
513 Int i;
514
515 CLG_ASSERT(em != 0);
516
517 for(i=0; i<em->set->size; i++)
518 if (VG_(strcmp)(n, em->set->e[i].type->name)==0)
519 break;
520
521 if (i == em->set->size) return;
522
523 CLG_ASSERT(em->capacity > em->size);
524
525 em->index[em->size] = i;
526 em->size++;
527}
528
529
530/* Returns number of characters written */
531Int CLG_(sprint_eventmapping)(Char* buf, EventMapping* em)
532{
533 Int i, pos = 0;
534
535 CLG_ASSERT(em != 0);
536
537 for(i=0; i< em->size; i++) {
538 if (pos>0) buf[pos++] = ' ';
539 pos += VG_(sprintf)(buf + pos, em->set->e[em->index[i]].type->name);
540 }
541 buf[pos] = 0;
542
543 return pos;
544}
545
546/* Returns number of characters written */
547Int CLG_(sprint_mappingcost)(Char* buf, EventMapping* em, ULong* c)
548{
549 Int i, pos, skipped = 0;
550
551 if (!c || em->size==0) return 0;
552
553 /* At least one entry */
554 pos = VG_(sprintf)(buf, "%llu", c[em->index[0]]);
555 i = 1;
556
557 while(i<em->size) {
558 if (c[em->index[i]] == 0) {
559 skipped++;
560 i++;
561 }
562 else {
563 while(skipped>0) {
564 buf[pos++] = ' ';
565 buf[pos++] = '0';
566 skipped--;
567 }
568 buf[pos++] = ' ';
569 pos += VG_(sprintf)(buf+pos, "%llu", c[em->index[i]]);
570 i++;
571 }
572 }
573
574 return pos;
575}