mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
gcc-4.3.2 shipped with Ubuntu 8.10. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8723
578 lines
11 KiB
C
578 lines
11 KiB
C
/*--------------------------------------------------------------------*/
|
|
/*--- Callgrind ---*/
|
|
/*--- events.c ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Callgrind, a Valgrind tool for call tracing.
|
|
|
|
Copyright (C) 2002-2008, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307, USA.
|
|
|
|
The GNU General Public License is contained in the file COPYING.
|
|
*/
|
|
|
|
#include "global.h"
|
|
|
|
#define MAX_EVENTTYPE 20
|
|
|
|
static EventType eventtype[MAX_EVENTTYPE];
|
|
static Int eventtype_count = 0;
|
|
|
|
EventType* CLG_(register_eventtype)(Char* name)
|
|
{
|
|
EventType* et;
|
|
|
|
if (eventtype_count == MAX_EVENTTYPE) {
|
|
VG_(printf)("\nMore than %d event types used!\n"
|
|
"Increase MAX_EVENTTYPE in ct_events.c and recomile this tool!\n",
|
|
MAX_EVENTTYPE);
|
|
VG_(tool_panic)("Too many event types requested.");
|
|
}
|
|
|
|
et = &(eventtype[eventtype_count]);
|
|
et->id = eventtype_count;
|
|
et->name = (UChar*) VG_(strdup)("cl.events.re.1", name);
|
|
et->description = 0;
|
|
|
|
eventtype_count++;
|
|
|
|
return et;
|
|
}
|
|
|
|
|
|
EventType* CLG_(get_eventtype)(Char* name)
|
|
{
|
|
Int i;
|
|
|
|
for(i=0;i<eventtype_count;i++)
|
|
if (VG_(strcmp)(eventtype[i].name, name) == 0)
|
|
return eventtype+i;
|
|
return 0;
|
|
}
|
|
|
|
EventType* CLG_(get_eventtype_byindex)(Int id)
|
|
{
|
|
if ((id >= 0) && (id < eventtype_count))
|
|
return eventtype+id;
|
|
return 0;
|
|
}
|
|
|
|
/* Allocate space for an event set */
|
|
EventSet* CLG_(get_eventset)(Char* n, Int capacity)
|
|
{
|
|
EventSet* es;
|
|
|
|
es = (EventSet*) CLG_MALLOC("cl.events.geSet.1",
|
|
sizeof(EventSet) +
|
|
capacity * sizeof(EventSetEntry));
|
|
es->capacity = capacity;
|
|
es->size = 0;
|
|
es->name = n;
|
|
|
|
return es;
|
|
}
|
|
|
|
/* Incorporate a event type into a set, get start offset */
|
|
Int CLG_(add_eventtype)(EventSet* es, EventType* t)
|
|
{
|
|
Int offset = es->size;
|
|
if (es->capacity - offset < 1) return -1;
|
|
|
|
es->size++;
|
|
es->e[offset].type = t;
|
|
es->e[offset].nextTop = es->size;
|
|
|
|
return offset;
|
|
}
|
|
|
|
/* Incorporate one event set into another, get start offset */
|
|
Int CLG_(add_eventset)(EventSet* dst, EventSet* src)
|
|
{
|
|
Int offset = dst->size, i;
|
|
if (!src || (src->size == 0)) return offset;
|
|
|
|
if (dst->capacity - offset < src->size) return -1;
|
|
|
|
for(i=0;i<src->size;i++) {
|
|
dst->e[offset+i].type = src->e[i].type;
|
|
dst->e[offset+i].nextTop = src->e[i].nextTop + offset;
|
|
}
|
|
dst->size += src->size;
|
|
|
|
return offset;
|
|
}
|
|
|
|
/* Incorporate two event types into a set, with second < first */
|
|
Int CLG_(add_dep_event2)(EventSet* es, EventType* e1, EventType* e2)
|
|
{
|
|
Int offset = es->size;
|
|
|
|
if (es->capacity - offset < 2) return -1;
|
|
|
|
es->size += 2;
|
|
es->e[offset].type = e1;
|
|
es->e[offset].nextTop = es->size;
|
|
es->e[offset+1].type = e2;
|
|
es->e[offset+1].nextTop = es->size;
|
|
|
|
return offset;
|
|
}
|
|
|
|
/* Incorporate 3 event types into a set, with third < second < first */
|
|
Int CLG_(add_dep_event3)(EventSet* es,
|
|
EventType* e1, EventType* e2, EventType* e3)
|
|
{
|
|
Int offset = es->size;
|
|
|
|
if (es->capacity - offset < 3) return -1;
|
|
|
|
es->size += 3;
|
|
es->e[offset].type = e1;
|
|
es->e[offset].nextTop = es->size;
|
|
es->e[offset+1].type = e2;
|
|
es->e[offset+1].nextTop = es->size;
|
|
es->e[offset+2].type = e3;
|
|
es->e[offset+2].nextTop = es->size;
|
|
|
|
return offset;
|
|
}
|
|
|
|
Int CLG_(add_dep_event4)(EventSet* es,
|
|
EventType* e1, EventType* e2,
|
|
EventType* e3, EventType* e4)
|
|
{
|
|
Int offset = es->size;
|
|
|
|
if (es->capacity - offset < 4) return -1;
|
|
|
|
es->size += 4;
|
|
es->e[offset].type = e1;
|
|
es->e[offset].nextTop = es->size;
|
|
es->e[offset+1].type = e2;
|
|
es->e[offset+1].nextTop = es->size;
|
|
es->e[offset+2].type = e3;
|
|
es->e[offset+2].nextTop = es->size;
|
|
es->e[offset+3].type = e4;
|
|
es->e[offset+3].nextTop = es->size;
|
|
|
|
return offset;
|
|
}
|
|
|
|
/* Returns number of characters written */
|
|
Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
|
|
{
|
|
Int i, pos = 0;
|
|
|
|
for(i=0; i< es->size; i++) {
|
|
if (pos>0) buf[pos++] = ' ';
|
|
pos += VG_(sprintf)(buf + pos, "%s", es->e[i].type->name);
|
|
}
|
|
buf[pos] = 0;
|
|
|
|
return pos;
|
|
}
|
|
|
|
/* Get cost array for an event set */
|
|
ULong* CLG_(get_eventset_cost)(EventSet* es)
|
|
{
|
|
return CLG_(get_costarray)(es->capacity);
|
|
}
|
|
|
|
/* Set all costs of an event set to zero */
|
|
void CLG_(init_cost)(EventSet* es, ULong* cost)
|
|
{
|
|
Int i;
|
|
|
|
if (!cost) return;
|
|
|
|
for(i=0;i<es->capacity;i++)
|
|
cost[i] = 0;
|
|
}
|
|
|
|
/* Set all costs of an event set to zero */
|
|
void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
|
|
{
|
|
Int i;
|
|
|
|
CLG_ASSERT(cost != 0);
|
|
if (!(*cost))
|
|
*cost = CLG_(get_eventset_cost)(es);
|
|
|
|
for(i=0;i<es->capacity;i++)
|
|
(*cost)[i] = 0;
|
|
}
|
|
|
|
void CLG_(zero_cost)(EventSet* es, ULong* cost)
|
|
{
|
|
Int i;
|
|
|
|
if (!cost) return;
|
|
|
|
for(i=0;i<es->size;i++)
|
|
cost[i] = 0;
|
|
}
|
|
|
|
Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
|
|
{
|
|
Int i = 0;
|
|
|
|
if (!cost) return True;
|
|
|
|
while(i<es->size) {
|
|
if (cost[i] != 0) return False;
|
|
i = es->e[i].nextTop;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
Bool CLG_(is_equal_cost)(EventSet* es, ULong* c1, ULong* c2)
|
|
{
|
|
Int i = 0;
|
|
|
|
if (!c1) return CLG_(is_zero_cost)(es,c2);
|
|
if (!c2) return CLG_(is_zero_cost)(es,c1);
|
|
|
|
while(i<es->size) {
|
|
if (c1[i] != c2[i]) return False;
|
|
if (c1[i] == 0)
|
|
i = es->e[i].nextTop;
|
|
else
|
|
i++;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
|
|
{
|
|
Int i;
|
|
|
|
if (!src) {
|
|
CLG_(zero_cost)(es, dst);
|
|
return;
|
|
}
|
|
CLG_ASSERT(dst != 0);
|
|
|
|
for(i=0;i<es->size;i++)
|
|
dst[i] = src[i];
|
|
}
|
|
|
|
void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
|
|
{
|
|
Int i;
|
|
ULong* dst;
|
|
|
|
CLG_ASSERT(pdst != 0);
|
|
|
|
if (!src) {
|
|
CLG_(zero_cost)(es, *pdst);
|
|
return;
|
|
}
|
|
dst = *pdst;
|
|
if (!dst)
|
|
dst = *pdst = CLG_(get_eventset_cost)(es);
|
|
|
|
for(i=0;i<es->size;i++)
|
|
dst[i] = src[i];
|
|
}
|
|
|
|
void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
|
|
{
|
|
Int i = 0;
|
|
|
|
if (!src) return;
|
|
CLG_ASSERT(dst != 0);
|
|
|
|
while(i<es->size) {
|
|
if (src[i] == 0)
|
|
i = es->e[i].nextTop;
|
|
else {
|
|
dst[i] += src[i];
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
|
|
{
|
|
Int i;
|
|
ULong* dst;
|
|
|
|
if (!src) return;
|
|
CLG_ASSERT(pdst != 0);
|
|
|
|
dst = *pdst;
|
|
if (!dst) {
|
|
dst = *pdst = CLG_(get_eventset_cost)(es);
|
|
CLG_(copy_cost)(es,dst,src);
|
|
return;
|
|
}
|
|
|
|
i = 0;
|
|
while(i<es->size) {
|
|
if (src[i] == 0)
|
|
i = es->e[i].nextTop;
|
|
else {
|
|
dst[i] += src[i];
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Adds src to dst and zeros src. Returns false if nothing changed */
|
|
Bool CLG_(add_and_zero_cost)(EventSet* es, ULong* dst, ULong* src)
|
|
{
|
|
Int i = 0, j = 0;
|
|
|
|
CLG_DEBUGIF(6) {
|
|
CLG_DEBUG(6, " add_and_zero_cost(%s, dst %p, src %p)\n", es->name, dst, src);
|
|
CLG_(print_cost)(-5, es, src);
|
|
}
|
|
|
|
if (!es || !src) return False;
|
|
|
|
while(i<es->size) {
|
|
if (src[i] == 0)
|
|
i = es->e[i].nextTop;
|
|
else {
|
|
dst[i] += src[i];
|
|
src[i] = 0;
|
|
i++;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
return (j>0);
|
|
}
|
|
|
|
/* Adds src to dst and zeros src. Returns false if nothing changed */
|
|
Bool CLG_(add_and_zero_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
|
|
{
|
|
Int i;
|
|
ULong* dst;
|
|
|
|
if (!src) return False;
|
|
|
|
i = 0;
|
|
while(1) {
|
|
if (i >= es->size) return False;
|
|
if (src[i] != 0) break;
|
|
i = es->e[i].nextTop;
|
|
}
|
|
|
|
CLG_ASSERT(pdst != 0);
|
|
dst = *pdst;
|
|
if (!dst) {
|
|
dst = *pdst = CLG_(get_eventset_cost)(es);
|
|
CLG_(copy_cost)(es,dst,src);
|
|
CLG_(zero_cost)(es,src);
|
|
return True;
|
|
}
|
|
|
|
dst[i] += src[i];
|
|
src[i] = 0;
|
|
i++;
|
|
|
|
while(i<es->size) {
|
|
if (src[i] == 0)
|
|
i = es->e[i].nextTop;
|
|
else {
|
|
dst[i] += src[i];
|
|
src[i] = 0;
|
|
}
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/* Adds difference of new and old to dst, and set old to new.
|
|
* Returns false if nothing changed */
|
|
Bool CLG_(add_diff_cost)(EventSet* es, ULong* dst, ULong* old, ULong* new)
|
|
{
|
|
Int i = 0, j = 0;
|
|
|
|
while(i<es->size) {
|
|
if (new[i] == old[i])
|
|
i = es->e[i].nextTop;
|
|
else {
|
|
dst[i] += new[i] - old[i];
|
|
old[i] = new[i];
|
|
i++;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
return (j>0);
|
|
}
|
|
|
|
/* Adds difference of new and old to dst, and set old to new.
|
|
* Returns false if nothing changed */
|
|
Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst,
|
|
ULong* old, ULong* new)
|
|
{
|
|
Int i;
|
|
ULong* dst;
|
|
|
|
if (!old && !new) return False;
|
|
CLG_ASSERT(old && new);
|
|
|
|
i = 0;
|
|
while(1) {
|
|
if (i >= es->size) return False;
|
|
if (old[i] != new[i]) break;
|
|
i = es->e[i].nextTop;
|
|
}
|
|
|
|
CLG_ASSERT(pdst != 0);
|
|
dst = *pdst;
|
|
if (!dst) {
|
|
dst = *pdst = CLG_(get_eventset_cost)(es);
|
|
CLG_(zero_cost)(es,dst);
|
|
}
|
|
|
|
dst[i] += new[i] - old[i];
|
|
old[i] = new[i];
|
|
i++;
|
|
|
|
while(i<es->size) {
|
|
if (new[i] == old[i])
|
|
i = es->e[i].nextTop;
|
|
else {
|
|
dst[i] += new[i] - old[i];
|
|
old[i] = new[i];
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/* Returns number of characters written */
|
|
Int CLG_(sprint_cost)(Char* buf, EventSet* es, ULong* c)
|
|
{
|
|
Int i, pos, skipped = 0;
|
|
|
|
if (!c || es->size==0) return 0;
|
|
|
|
/* At least one entry */
|
|
pos = VG_(sprintf)(buf, "%llu", c[0]);
|
|
i = 1;
|
|
|
|
while(i<es->size) {
|
|
if (c[i] == 0) {
|
|
skipped += es->e[i].nextTop - i;
|
|
i = es->e[i].nextTop;
|
|
}
|
|
else {
|
|
while(skipped>0) {
|
|
buf[pos++] = ' ';
|
|
buf[pos++] = '0';
|
|
skipped--;
|
|
}
|
|
buf[pos++] = ' ';
|
|
pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return pos;
|
|
}
|
|
|
|
|
|
/* Allocate space for an event mapping */
|
|
EventMapping* CLG_(get_eventmapping)(EventSet* es)
|
|
{
|
|
EventMapping* em;
|
|
|
|
CLG_ASSERT(es != 0);
|
|
|
|
em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
|
|
sizeof(EventMapping) +
|
|
es->capacity * sizeof(Int));
|
|
em->capacity = es->capacity;
|
|
em->size = 0;
|
|
em->set = es;
|
|
|
|
return em;
|
|
}
|
|
|
|
void CLG_(append_event)(EventMapping* em, Char* n)
|
|
{
|
|
Int i;
|
|
|
|
CLG_ASSERT(em != 0);
|
|
|
|
for(i=0; i<em->set->size; i++)
|
|
if (VG_(strcmp)(n, em->set->e[i].type->name)==0)
|
|
break;
|
|
|
|
if (i == em->set->size) return;
|
|
|
|
CLG_ASSERT(em->capacity > em->size);
|
|
|
|
em->index[em->size] = i;
|
|
em->size++;
|
|
}
|
|
|
|
|
|
/* Returns number of characters written */
|
|
Int CLG_(sprint_eventmapping)(Char* buf, EventMapping* em)
|
|
{
|
|
Int i, pos = 0;
|
|
|
|
CLG_ASSERT(em != 0);
|
|
|
|
for(i=0; i< em->size; i++) {
|
|
if (pos>0) buf[pos++] = ' ';
|
|
pos += VG_(sprintf)(buf + pos, "%s", em->set->e[em->index[i]].type->name);
|
|
}
|
|
buf[pos] = 0;
|
|
|
|
return pos;
|
|
}
|
|
|
|
/* Returns number of characters written */
|
|
Int CLG_(sprint_mappingcost)(Char* buf, EventMapping* em, ULong* c)
|
|
{
|
|
Int i, pos, skipped = 0;
|
|
|
|
if (!c || em->size==0) return 0;
|
|
|
|
/* At least one entry */
|
|
pos = VG_(sprintf)(buf, "%llu", c[em->index[0]]);
|
|
i = 1;
|
|
|
|
while(i<em->size) {
|
|
if (c[em->index[i]] == 0) {
|
|
skipped++;
|
|
i++;
|
|
}
|
|
else {
|
|
while(skipped>0) {
|
|
buf[pos++] = ' ';
|
|
buf[pos++] = '0';
|
|
skipped--;
|
|
}
|
|
buf[pos++] = ' ';
|
|
pos += VG_(sprintf)(buf+pos, "%llu", c[em->index[i]]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return pos;
|
|
}
|