📄 profile.c
字号:
/* * mpatrol * A library for controlling and tracing dynamic memory allocations. * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. *//* * Memory allocation profiling. The call graphs for every memory allocation * and deallocation are recorded here along with their memory usage statistics * and are written to a file for later processing by a profiling tool. */#include "profile.h"#include "info.h"#include "diag.h"#include "utils.h"#include "version.h"#include <stdio.h>#include <string.h>#if MP_IDENT_SUPPORT#ident "$Id: profile.c,v 1.38 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *profile_id = "$Id: profile.c,v 1.38 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus *//* Initialise the fields of a profhead so that the mpatrol library * is ready to profile memory allocations. */MP_GLOBALvoid__mp_newprofile(profhead *p, heaphead *h, symhead *s){ struct { char x; profdata y; } w; struct { char x; profnode y; } z; size_t i; long n; p->heap = h; p->syms = s; /* Determine the minimum alignment for a profdata structure and a * profnode on this system and force the alignments to be a power * of two. This information is used when initialising the slot * tables. */ n = (char *) &w.y - &w.x; __mp_newslots(&p->dtable, sizeof(profdata), __mp_poweroftwo(n)); n = (char *) &z.y - &z.x; __mp_newslots(&p->ntable, sizeof(profnode), __mp_poweroftwo(n)); __mp_newlist(&p->ilist); __mp_newlist(&p->list); __mp_newtree(&p->tree); p->size = 0; for (i = 0; i < MP_BIN_SIZE; i++) p->acounts[i] = p->dcounts[i] = 0; p->atotals = p->dtotals = 0; p->sbound = MP_SMALLBOUND; p->mbound = MP_MEDIUMBOUND; p->lbound = MP_LARGEBOUND; p->autosave = p->autocount = 0; p->file = __mp_proffile(&h->memory, NULL); p->prot = MA_NOACCESS; p->protrecur = 0; p->profiling = 0;}/* Forget all existing profiling information. */MP_GLOBALvoid__mp_deleteprofile(profhead *p){ size_t i; /* We don't need to explicitly free any memory as this is dealt with * at a lower level by the heap manager. */ p->heap = NULL; p->syms = NULL; p->dtable.free = NULL; p->dtable.size = 0; p->ntable.free = NULL; p->ntable.size = 0; __mp_newlist(&p->ilist); __mp_newlist(&p->list); __mp_newtree(&p->tree); p->size = 0; for (i = 0; i < MP_BIN_SIZE; i++) p->acounts[i] = p->dcounts[i] = 0; p->atotals = p->dtotals = 0; p->autocount = 0; p->file = NULL; p->prot = MA_NOACCESS; p->protrecur = 0; p->profiling = 0;}/* Allocate a new profiling data structure. */staticprofdata *getprofdata(profhead *p){ profdata *d; heapnode *h; size_t i; /* If we have no more profiling data structure slots left then we must * allocate some more memory for them. An extra MP_ALLOCFACTOR pages * of memory should suffice. */ if ((d = (profdata *) __mp_getslot(&p->dtable)) == NULL) { if ((h = __mp_heapalloc(p->heap, p->heap->memory.page * MP_ALLOCFACTOR, p->dtable.entalign, 1)) == NULL) return NULL; __mp_initslots(&p->dtable, h->block, h->size); d = (profdata *) __mp_getslot(&p->dtable); __mp_addtail(&p->ilist, &d->index.node); d->index.block = h->block; d->index.size = h->size; p->size += h->size; d = (profdata *) __mp_getslot(&p->dtable); } __mp_addtail(&p->list, &d->data.node); d->data.index = p->list.size; for (i = 0; i < 4; i++) { d->data.acount[i] = d->data.dcount[i] = 0; d->data.atotal[i] = d->data.dtotal[i] = 0; } return d;}/* Allocate a new profiling node. */staticprofnode *getprofnode(profhead *p){ profnode *n; heapnode *h; /* If we have no more profnode slots left then we must allocate * some more memory for them. An extra MP_ALLOCFACTOR pages of memory * should suffice. */ if ((n = (profnode *) __mp_getslot(&p->ntable)) == NULL) { if ((h = __mp_heapalloc(p->heap, p->heap->memory.page * MP_ALLOCFACTOR, p->ntable.entalign, 1)) == NULL) return NULL; __mp_initslots(&p->ntable, h->block, h->size); n = (profnode *) __mp_getslot(&p->ntable); __mp_addtail(&p->ilist, &n->index.node); n->index.block = h->block; n->index.size = h->size; p->size += h->size; n = (profnode *) __mp_getslot(&p->ntable); } return n;}/* Locate or create a call site associated with a specified return address. */staticprofnode *getcallsite(profhead *p, addrnode *a){ profnode *n, *t; addrnode *d; if (n = (profnode *) __mp_search(p->tree.root, (unsigned long) a->data.addr)) { while ((t = (profnode *) __mp_predecessor(&n->data.node)) && (t->data.addr == a->data.addr)) n = t; while ((n != NULL) && (n->data.addr == a->data.addr)) { for (t = n->data.parent, d = a->data.next; (t != NULL) && (d != NULL); t = t->data.parent, d = d->data.next) if (t->data.addr != d->data.addr) break; if ((t == NULL) && (d == NULL)) return n; n = (profnode *) __mp_successor(&n->data.node); } } t = NULL; if (((n = getprofnode(p)) == NULL) || ((a->data.next != NULL) && ((t = getcallsite(p, a->data.next)) == NULL))) { if (n != NULL) __mp_freeslot(&p->ntable, n); return NULL; } __mp_treeinsert(&p->tree, &n->data.node, (unsigned long) a->data.addr); n->data.parent = t; n->data.index = p->tree.size; n->data.addr = a->data.addr; n->data.symbol = __mp_findsymbol(p->syms, a->data.addr); n->data.data = NULL; return n;}/* Record a memory allocation for profiling. */MP_GLOBALint__mp_profilealloc(profhead *p, size_t l, void *d, int w){ profnode *n; infonode *m; size_t i; /* Try to associate the allocation with a previous call site, or create * a new call site if no such site exists. This information is not * recorded if the return address could not be determined. */ m = (infonode *) d; if ((m->data.stack != NULL) && (m->data.stack->data.addr != NULL)) { if (((n = getcallsite(p, m->data.stack)) == NULL) || ((n->data.data == NULL) && ((n->data.data = getprofdata(p)) == NULL))) return 0; if (l <= p->sbound) i = 0; else if (l <= p->mbound) i = 1; else if (l <= p->lbound)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -