• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*--------------------------------------------------------------------*/
2 /*--- Callgrind                                                    ---*/
3 /*---                                                     events.c ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Callgrind, a Valgrind tool for call tracing.
8 
9    Copyright (C) 2002-2010, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
10 
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 /* This should be 2**MAX_EVENTGROUP_COUNT */
32 #define MAX_EVENTSET_COUNT 1024
33 
34 static EventGroup* eventGroup[MAX_EVENTGROUP_COUNT];
35 static EventSet* eventSetTable[MAX_EVENTSET_COUNT];
36 static Bool eventSets_initialized = 0;
37 
38 static
initialize_event_sets(void)39 void initialize_event_sets(void)
40 {
41     Int i;
42 
43     if (eventSets_initialized) return;
44 
45     for(i=0; i< MAX_EVENTGROUP_COUNT; i++)
46 	eventGroup[i] = 0;
47 
48     for(i=0; i< MAX_EVENTSET_COUNT; i++)
49 	eventSetTable[i] = 0;
50 
51     eventSets_initialized = 1;
52  }
53 
54 static
new_event_group(int id,int n)55 EventGroup* new_event_group(int id, int n)
56 {
57     EventGroup* eg;
58 
59     initialize_event_sets();
60 
61     CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
62     CLG_ASSERT(eventGroup[id]==0);
63 
64     eg = (EventGroup*) CLG_MALLOC("cl.events.group.1",
65 				  sizeof(EventGroup) + n * sizeof(Char*));
66     eg->size = n;
67     eventGroup[id] = eg;
68     return eg;
69 }
70 
CLG_(register_event_group)71 EventGroup* CLG_(register_event_group) (int id, Char* n1)
72 {
73     EventGroup* eg = new_event_group(id, 1);
74     eg->name[0] = n1;
75 
76     return eg;
77 }
78 
CLG_(register_event_group2)79 EventGroup* CLG_(register_event_group2)(int id, Char* n1, Char* n2)
80 {
81     EventGroup* eg = new_event_group(id, 2);
82     eg->name[0] = n1;
83     eg->name[1] = n2;
84 
85     return eg;
86 }
87 
CLG_(register_event_group3)88 EventGroup* CLG_(register_event_group3)(int id, Char* n1, Char* n2, Char* n3)
89 {
90     EventGroup* eg = new_event_group(id, 3);
91     eg->name[0] = n1;
92     eg->name[1] = n2;
93     eg->name[2] = n3;
94 
95     return eg;
96 }
97 
CLG_(register_event_group4)98 EventGroup* CLG_(register_event_group4)(int id,
99 					Char* n1, Char* n2, Char* n3, Char* n4)
100 {
101     EventGroup* eg = new_event_group(id, 4);
102     eg->name[0] = n1;
103     eg->name[1] = n2;
104     eg->name[2] = n3;
105     eg->name[3] = n4;
106 
107     return eg;
108 }
109 
CLG_(get_event_group)110 EventGroup* CLG_(get_event_group)(int id)
111 {
112     CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
113 
114     return eventGroup[id];
115 }
116 
117 
118 static
eventset_from_mask(UInt mask)119 EventSet* eventset_from_mask(UInt mask)
120 {
121     EventSet* es;
122     Int i, count, offset;
123 
124     if (mask >= MAX_EVENTSET_COUNT) return 0;
125 
126     initialize_event_sets();
127     if (eventSetTable[mask]) return eventSetTable[mask];
128 
129     es = (EventSet*) CLG_MALLOC("cl.events.eventset.1", sizeof(EventSet));
130     es->mask = mask;
131 
132     offset = 0;
133     count = 0;
134     for(i=0;i<MAX_EVENTGROUP_COUNT;i++) {
135 	es->offset[i] = offset;
136 	if ( ((mask & (1u<<i))==0) || (eventGroup[i]==0))
137 	    continue;
138 
139 	offset += eventGroup[i]->size;
140 	count++;
141     }
142     es->size = offset;
143     es->count = count;
144 
145     eventSetTable[mask] = es;
146     return es;
147 }
148 
CLG_(get_event_set)149 EventSet* CLG_(get_event_set)(Int id)
150 {
151     CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
152     return eventset_from_mask(1u << id);
153 }
154 
CLG_(get_event_set2)155 EventSet* CLG_(get_event_set2)(Int id1, Int id2)
156 {
157     CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
158     CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
159     return eventset_from_mask((1u << id1) | (1u << id2));
160 }
161 
CLG_(get_event_set3)162 EventSet* CLG_(get_event_set3)(Int id1, Int id2, Int id3)
163 {
164     CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
165     CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
166     CLG_ASSERT(id3>=0 && id3<MAX_EVENTGROUP_COUNT);
167     return eventset_from_mask((1u << id1) | (1u << id2) | (1u << id3));
168 }
169 
CLG_(add_event_group)170 EventSet* CLG_(add_event_group)(EventSet* es, Int id)
171 {
172     CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
173     if (!es) es = eventset_from_mask(0);
174     return eventset_from_mask(es->mask | (1u << id));
175 }
176 
CLG_(add_event_group2)177 EventSet* CLG_(add_event_group2)(EventSet* es, Int id1, Int id2)
178 {
179     CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
180     CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
181     if (!es) es = eventset_from_mask(0);
182     return eventset_from_mask(es->mask | (1u << id1) | (1u << id2));
183 }
184 
CLG_(add_event_set)185 EventSet* CLG_(add_event_set)(EventSet* es1, EventSet* es2)
186 {
187     if (!es1) es1 = eventset_from_mask(0);
188     if (!es2) es2 = eventset_from_mask(0);
189     return eventset_from_mask(es1->mask | es2->mask);
190 }
191 
CLG_(sprint_eventset)192 Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
193 {
194     Int i, j, pos;
195     UInt mask;
196     EventGroup* eg;
197 
198 
199     CLG_ASSERT(es->size >0);
200     pos = 0;
201     for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
202 	if ((es->mask & mask)==0) continue;
203 	if (eventGroup[i] ==0) continue;
204 
205 	eg = eventGroup[i];
206 	for(j=0; j<eg->size; j++) {
207 	    if (pos>0) buf[pos++] = ' ';
208 	    pos += VG_(sprintf)(buf + pos, "%s", eg->name[j]);
209 	}
210     }
211     buf[pos] = 0;
212 
213     return pos;
214 }
215 
216 
217 /* Get cost array for an event set */
CLG_(get_eventset_cost)218 ULong* CLG_(get_eventset_cost)(EventSet* es)
219 {
220     return CLG_(get_costarray)(es->size);
221 }
222 
223 /* Set all costs of an event set to zero */
CLG_(init_cost)224 void CLG_(init_cost)(EventSet* es, ULong* cost)
225 {
226     Int i;
227 
228     if (!cost) return;
229 
230     for(i=0; i<es->size; i++)
231 	cost[i] = 0;
232 }
233 
234 /* Set all costs of an event set to zero */
CLG_(init_cost_lz)235 void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
236 {
237     Int i;
238 
239     CLG_ASSERT(cost != 0);
240     if (!(*cost))
241 	*cost = CLG_(get_eventset_cost)(es);
242 
243     for(i=0; i<es->size; i++)
244 	(*cost)[i] = 0;
245 }
246 
CLG_(zero_cost)247 void CLG_(zero_cost)(EventSet* es, ULong* cost)
248 {
249     Int i;
250 
251     if (!cost) return;
252 
253     for(i=0;i<es->size;i++)
254 	cost[i] = 0;
255 }
256 
CLG_(is_zero_cost)257 Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
258 {
259     Int i;
260 
261     if (!cost) return True;
262 
263     for(i=0; i<es->size; i++)
264 	if (cost[i] != 0) return False;
265 
266     return True;
267 }
268 
CLG_(is_equal_cost)269 Bool CLG_(is_equal_cost)(EventSet* es, ULong* c1, ULong* c2)
270 {
271     Int i;
272 
273     if (!c1) return CLG_(is_zero_cost)(es, c2);
274     if (!c2) return CLG_(is_zero_cost)(es, c1);
275 
276     for(i=0; i<es->size; i++)
277 	if (c1[i] != c2[i]) return False;
278 
279     return True;
280 }
281 
CLG_(copy_cost)282 void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
283 {
284     Int i;
285 
286     if (!src) {
287 	CLG_(zero_cost)(es, dst);
288 	return;
289     }
290     CLG_ASSERT(dst != 0);
291 
292     for(i=0;i<es->size;i++)
293 	dst[i] = src[i];
294 }
295 
CLG_(copy_cost_lz)296 void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
297 {
298     Int i;
299     ULong* dst;
300 
301     CLG_ASSERT(pdst != 0);
302 
303     if (!src) {
304 	CLG_(zero_cost)(es, *pdst);
305 	return;
306     }
307     dst = *pdst;
308     if (!dst)
309 	dst = *pdst = CLG_(get_eventset_cost)(es);
310 
311     for(i=0;i<es->size;i++)
312 	dst[i] = src[i];
313 }
314 
CLG_(add_cost)315 void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
316 {
317     Int i;
318 
319     if (!src) return;
320     CLG_ASSERT(dst != 0);
321 
322     for(i=0; i<es->size; i++)
323 	dst[i] += src[i];
324 }
325 
CLG_(add_cost_lz)326 void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
327 {
328     Int i;
329     ULong* dst;
330 
331     if (!src) return;
332     CLG_ASSERT(pdst != 0);
333 
334     dst = *pdst;
335     if (!dst) {
336 	dst = *pdst = CLG_(get_eventset_cost)(es);
337 	CLG_(copy_cost)(es, dst, src);
338 	return;
339     }
340 
341     for(i=0; i<es->size; i++)
342 	dst[i] += src[i];
343 }
344 
345 /* Adds src to dst and zeros src. Returns false if nothing changed */
CLG_(add_and_zero_cost)346 Bool CLG_(add_and_zero_cost)(EventSet* es, ULong* dst, ULong* src)
347 {
348     Int i;
349     Bool is_nonzero = False;
350 
351     CLG_ASSERT((es != 0) && (dst != 0));
352     if (!src) return False;
353 
354     for(i=0; i<es->size; i++) {
355 	if (src[i]==0) continue;
356 	dst[i] += src[i];
357 	src[i] = 0;
358 	is_nonzero = True;
359     }
360 
361     return is_nonzero;
362 }
363 
364 /* Adds src to dst and zeros src. Returns false if nothing changed */
CLG_(add_and_zero_cost2)365 Bool CLG_(add_and_zero_cost2)(EventSet* esDst, ULong* dst,
366 			      EventSet* esSrc, ULong* src)
367 {
368     Int i,j;
369     Bool is_nonzero = False;
370     UInt mask;
371     EventGroup *eg;
372     ULong *egDst, *egSrc;
373 
374     CLG_ASSERT((esDst != 0) && (dst != 0) && (esSrc != 0));
375     if (!src) return False;
376 
377     for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
378 	if ((esSrc->mask & mask)==0) continue;
379 	if (eventGroup[i] ==0) continue;
380 
381 	/* if src has a subset, dst must have, too */
382 	CLG_ASSERT((esDst->mask & mask)>0);
383 	eg = eventGroup[i];
384 	egSrc = src + esSrc->offset[i];
385 	egDst = dst + esDst->offset[i];
386 	for(j=0; j<eg->size; j++) {
387 	    if (egSrc[j]==0) continue;
388 	    egDst[j] += egSrc[j];
389 	    egSrc[j] = 0;
390 	    is_nonzero = True;
391 	}
392     }
393 
394     return is_nonzero;
395 }
396 
397 
398 
399 /* Adds difference of new and old to dst, and set old to new.
400  * Returns false if nothing changed */
CLG_(add_diff_cost)401 Bool CLG_(add_diff_cost)(EventSet* es, ULong* dst, ULong* old, ULong* new_cost)
402 {
403     Int i;
404     Bool is_nonzero = False;
405 
406     CLG_ASSERT((es != 0) && (dst != 0));
407     CLG_ASSERT(old && new_cost);
408 
409     for(i=0; i<es->size; i++) {
410 	if (new_cost[i] == old[i]) continue;
411 	dst[i] += new_cost[i] - old[i];
412 	old[i] = new_cost[i];
413 	is_nonzero = True;
414     }
415 
416     return is_nonzero;
417 }
418 
CLG_(add_diff_cost_lz)419 Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst, ULong* old, ULong* new_cost)
420 {
421     Int i;
422     ULong* dst;
423     Bool is_nonzero = False;
424 
425     CLG_ASSERT((es != 0) && (pdst != 0));
426     CLG_ASSERT(old && new_cost);
427 
428     dst = *pdst;
429     if (!dst) {
430 	dst = *pdst = CLG_(get_eventset_cost)(es);
431 	CLG_(zero_cost)(es, dst);
432     }
433 
434     for(i=0; i<es->size; i++) {
435 	if (new_cost[i] == old[i]) continue;
436 	dst[i] += new_cost[i] - old[i];
437 	old[i] = new_cost[i];
438 	is_nonzero = True;
439     }
440 
441     return is_nonzero;
442 }
443 
444 
445 /* Returns number of characters written */
CLG_(sprint_cost)446 Int CLG_(sprint_cost)(Char* buf, EventSet* es, ULong* c)
447 {
448     Int i, pos, skipped = 0;
449 
450     if (!c || es->size==0) return 0;
451 
452     /* At least one entry */
453     pos = VG_(sprintf)(buf, "%llu", c[0]);
454     for(i=1; i<es->size; i++) {
455 	if (c[i] == 0) {
456 	    skipped++;
457 	    continue;
458 	}
459 	while(skipped>0) {
460 	    buf[pos++] = ' ';
461 	    buf[pos++] = '0';
462 	    skipped--;
463 	}
464 	buf[pos++] = ' ';
465 	pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
466     }
467 
468     return pos;
469 }
470 
471 
472 /* Allocate space for an event mapping */
CLG_(get_eventmapping)473 EventMapping* CLG_(get_eventmapping)(EventSet* es)
474 {
475     EventMapping* em;
476 
477     CLG_ASSERT(es != 0);
478 
479     em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
480 				    sizeof(EventMapping) +
481 				    sizeof(struct EventMappingEntry) *
482 				    es->size);
483     em->capacity = es->size;
484     em->size = 0;
485     em->es = es;
486 
487     return em;
488 }
489 
CLG_(append_event)490 void CLG_(append_event)(EventMapping* em, Char* n)
491 {
492     Int i, j, offset = 0;
493     UInt mask;
494     EventGroup* eg;
495 
496     CLG_ASSERT(em != 0);
497     for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
498 	if ((em->es->mask & mask)==0) continue;
499 	if (eventGroup[i] ==0) continue;
500 
501 	eg = eventGroup[i];
502 	for(j=0; j<eg->size; j++, offset++) {
503 	    if (VG_(strcmp)(n, eg->name[j])!=0)
504 		    continue;
505 
506 	    CLG_ASSERT(em->capacity > em->size);
507 	    em->entry[em->size].group = i;
508 	    em->entry[em->size].index = j;
509 	    em->entry[em->size].offset = offset;
510 	    em->size++;
511 	    return;
512 	}
513     }
514 }
515 
516 
517 /* Returns number of characters written */
CLG_(sprint_eventmapping)518 Int CLG_(sprint_eventmapping)(Char* buf, EventMapping* em)
519 {
520     Int i, pos = 0;
521     EventGroup* eg;
522 
523     CLG_ASSERT(em != 0);
524 
525     for(i=0; i< em->size; i++) {
526 	if (pos>0) buf[pos++] = ' ';
527 	eg = eventGroup[em->entry[i].group];
528 	CLG_ASSERT(eg != 0);
529 	pos += VG_(sprintf)(buf + pos, "%s", eg->name[em->entry[i].index]);
530     }
531     buf[pos] = 0;
532 
533     return pos;
534 }
535 
536 /* Returns number of characters written */
CLG_(sprint_mappingcost)537 Int CLG_(sprint_mappingcost)(Char* buf, EventMapping* em, ULong* c)
538 {
539     Int i, pos, skipped = 0;
540 
541     if (!c || em->size==0) return 0;
542 
543     /* At least one entry */
544     pos = VG_(sprintf)(buf, "%llu", c[em->entry[0].offset]);
545 
546     for(i=1; i<em->size; i++) {
547 	if (c[em->entry[i].offset] == 0) {
548 	    skipped++;
549 	    continue;
550 	}
551 	while(skipped>0) {
552 	    buf[pos++] = ' ';
553 	    buf[pos++] = '0';
554 	    skipped--;
555 	}
556 	buf[pos++] = ' ';
557 	pos += VG_(sprintf)(buf+pos, "%llu", c[em->entry[i].offset]);
558     }
559 
560     return pos;
561 }
562