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 (at) 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 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 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(HChar*)); 66 eg->size = n; 67 eventGroup[id] = eg; 68 return eg; 69 } 70 71 EventGroup* 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 79 EventGroup* 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 89 EventGroup* 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 100 EventGroup* 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 113 EventGroup* CLG_(get_event_group)(int id) 114 { 115 CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT); 116 117 return eventGroup[id]; 118 } 119 120 121 static 122 EventSet* 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 152 EventSet* 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 158 EventSet* 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 165 EventSet* 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 173 EventSet* 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 180 EventSet* 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 188 EventSet* 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 195 Int 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 */ 221 ULong* 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 */ 227 void 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 */ 238 void 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 250 void 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 260 Bool 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 272 Bool 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 285 void 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 299 void 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 318 void 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 329 void 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 */ 349 Bool 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 */ 368 Bool 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 */ 404 Bool 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 422 Bool 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 */ 449 Int 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 */ 476 EventMapping* 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 493 void 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 */ 521 Int 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 */ 540 Int 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