Home | History | Annotate | Download | only in callgrind
      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