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