FreeBSD regtest: add fakes for FreeBSD < 13
[valgrind.git] / callgrind / events.c
blob4b0394f6e3a7044efd8280e385d0ee737b379b34
1 /*--------------------------------------------------------------------*/
2 /*--- Callgrind ---*/
3 /*--- events.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
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.
27 #include "global.h"
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;
36 static
37 void initialize_event_sets(void)
39 Int i;
41 if (eventSets_initialized) return;
43 for(i=0; i< MAX_EVENTGROUP_COUNT; i++)
44 eventGroup[i] = 0;
46 for(i=0; i< MAX_EVENTSET_COUNT; i++)
47 eventSetTable[i] = 0;
49 eventSets_initialized = 1;
52 static
53 EventGroup* new_event_group(int id, int n)
55 EventGroup* eg;
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*));
64 eg->size = n;
65 eventGroup[id] = eg;
66 return eg;
69 EventGroup* CLG_(register_event_group) (int id, const HChar* n1)
71 EventGroup* eg = new_event_group(id, 1);
72 eg->name[0] = n1;
74 return eg;
77 EventGroup* CLG_(register_event_group2)(int id, const HChar* n1,
78 const HChar* n2)
80 EventGroup* eg = new_event_group(id, 2);
81 eg->name[0] = n1;
82 eg->name[1] = n2;
84 return eg;
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);
91 eg->name[0] = n1;
92 eg->name[1] = n2;
93 eg->name[2] = n3;
95 return eg;
98 EventGroup* CLG_(register_event_group4)(int id, const HChar* n1,
99 const HChar* n2, const HChar* n3,
100 const HChar* n4)
102 EventGroup* eg = new_event_group(id, 4);
103 eg->name[0] = n1;
104 eg->name[1] = n2;
105 eg->name[2] = n3;
106 eg->name[3] = n4;
108 return eg;
111 EventGroup* CLG_(get_event_group)(int id)
113 CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
115 return eventGroup[id];
119 static
120 EventSet* eventset_from_mask(UInt mask)
122 EventSet* es;
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));
131 es->mask = mask;
133 offset = 0;
134 count = 0;
135 for(i=0;i<MAX_EVENTGROUP_COUNT;i++) {
136 es->offset[i] = offset;
137 if ( ((mask & (1u<<i))==0) || (eventGroup[i]==0))
138 continue;
140 offset += eventGroup[i]->size;
141 count++;
143 es->size = offset;
144 es->count = count;
146 eventSetTable[mask] = es;
147 return 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)
195 Int i;
197 if (!cost) return;
199 for(i=0; i<es->size; i++)
200 cost[i] = 0;
203 /* Set all costs of an event set to zero */
204 void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
206 Int i;
208 CLG_ASSERT(cost != 0);
209 if (!(*cost))
210 *cost = CLG_(get_eventset_cost)(es);
212 for(i=0; i<es->size; i++)
213 (*cost)[i] = 0;
216 void CLG_(zero_cost)(EventSet* es, ULong* cost)
218 Int i;
220 if (!cost) return;
222 for(i=0;i<es->size;i++)
223 cost[i] = 0;
226 Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
228 Int i;
230 if (!cost) return True;
232 for(i=0; i<es->size; i++)
233 if (cost[i] != 0) return False;
235 return True;
238 void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
240 Int i;
242 if (!src) {
243 CLG_(zero_cost)(es, dst);
244 return;
246 CLG_ASSERT(dst != 0);
248 for(i=0;i<es->size;i++)
249 dst[i] = src[i];
252 void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
254 Int i;
255 ULong* dst;
257 CLG_ASSERT(pdst != 0);
259 if (!src) {
260 CLG_(zero_cost)(es, *pdst);
261 return;
263 dst = *pdst;
264 if (!dst)
265 dst = *pdst = CLG_(get_eventset_cost)(es);
267 for(i=0;i<es->size;i++)
268 dst[i] = src[i];
271 void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
273 Int i;
275 if (!src) return;
276 CLG_ASSERT(dst != 0);
278 for(i=0; i<es->size; i++)
279 dst[i] += src[i];
282 void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
284 Int i;
285 ULong* dst;
287 if (!src) return;
288 CLG_ASSERT(pdst != 0);
290 dst = *pdst;
291 if (!dst) {
292 dst = *pdst = CLG_(get_eventset_cost)(es);
293 CLG_(copy_cost)(es, dst, src);
294 return;
297 for(i=0; i<es->size; i++)
298 dst[i] += src[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)
304 Int i;
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;
312 dst[i] += src[i];
313 src[i] = 0;
314 is_nonzero = True;
317 return is_nonzero;
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)
324 Int i,j;
325 Bool is_nonzero = False;
326 UInt mask;
327 EventGroup *eg;
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);
339 eg = eventGroup[i];
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];
345 egSrc[j] = 0;
346 is_nonzero = True;
350 return is_nonzero;
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)
359 Int i;
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];
369 is_nonzero = True;
372 return is_nonzero;
375 Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst, ULong* old, ULong* new_cost)
377 Int i;
378 ULong* dst;
379 Bool is_nonzero = False;
381 CLG_ASSERT((es != 0) && (pdst != 0));
382 CLG_ASSERT(old && new_cost);
384 dst = *pdst;
385 if (!dst) {
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];
394 is_nonzero = True;
397 return is_nonzero;
401 /* Allocate space for an event mapping */
402 EventMapping* CLG_(get_eventmapping)(EventSet* es)
404 EventMapping* em;
406 CLG_ASSERT(es != 0);
408 em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
409 sizeof(EventMapping) +
410 sizeof(struct EventMappingEntry) *
411 es->size);
412 em->capacity = es->size;
413 em->size = 0;
414 em->es = es;
416 return em;
419 void CLG_(append_event)(EventMapping* em, const HChar* n)
421 Int i, j, offset = 0;
422 UInt mask;
423 EventGroup* eg;
425 CLG_ASSERT(em != 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;
430 eg = eventGroup[i];
431 for(j=0; j<eg->size; j++, offset++) {
432 if (VG_(strcmp)(n, eg->name[j])!=0)
433 continue;
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;
439 em->size++;
440 return;
446 /* Returns pointer to dynamically string. The string will be overwritten
447 with each invocation. */
448 HChar *CLG_(eventmapping_as_string)(const EventMapping* em)
450 Int i;
451 EventGroup* eg;
453 CLG_ASSERT(em != 0);
455 XArray *xa = VG_(newXA)(VG_(malloc), "cl.events.emas", VG_(free),
456 sizeof(HChar));
458 for(i=0; i< em->size; i++) {
459 if (i > 0) {
460 VG_(xaprintf)(xa, "%c", ' ');
462 eg = eventGroup[em->entry[i].group];
463 CLG_ASSERT(eg != 0);
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));
469 VG_(deleteXA)(xa);
471 return buf;
474 /* Returns pointer to dynamically allocated string. Caller needs to
475 VG_(free) it. */
476 HChar *CLG_(mappingcost_as_string)(const EventMapping* em, const ULong* c)
478 Int i, skipped = 0;
480 if (!c || em->size==0) return VG_(strdup)("cl.events.mcas", "");
482 XArray *xa = VG_(newXA)(VG_(malloc), "cl.events.mcas", VG_(free),
483 sizeof(HChar));
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) {
490 skipped++;
491 continue;
493 while(skipped>0) {
494 VG_(xaprintf)(xa, " 0");
495 skipped--;
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));
502 VG_(deleteXA)(xa);
504 return buf;