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-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