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