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, see <http://www.gnu.org/licenses/>.
24 The GNU General Public License is contained in the file COPYING.
29 /* This should be 2**MAX_EVENTGROUP_COUNT */
30 #define MAX_EVENTSET_COUNT 1024
32 static EventGroup
* eventGroup
[MAX_EVENTGROUP_COUNT
];
33 static EventSet
* eventSetTable
[MAX_EVENTSET_COUNT
];
34 static Bool eventSets_initialized
= 0;
37 void initialize_event_sets(void)
41 if (eventSets_initialized
) return;
43 for(i
=0; i
< MAX_EVENTGROUP_COUNT
; i
++)
46 for(i
=0; i
< MAX_EVENTSET_COUNT
; i
++)
49 eventSets_initialized
= 1;
53 EventGroup
* new_event_group(int id
, int n
)
57 initialize_event_sets();
59 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
60 CLG_ASSERT(eventGroup
[id
]==0);
62 eg
= (EventGroup
*) CLG_MALLOC("cl.events.group.1",
63 sizeof(EventGroup
) + n
* sizeof(HChar
*));
69 EventGroup
* CLG_(register_event_group
) (int id
, const HChar
* n1
)
71 EventGroup
* eg
= new_event_group(id
, 1);
77 EventGroup
* CLG_(register_event_group2
)(int id
, const HChar
* n1
,
80 EventGroup
* eg
= new_event_group(id
, 2);
87 EventGroup
* CLG_(register_event_group3
)(int id
, const HChar
* n1
,
88 const HChar
* n2
, const HChar
* n3
)
90 EventGroup
* eg
= new_event_group(id
, 3);
98 EventGroup
* CLG_(register_event_group4
)(int id
, const HChar
* n1
,
99 const HChar
* n2
, const HChar
* n3
,
102 EventGroup
* eg
= new_event_group(id
, 4);
111 EventGroup
* CLG_(get_event_group
)(int id
)
113 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
115 return eventGroup
[id
];
120 EventSet
* eventset_from_mask(UInt mask
)
123 Int i
, count
, offset
;
125 if (mask
>= MAX_EVENTSET_COUNT
) return 0;
127 initialize_event_sets();
128 if (eventSetTable
[mask
]) return eventSetTable
[mask
];
130 es
= (EventSet
*) CLG_MALLOC("cl.events.eventset.1", sizeof(EventSet
));
135 for(i
=0;i
<MAX_EVENTGROUP_COUNT
;i
++) {
136 es
->offset
[i
] = offset
;
137 if ( ((mask
& (1u<<i
))==0) || (eventGroup
[i
]==0))
140 offset
+= eventGroup
[i
]->size
;
146 eventSetTable
[mask
] = es
;
150 EventSet
* CLG_(get_event_set
)(Int id
)
152 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
153 return eventset_from_mask(1u << id
);
156 EventSet
* CLG_(get_event_set2
)(Int id1
, Int id2
)
158 CLG_ASSERT(id1
>=0 && id1
<MAX_EVENTGROUP_COUNT
);
159 CLG_ASSERT(id2
>=0 && id2
<MAX_EVENTGROUP_COUNT
);
160 return eventset_from_mask((1u << id1
) | (1u << id2
));
163 EventSet
* CLG_(add_event_group
)(EventSet
* es
, Int id
)
165 CLG_ASSERT(id
>=0 && id
<MAX_EVENTGROUP_COUNT
);
166 if (!es
) es
= eventset_from_mask(0);
167 return eventset_from_mask(es
->mask
| (1u << id
));
170 EventSet
* CLG_(add_event_group2
)(EventSet
* es
, Int id1
, Int id2
)
172 CLG_ASSERT(id1
>=0 && id1
<MAX_EVENTGROUP_COUNT
);
173 CLG_ASSERT(id2
>=0 && id2
<MAX_EVENTGROUP_COUNT
);
174 if (!es
) es
= eventset_from_mask(0);
175 return eventset_from_mask(es
->mask
| (1u << id1
) | (1u << id2
));
178 EventSet
* CLG_(add_event_set
)(EventSet
* es1
, EventSet
* es2
)
180 if (!es1
) es1
= eventset_from_mask(0);
181 if (!es2
) es2
= eventset_from_mask(0);
182 return eventset_from_mask(es1
->mask
| es2
->mask
);
186 /* Get cost array for an event set */
187 ULong
* CLG_(get_eventset_cost
)(EventSet
* es
)
189 return CLG_(get_costarray
)(es
->size
);
192 /* Set all costs of an event set to zero */
193 void CLG_(init_cost
)(EventSet
* es
, ULong
* cost
)
199 for(i
=0; i
<es
->size
; i
++)
203 /* Set all costs of an event set to zero */
204 void CLG_(init_cost_lz
)(EventSet
* es
, ULong
** cost
)
208 CLG_ASSERT(cost
!= 0);
210 *cost
= CLG_(get_eventset_cost
)(es
);
212 for(i
=0; i
<es
->size
; i
++)
216 void CLG_(zero_cost
)(EventSet
* es
, ULong
* cost
)
222 for(i
=0;i
<es
->size
;i
++)
226 Bool
CLG_(is_zero_cost
)(EventSet
* es
, ULong
* cost
)
230 if (!cost
) return True
;
232 for(i
=0; i
<es
->size
; i
++)
233 if (cost
[i
] != 0) return False
;
238 void CLG_(copy_cost
)(EventSet
* es
, ULong
* dst
, ULong
* src
)
243 CLG_(zero_cost
)(es
, dst
);
246 CLG_ASSERT(dst
!= 0);
248 for(i
=0;i
<es
->size
;i
++)
252 void CLG_(copy_cost_lz
)(EventSet
* es
, ULong
** pdst
, ULong
* src
)
257 CLG_ASSERT(pdst
!= 0);
260 CLG_(zero_cost
)(es
, *pdst
);
265 dst
= *pdst
= CLG_(get_eventset_cost
)(es
);
267 for(i
=0;i
<es
->size
;i
++)
271 void CLG_(add_cost
)(EventSet
* es
, ULong
* dst
, ULong
* src
)
276 CLG_ASSERT(dst
!= 0);
278 for(i
=0; i
<es
->size
; i
++)
282 void CLG_(add_cost_lz
)(EventSet
* es
, ULong
** pdst
, ULong
* src
)
288 CLG_ASSERT(pdst
!= 0);
292 dst
= *pdst
= CLG_(get_eventset_cost
)(es
);
293 CLG_(copy_cost
)(es
, dst
, src
);
297 for(i
=0; i
<es
->size
; i
++)
301 /* Adds src to dst and zeros src. Returns false if nothing changed */
302 Bool
CLG_(add_and_zero_cost
)(EventSet
* es
, ULong
* dst
, ULong
* src
)
305 Bool is_nonzero
= False
;
307 CLG_ASSERT((es
!= 0) && (dst
!= 0));
308 if (!src
) return False
;
310 for(i
=0; i
<es
->size
; i
++) {
311 if (src
[i
]==0) continue;
320 /* Adds src to dst and zeros src. Returns false if nothing changed */
321 Bool
CLG_(add_and_zero_cost2
)(EventSet
* esDst
, ULong
* dst
,
322 EventSet
* esSrc
, ULong
* src
)
325 Bool is_nonzero
= False
;
328 ULong
*egDst
, *egSrc
;
330 CLG_ASSERT((esDst
!= 0) && (dst
!= 0) && (esSrc
!= 0));
331 if (!src
) return False
;
333 for(i
=0, mask
=1; i
<MAX_EVENTGROUP_COUNT
; i
++, mask
=mask
<<1) {
334 if ((esSrc
->mask
& mask
)==0) continue;
335 if (eventGroup
[i
] ==0) continue;
337 /* if src has a subset, dst must have, too */
338 CLG_ASSERT((esDst
->mask
& mask
)>0);
340 egSrc
= src
+ esSrc
->offset
[i
];
341 egDst
= dst
+ esDst
->offset
[i
];
342 for(j
=0; j
<eg
->size
; j
++) {
343 if (egSrc
[j
]==0) continue;
344 egDst
[j
] += egSrc
[j
];
355 /* Adds difference of new and old to dst, and set old to new.
356 * Returns false if nothing changed */
357 Bool
CLG_(add_diff_cost
)(EventSet
* es
, ULong
* dst
, ULong
* old
, ULong
* new_cost
)
360 Bool is_nonzero
= False
;
362 CLG_ASSERT((es
!= 0) && (dst
!= 0));
363 CLG_ASSERT(old
&& new_cost
);
365 for(i
=0; i
<es
->size
; i
++) {
366 if (new_cost
[i
] == old
[i
]) continue;
367 dst
[i
] += new_cost
[i
] - old
[i
];
368 old
[i
] = new_cost
[i
];
375 Bool
CLG_(add_diff_cost_lz
)(EventSet
* es
, ULong
** pdst
, ULong
* old
, ULong
* new_cost
)
379 Bool is_nonzero
= False
;
381 CLG_ASSERT((es
!= 0) && (pdst
!= 0));
382 CLG_ASSERT(old
&& new_cost
);
386 dst
= *pdst
= CLG_(get_eventset_cost
)(es
);
387 CLG_(zero_cost
)(es
, dst
);
390 for(i
=0; i
<es
->size
; i
++) {
391 if (new_cost
[i
] == old
[i
]) continue;
392 dst
[i
] += new_cost
[i
] - old
[i
];
393 old
[i
] = new_cost
[i
];
401 /* Allocate space for an event mapping */
402 EventMapping
* CLG_(get_eventmapping
)(EventSet
* es
)
408 em
= (EventMapping
*) CLG_MALLOC("cl.events.geMapping.1",
409 sizeof(EventMapping
) +
410 sizeof(struct EventMappingEntry
) *
412 em
->capacity
= es
->size
;
419 void CLG_(append_event
)(EventMapping
* em
, const HChar
* n
)
421 Int i
, j
, offset
= 0;
426 for(i
=0, mask
=1; i
<MAX_EVENTGROUP_COUNT
; i
++, mask
=mask
<<1) {
427 if ((em
->es
->mask
& mask
)==0) continue;
428 if (eventGroup
[i
] ==0) continue;
431 for(j
=0; j
<eg
->size
; j
++, offset
++) {
432 if (VG_(strcmp
)(n
, eg
->name
[j
])!=0)
435 CLG_ASSERT(em
->capacity
> em
->size
);
436 em
->entry
[em
->size
].group
= i
;
437 em
->entry
[em
->size
].index
= j
;
438 em
->entry
[em
->size
].offset
= offset
;
446 /* Returns pointer to dynamically string. The string will be overwritten
447 with each invocation. */
448 HChar
*CLG_(eventmapping_as_string
)(const EventMapping
* em
)
455 XArray
*xa
= VG_(newXA
)(VG_(malloc
), "cl.events.emas", VG_(free
),
458 for(i
=0; i
< em
->size
; i
++) {
460 VG_(xaprintf
)(xa
, "%c", ' ');
462 eg
= eventGroup
[em
->entry
[i
].group
];
464 VG_(xaprintf
)(xa
, "%s", eg
->name
[em
->entry
[i
].index
]);
466 VG_(xaprintf
)(xa
, "%c", '\0'); // zero terminate the string
468 HChar
*buf
= VG_(strdup
)("cl.events.emas", VG_(indexXA
)(xa
, 0));
474 /* Returns pointer to dynamically allocated string. Caller needs to
476 HChar
*CLG_(mappingcost_as_string
)(const EventMapping
* em
, const ULong
* c
)
480 if (!c
|| em
->size
==0) return VG_(strdup
)("cl.events.mcas", "");
482 XArray
*xa
= VG_(newXA
)(VG_(malloc
), "cl.events.mcas", VG_(free
),
485 /* At least one entry */
486 VG_(xaprintf
)(xa
, "%llu", c
[em
->entry
[0].offset
]);
488 for(i
=1; i
<em
->size
; i
++) {
489 if (c
[em
->entry
[i
].offset
] == 0) {
494 VG_(xaprintf
)(xa
, " 0");
497 VG_(xaprintf
)(xa
, " %llu", c
[em
->entry
[i
].offset
]);
499 VG_(xaprintf
)(xa
, "%c", '\0'); // zero terminate the string
501 HChar
*buf
= VG_(strdup
)("cl.events.mas", VG_(indexXA
)(xa
, 0));