1 /*--------------------------------------------------------------------*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Callgrind, a Valgrind tool for call tracing.
9 Copyright (C) 2002-2017, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
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.
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.
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
26 The GNU General Public License is contained in the file COPYING.
31 /* This should be 2**MAX_EVENTGROUP_COUNT */
32 #define MAX_EVENTSET_COUNT 1024
34 static EventGroup
* eventGroup
[MAX_EVENTGROUP_COUNT
];
35 static EventSet
* eventSetTable
[MAX_EVENTSET_COUNT
];
36 static Bool eventSets_initialized
= 0;
39 void initialize_event_sets(void)
43 if (eventSets_initialized
) return;
45 for(i
=0; i
< MAX_EVENTGROUP_COUNT
; i
++)
48 for(i
=0; i
< MAX_EVENTSET_COUNT
; i
++)
51 eventSets_initialized
= 1;
55 EventGroup
* new_event_group(int id
, int n
)
59 initialize_event_sets();
61 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
62 CLG_ASSERT(eventGroup
[id
]==0);
64 eg
= (EventGroup
*) CLG_MALLOC("cl.events.group.1",
65 sizeof(EventGroup
) + n
* sizeof(HChar
*));
71 EventGroup
* CLG_(register_event_group
) (int id
, const HChar
* n1
)
73 EventGroup
* eg
= new_event_group(id
, 1);
79 EventGroup
* CLG_(register_event_group2
)(int id
, const HChar
* n1
,
82 EventGroup
* eg
= new_event_group(id
, 2);
89 EventGroup
* CLG_(register_event_group3
)(int id
, const HChar
* n1
,
90 const HChar
* n2
, const HChar
* n3
)
92 EventGroup
* eg
= new_event_group(id
, 3);
100 EventGroup
* CLG_(register_event_group4
)(int id
, const HChar
* n1
,
101 const HChar
* n2
, const HChar
* n3
,
104 EventGroup
* eg
= new_event_group(id
, 4);
113 EventGroup
* CLG_(get_event_group
)(int id
)
115 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
117 return eventGroup
[id
];
122 EventSet
* eventset_from_mask(UInt mask
)
125 Int i
, count
, offset
;
127 if (mask
>= MAX_EVENTSET_COUNT
) return 0;
129 initialize_event_sets();
130 if (eventSetTable
[mask
]) return eventSetTable
[mask
];
132 es
= (EventSet
*) CLG_MALLOC("cl.events.eventset.1", sizeof(EventSet
));
137 for(i
=0;i
<MAX_EVENTGROUP_COUNT
;i
++) {
138 es
->offset
[i
] = offset
;
139 if ( ((mask
& (1u<<i
))==0) || (eventGroup
[i
]==0))
142 offset
+= eventGroup
[i
]->size
;
148 eventSetTable
[mask
] = es
;
152 EventSet
* CLG_(get_event_set
)(Int id
)
154 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
155 return eventset_from_mask(1u << id
);
158 EventSet
* CLG_(get_event_set2
)(Int id1
, Int id2
)
160 CLG_ASSERT(id1
>=0 && id1
<MAX_EVENTGROUP_COUNT
);
161 CLG_ASSERT(id2
>=0 && id2
<MAX_EVENTGROUP_COUNT
);
162 return eventset_from_mask((1u << id1
) | (1u << id2
));
165 EventSet
* CLG_(add_event_group
)(EventSet
* es
, Int id
)
167 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
168 if (!es
) es
= eventset_from_mask(0);
169 return eventset_from_mask(es
->mask
| (1u << id
));
172 EventSet
* CLG_(add_event_group2
)(EventSet
* es
, Int id1
, Int id2
)
174 CLG_ASSERT(id1
>=0 && id1
<MAX_EVENTGROUP_COUNT
);
175 CLG_ASSERT(id2
>=0 && id2
<MAX_EVENTGROUP_COUNT
);
176 if (!es
) es
= eventset_from_mask(0);
177 return eventset_from_mask(es
->mask
| (1u << id1
) | (1u << id2
));
180 EventSet
* CLG_(add_event_set
)(EventSet
* es1
, EventSet
* es2
)
182 if (!es1
) es1
= eventset_from_mask(0);
183 if (!es2
) es2
= eventset_from_mask(0);
184 return eventset_from_mask(es1
->mask
| es2
->mask
);
188 /* Get cost array for an event set */
189 ULong
* CLG_(get_eventset_cost
)(EventSet
* es
)
191 return CLG_(get_costarray
)(es
->size
);
194 /* Set all costs of an event set to zero */
195 void CLG_(init_cost
)(EventSet
* es
, ULong
* cost
)
201 for(i
=0; i
<es
->size
; i
++)
205 /* Set all costs of an event set to zero */
206 void CLG_(init_cost_lz
)(EventSet
* es
, ULong
** cost
)
210 CLG_ASSERT(cost
!= 0);
212 *cost
= CLG_(get_eventset_cost
)(es
);
214 for(i
=0; i
<es
->size
; i
++)
218 void CLG_(zero_cost
)(EventSet
* es
, ULong
* cost
)
224 for(i
=0;i
<es
->size
;i
++)
228 Bool
CLG_(is_zero_cost
)(EventSet
* es
, ULong
* cost
)
232 if (!cost
) return True
;
234 for(i
=0; i
<es
->size
; i
++)
235 if (cost
[i
] != 0) return False
;
240 void CLG_(copy_cost
)(EventSet
* es
, ULong
* dst
, ULong
* src
)
245 CLG_(zero_cost
)(es
, dst
);
248 CLG_ASSERT(dst
!= 0);
250 for(i
=0;i
<es
->size
;i
++)
254 void CLG_(copy_cost_lz
)(EventSet
* es
, ULong
** pdst
, ULong
* src
)
259 CLG_ASSERT(pdst
!= 0);
262 CLG_(zero_cost
)(es
, *pdst
);
267 dst
= *pdst
= CLG_(get_eventset_cost
)(es
);
269 for(i
=0;i
<es
->size
;i
++)
273 void CLG_(add_cost
)(EventSet
* es
, ULong
* dst
, ULong
* src
)
278 CLG_ASSERT(dst
!= 0);
280 for(i
=0; i
<es
->size
; i
++)
284 void CLG_(add_cost_lz
)(EventSet
* es
, ULong
** pdst
, ULong
* src
)
290 CLG_ASSERT(pdst
!= 0);
294 dst
= *pdst
= CLG_(get_eventset_cost
)(es
);
295 CLG_(copy_cost
)(es
, dst
, src
);
299 for(i
=0; i
<es
->size
; i
++)
303 /* Adds src to dst and zeros src. Returns false if nothing changed */
304 Bool
CLG_(add_and_zero_cost
)(EventSet
* es
, ULong
* dst
, ULong
* src
)
307 Bool is_nonzero
= False
;
309 CLG_ASSERT((es
!= 0) && (dst
!= 0));
310 if (!src
) return False
;
312 for(i
=0; i
<es
->size
; i
++) {
313 if (src
[i
]==0) continue;
322 /* Adds src to dst and zeros src. Returns false if nothing changed */
323 Bool
CLG_(add_and_zero_cost2
)(EventSet
* esDst
, ULong
* dst
,
324 EventSet
* esSrc
, ULong
* src
)
327 Bool is_nonzero
= False
;
330 ULong
*egDst
, *egSrc
;
332 CLG_ASSERT((esDst
!= 0) && (dst
!= 0) && (esSrc
!= 0));
333 if (!src
) return False
;
335 for(i
=0, mask
=1; i
<MAX_EVENTGROUP_COUNT
; i
++, mask
=mask
<<1) {
336 if ((esSrc
->mask
& mask
)==0) continue;
337 if (eventGroup
[i
] ==0) continue;
339 /* if src has a subset, dst must have, too */
340 CLG_ASSERT((esDst
->mask
& mask
)>0);
342 egSrc
= src
+ esSrc
->offset
[i
];
343 egDst
= dst
+ esDst
->offset
[i
];
344 for(j
=0; j
<eg
->size
; j
++) {
345 if (egSrc
[j
]==0) continue;
346 egDst
[j
] += egSrc
[j
];
357 /* Adds difference of new and old to dst, and set old to new.
358 * Returns false if nothing changed */
359 Bool
CLG_(add_diff_cost
)(EventSet
* es
, ULong
* dst
, ULong
* old
, ULong
* new_cost
)
362 Bool is_nonzero
= False
;
364 CLG_ASSERT((es
!= 0) && (dst
!= 0));
365 CLG_ASSERT(old
&& new_cost
);
367 for(i
=0; i
<es
->size
; i
++) {
368 if (new_cost
[i
] == old
[i
]) continue;
369 dst
[i
] += new_cost
[i
] - old
[i
];
370 old
[i
] = new_cost
[i
];
377 Bool
CLG_(add_diff_cost_lz
)(EventSet
* es
, ULong
** pdst
, ULong
* old
, ULong
* new_cost
)
381 Bool is_nonzero
= False
;
383 CLG_ASSERT((es
!= 0) && (pdst
!= 0));
384 CLG_ASSERT(old
&& new_cost
);
388 dst
= *pdst
= CLG_(get_eventset_cost
)(es
);
389 CLG_(zero_cost
)(es
, dst
);
392 for(i
=0; i
<es
->size
; i
++) {
393 if (new_cost
[i
] == old
[i
]) continue;
394 dst
[i
] += new_cost
[i
] - old
[i
];
395 old
[i
] = new_cost
[i
];
403 /* Allocate space for an event mapping */
404 EventMapping
* CLG_(get_eventmapping
)(EventSet
* es
)
410 em
= (EventMapping
*) CLG_MALLOC("cl.events.geMapping.1",
411 sizeof(EventMapping
) +
412 sizeof(struct EventMappingEntry
) *
414 em
->capacity
= es
->size
;
421 void CLG_(append_event
)(EventMapping
* em
, const HChar
* n
)
423 Int i
, j
, offset
= 0;
428 for(i
=0, mask
=1; i
<MAX_EVENTGROUP_COUNT
; i
++, mask
=mask
<<1) {
429 if ((em
->es
->mask
& mask
)==0) continue;
430 if (eventGroup
[i
] ==0) continue;
433 for(j
=0; j
<eg
->size
; j
++, offset
++) {
434 if (VG_(strcmp
)(n
, eg
->name
[j
])!=0)
437 CLG_ASSERT(em
->capacity
> em
->size
);
438 em
->entry
[em
->size
].group
= i
;
439 em
->entry
[em
->size
].index
= j
;
440 em
->entry
[em
->size
].offset
= offset
;
448 /* Returns pointer to dynamically string. The string will be overwritten
449 with each invocation. */
450 HChar
*CLG_(eventmapping_as_string
)(const EventMapping
* em
)
457 XArray
*xa
= VG_(newXA
)(VG_(malloc
), "cl.events.emas", VG_(free
),
460 for(i
=0; i
< em
->size
; i
++) {
462 VG_(xaprintf
)(xa
, "%c", ' ');
464 eg
= eventGroup
[em
->entry
[i
].group
];
466 VG_(xaprintf
)(xa
, "%s", eg
->name
[em
->entry
[i
].index
]);
468 VG_(xaprintf
)(xa
, "%c", '\0'); // zero terminate the string
470 HChar
*buf
= VG_(strdup
)("cl.events.emas", VG_(indexXA
)(xa
, 0));
476 /* Returns pointer to dynamically allocated string. Caller needs to
478 HChar
*CLG_(mappingcost_as_string
)(const EventMapping
* em
, const ULong
* c
)
482 if (!c
|| em
->size
==0) return VG_(strdup
)("cl.events.mcas", "");
484 XArray
*xa
= VG_(newXA
)(VG_(malloc
), "cl.events.mcas", VG_(free
),
487 /* At least one entry */
488 VG_(xaprintf
)(xa
, "%llu", c
[em
->entry
[0].offset
]);
490 for(i
=1; i
<em
->size
; i
++) {
491 if (c
[em
->entry
[i
].offset
] == 0) {
496 VG_(xaprintf
)(xa
, " 0");
499 VG_(xaprintf
)(xa
, " %llu", c
[em
->entry
[i
].offset
]);
501 VG_(xaprintf
)(xa
, "%c", '\0'); // zero terminate the string
503 HChar
*buf
= VG_(strdup
)("cl.events.mas", VG_(indexXA
)(xa
, 0));