MP_GLOBAL void __mp_deleteheap(heaphead *h) { heapnode *n, *p; /* Free up the memory pointed to by the heap nodes first, since the * heap nodes themselves are freed in the second loop. */ for (n = (heapnode *) __mp_minimum(h->dtree.root); n != NULL; n = p) { p = (heapnode *) __mp_successor(&n->node); __mp_heapfree(h, n); } for (n = (heapnode *) __mp_minimum(h->itree.root); n != NULL; n = p) { p = (heapnode *) __mp_successor(&n->node); __mp_treeremove(&h->itree, &n->node); __mp_memfree(&h->memory, n->block, n->size); } __mp_endmemory(&h->memory); h->table.free = NULL; h->table.size = 0; h->isize = 0; h->prot = MA_NOACCESS; h->protrecur = 0; h->tracing = 0; }
static void deletegraph(void) { vertex *n, *v; edge *e, *m; /* Remove the nodes from the graph and free up the memory that they * inhabit. This is done by traversing the tree rather than the graph * in order to avoid deleting nodes that result in other nodes being * inaccessible. */ for (v = (vertex *) __mp_minimum(temptree.root); v != NULL; v = n) { n = (vertex *) __mp_successor(&v->node); __mp_treeremove(&temptree, &v->node); __mp_removenode(&graph, &v->gnode); free(v); } /* Remove the edges from the graph. The graph is now empty following * the removal of the nodes in the previous loop, so we just need to * free the memory that each edge uses. */ for (e = (edge *) edgelist.head; (m = (edge *) e->node.next) != NULL; e = m) { __mp_remove(&edgelist, &e->node); free(e); } }
MP_GLOBAL int __mp_heapprotect(heaphead *h, memaccess a) { heapnode *n; /* The library already knows what its protection status is so we don't * need to do anything if the request has already been done. */ if (h->prot == a) { h->protrecur++; return 1; } else if (h->protrecur > 0) { h->protrecur--; return 1; } h->prot = a; for (n = (heapnode *) __mp_minimum(h->itree.root); n != NULL; n = (heapnode *) __mp_successor(&n->node)) if (!__mp_memprotect(&h->memory, n->block, n->size, a)) return 0; return 1; }
MP_GLOBAL int __mp_protectalloc(allochead *h, memaccess a) { allocnode *n; treenode *t; if (!__mp_heapprotect(&h->heap, a)) return 0; /* The library already knows what its protection status is so we don't * need to do anything if the request has already been done. */ if (h->prot == a) { h->protrecur++; return 1; } else if (h->protrecur > 0) { h->protrecur--; return 1; } h->prot = a; for (t = __mp_minimum(h->itree.root); t != NULL; t = __mp_successor(t)) { n = (allocnode *) ((char *) t - offsetof(allocnode, tnode)); if (!__mp_memprotect(&h->heap.memory, n->block, n->size, a)) return 0; } return 1; }
static void freeallocs(void) { allocation *n, *p; for (n = (allocation *) __mp_minimum(alloctree.root); n != NULL; n = p) { p = (allocation *) __mp_successor(&n->node); __mp_treeremove(&alloctree, &n->node); free(n); } }
static void directtable(void) { profiledata *d; profilenode *n, *p; treenode *t; profiledata m; size_t i; unsigned long a, b, c; double e, f; cleardata(&m); printchar(' ', 31); fputs("DIRECT ALLOCATIONS\n\n", stdout); printchar(' ', 20); fprintf(stdout, "(0 < s <= %lu < m <= %lu < l <= %lu < x)\n\n", sbound, mbound, lbound); if (showcounts) { printchar(' ', 9); fputs("allocated", stdout); printchar(' ', 21); fputs("unfreed\n", stdout); printchar('-', 27); fputs(" ", stdout); printchar('-', 27); fputs("\n count % s m l x " "count % s m l x bytes function\n\n", stdout); } else { printchar(' ', 10); fputs("allocated", stdout); printchar(' ', 23); fputs("unfreed\n", stdout); printchar('-', 29); fputs(" ", stdout); printchar('-', 29); fputs("\n bytes % s m l x " "bytes % s m l x count function\n\n", stdout); } for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = p) { p = (profilenode *) __mp_successor(&n->node); if (n->data != 0) { d = &n->tdata; sumdata(d, &data[n->data - 1]); while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses && (p->symbol != 0) && (p->symbol == n->symbol)))) { if (p->data != 0) sumdata(d, &data[p->data - 1]); p = (profilenode *) __mp_successor(&p->node); } a = 0; for (i = 0; i < 4; i++) if (showcounts) a += d->acount[i]; else a += d->atotal[i]; __mp_treeinsert(&temptree, &n->tnode, a); sumdata(&m, d); } } for (t = __mp_maximum(temptree.root); t != NULL; t = __mp_predecessor(t)) { n = (profilenode *) ((char *) t - offsetof(profilenode, tnode)); d = &n->tdata; a = t->key; b = c = 0; for (i = 0; i < 4; i++) { if (showcounts) { b += d->dcount[i]; c += d->atotal[i]; } else { b += d->dtotal[i]; c += d->acount[i]; } d->dcount[i] = d->acount[i] - d->dcount[i]; d->dtotal[i] = d->atotal[i] - d->dtotal[i]; } b = a - b; if (showcounts) { e = ((double) a / (double) acount) * 100.0; if (acount != dcount) f = ((double) b / (double) (acount - dcount)) * 100.0; else f = 0.0; fprintf(stdout, "%6lu %6.2f ", a, e); printdata(d->acount, acount); fprintf(stdout, " %6lu %6.2f ", b, f); printdata(d->dcount, acount - dcount); fprintf(stdout, " %8lu ", c); } else { e = ((double) a / (double) atotal) * 100.0; if (atotal != dtotal) f = ((double) b / (double) (atotal - dtotal)) * 100.0; else f = 0.0; fprintf(stdout, "%8lu %6.2f ", a, e); printdata(d->atotal, atotal); fprintf(stdout, " %8lu %6.2f ", b, f); printdata(d->dtotal, atotal - dtotal); fprintf(stdout, " %6lu ", c); } printsymbol(stdout, n); fputc('\n', stdout); cleardata(d); } for (i = 0; i < 4; i++) { m.dcount[i] = m.acount[i] - m.dcount[i]; m.dtotal[i] = m.atotal[i] - m.dtotal[i]; } if (temptree.size != 0) fputc('\n', stdout); if (showcounts) { fprintf(stdout, "%6lu ", acount); printdata(m.acount, acount); fprintf(stdout, " %6lu ", acount - dcount); printdata(m.dcount, acount - dcount); fprintf(stdout, " %8lu total\n", atotal); } else { fprintf(stdout, "%8lu ", atotal); printdata(m.atotal, atotal); fprintf(stdout, " %8lu ", atotal - dtotal); printdata(m.dtotal, atotal - dtotal); fprintf(stdout, " %6lu total\n", acount); } __mp_newtree(&temptree); }
static void buildgraph(void) { profilenode *n, *p; vertex *u, *v; edge *e; graphedge *g; profiledata d; for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = (profilenode *) __mp_successor(&n->node)) if ((n->data != 0) && !(n->flags & 1)) { cleardata(&d); sumdata(&d, &data[n->data - 1]); p = (profilenode *) __mp_successor(&n->node); while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses && (p->symbol != 0) && (p->symbol == n->symbol)))) { if ((p->data != 0) && !(p->flags & 1) && comparestack(n, p, 1)) { sumdata(&d, &data[p->data - 1]); p->flags |= 1; } p = (profilenode *) __mp_successor(&p->node); } p = n; if (useaddresses || (p->symbol == 0)) u = (vertex *) __mp_search(temptree.root, (unsigned long) p->addr); else u = (vertex *) __mp_search(temptree.root, p->symbol); if (u == NULL) u = addvertex(p); if ((g = __mp_findedge(&graph, &u->gnode, &graph.end)) == NULL) e = addedge(&u->gnode, &graph.end); else e = (edge *) ((char *) g - offsetof(edge, gnode)); sumdata(&e->data, &d); u->pnode->flags |= 2; for (v = u; p->parent != 0; u = v) { p = &nodes[p->parent - 1]; if (useaddresses || (p->symbol == 0)) v = (vertex *) __mp_search(temptree.root, (unsigned long) p->addr); else v = (vertex *) __mp_search(temptree.root, p->symbol); if (v == NULL) v = addvertex(p); if ((g = __mp_findedge(&graph, &v->gnode, &u->gnode)) == NULL) e = addedge(&v->gnode, &u->gnode); else e = (edge *) ((char *) g - offsetof(edge, gnode)); /* Find out if we've been here before. If we have then we have * detected a cycle in the call graph and we should not * contribute anything to the current edge since we have done so * already. However, we mark the edge as being part of a cycle * since it is useful to know this later on. */ if (v->pnode->flags & 2) e->flags |= 2; else { sumdata(&e->data, &d); v->pnode->flags |= 2; } } if ((g = __mp_findedge(&graph, &graph.start, &v->gnode)) == NULL) e = addedge(&graph.start, &v->gnode); else e = (edge *) ((char *) g - offsetof(edge, gnode)); sumdata(&e->data, &d); /* Clear all of the flags from the current call stack that we used * to determine cycles in the call graph. */ p = n; do { if (useaddresses || (p->symbol == 0)) v = (vertex *) __mp_search(temptree.root, (unsigned long) p->addr); else v = (vertex *) __mp_search(temptree.root, p->symbol); v->pnode->flags &= ~2; if (p->parent != 0) p = &nodes[p->parent - 1]; else p = NULL; } while (p != NULL); } for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = (profilenode *) __mp_successor(&n->node)) n->flags = 0; }
static void callgraph(void) { size_t d[4]; listnode *l; vertex *u, *v; edge *e; graphedge *g; size_t i, s, t; i = 1; printchar(' ', 29); fputs("ALLOCATION CALL GRAPH\n\n", stdout); printchar(' ', 28); fprintf(stdout, "(number of vertices: %lu)\n\n", temptree.size); if (showcounts) { printchar(' ', 10); fputs("allocated", stdout); printchar(' ', 13); fputs("unfreed\n", stdout); printchar(' ', 5); printchar('-', 19); fputs(" ", stdout); printchar('-', 19); fputs("\nindex count s m l x count s m l x function\n", stdout); } else { printchar(' ', 11); fputs("allocated", stdout); printchar(' ', 15); fputs("unfreed\n", stdout); printchar(' ', 5); printchar('-', 21); fputs(" ", stdout); printchar('-', 21); fputs("\nindex bytes s m l x bytes s m l x function\n", stdout); } /* Compute the index for each vertex in the graph. This is currently * done after the graph has been completely constructed so that the * ordering can be done by code address. It has to be done before we * start displaying the graph since each vertex will contain forward * references to its parents and children. */ for (v = (vertex *) __mp_minimum(temptree.root); v != NULL; v = (vertex *) __mp_successor(&v->node)) v->index = i++; for (v = (vertex *) __mp_minimum(temptree.root); v != NULL; v = (vertex *) __mp_successor(&v->node)) { if (showcounts) printchar('-', 45); else printchar('-', 49); fputc('\n', stdout); /* Calculate the details of the parents. */ for (l = v->gnode.parents.head; l->next != NULL; l = l->next) { /* The following three lines are a bit excessive and result from * using class-based programming in C. These conversions would be * automatically calculated by the compiler if we were using C++ * classes. */ g = (graphedge *) ((char *) l - offsetof(graphedge, pnode)); e = (edge *) ((char *) g - offsetof(edge, gnode)); u = (vertex *) ((char *) e->gnode.parent - offsetof(vertex, gnode)); if (&u->gnode != &graph.start) { for (i = s = t = 0; i < 4; i++) { if (showcounts) { t += e->data.acount[i]; d[i] = e->data.acount[i] - e->data.dcount[i]; } else { t += e->data.atotal[i]; d[i] = e->data.atotal[i] - e->data.dtotal[i]; } s += d[i]; } if (e->flags & 2) fputs(" (*) ", stdout); else printchar(' ', 5); if (showcounts) { fprintf(stdout, "%6lu ", t); printdata(e->data.acount, t); fprintf(stdout, " %6lu ", s); } else { fprintf(stdout, "%8lu ", t); printdata(e->data.atotal, t); fprintf(stdout, " %8lu ", s); } printdata(d, s); printchar(' ', 6); printsymbol(stdout, u->pnode); fprintf(stdout, " [%lu]\n", u->index); } } fprintf(stdout, "[%lu] ", v->index); if (showcounts) printchar(' ', 44 - countdigits(v->index)); else printchar(' ', 48 - countdigits(v->index)); printsymbol(stdout, v->pnode); fprintf(stdout, " [%lu]\n", v->index); /* Calculate the details of the children. */ for (l = v->gnode.children.head; l->next != NULL; l = l->next) { /* The following three lines are a bit excessive and result from * using class-based programming in C. These conversions would be * automatically calculated by the compiler if we were using C++ * classes. */ g = (graphedge *) ((char *) l - offsetof(graphedge, cnode)); e = (edge *) ((char *) g - offsetof(edge, gnode)); u = (vertex *) ((char *) e->gnode.child - offsetof(vertex, gnode)); if (&u->gnode != &graph.end) { for (i = s = t = 0; i < 4; i++) { if (showcounts) { t += e->data.acount[i]; d[i] = e->data.acount[i] - e->data.dcount[i]; } else { t += e->data.atotal[i]; d[i] = e->data.atotal[i] - e->data.dtotal[i]; } s += d[i]; } if (e->flags & 2) fputs(" (*) ", stdout); else printchar(' ', 5); if (showcounts) { fprintf(stdout, "%6lu ", t); printdata(e->data.acount, t); fprintf(stdout, " %6lu ", s); } else { fprintf(stdout, "%8lu ", t); printdata(e->data.atotal, t); fprintf(stdout, " %8lu ", s); } printdata(d, s); printchar(' ', 6); printsymbol(stdout, u->pnode); fprintf(stdout, " [%lu]\n", u->index); } } } }
static void leaktable(void) { profiledata *d; profilenode *n, *p; treenode *t; size_t i; unsigned long a, b, j, k; double e, f, g; printchar(' ', 34); fputs("MEMORY LEAKS\n\n", stdout); printchar(' ', 28); fprintf(stdout, "(maximum stack depth: %lu)\n\n", maxstack); printchar(' ', 16); fputs("unfreed", stdout); printchar(' ', 22); fputs("allocated\n", stdout); printchar('-', 40); fputs(" ", stdout); printchar('-', 16); if (showcounts) fputs("\n % count % bytes % " "count bytes function\n\n", stdout); else fputs("\n % bytes % count % " "bytes count function\n\n", stdout); for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = p) { p = (profilenode *) __mp_successor(&n->node); if ((n->data != 0) && !n->flags) { d = &n->tdata; sumdata(d, &data[n->data - 1]); while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses && (p->symbol != 0) && (p->symbol == n->symbol)))) { if ((p->data != 0) && !p->flags && comparestack(n, p, 0)) { sumdata(d, &data[p->data - 1]); p->flags = 1; } p = (profilenode *) __mp_successor(&p->node); } p = (profilenode *) __mp_successor(&n->node); a = 0; for (i = 0; i < 4; i++) if (showcounts) a += d->acount[i] - d->dcount[i]; else a += d->atotal[i] - d->dtotal[i]; if (a > 0) __mp_treeinsert(&temptree, &n->tnode, a); } } for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = (profilenode *) __mp_successor(&n->node)) n->flags = 0; for (t = __mp_maximum(temptree.root); t != NULL; t = __mp_predecessor(t)) { n = (profilenode *) ((char *) t - offsetof(profilenode, tnode)); d = &n->tdata; a = t->key; b = j = k = 0; for (i = 0; i < 4; i++) if (showcounts) { b += d->dtotal[i]; j += d->acount[i]; k += d->atotal[i]; } else { b += d->dcount[i]; j += d->atotal[i]; k += d->acount[i]; } b = k - b; e = ((double) a / (double) j) * 100.0; f = ((double) b / (double) k) * 100.0; if (showcounts) { g = ((double) a / (double) (acount - dcount)) * 100.0; fprintf(stdout, "%6.2f %6lu %6.2f %8lu %6.2f %6lu %8lu ", g, a, e, b, f, j, k); } else { g = ((double) a / (double) (atotal - dtotal)) * 100.0; fprintf(stdout, "%6.2f %8lu %6.2f %6lu %6.2f %8lu %6lu ", g, a, e, b, f, j, k); } printsymbol(stdout, n); fputc('\n', stdout); p = n; for (i = 1; (maxstack == 0) || (i < maxstack); i++) { if (p->parent == 0) break; p = &nodes[p->parent - 1]; printchar(' ', 60); printsymbol(stdout, p); fputc('\n', stdout); } cleardata(d); } if (acount != 0) e = ((double) (acount - dcount) / (double) acount) * 100.0; else e = 0.0; if (atotal != 0) f = ((double) (atotal - dtotal) / (double) atotal) * 100.0; else f = 0.0; if (temptree.size != 0) fputc('\n', stdout); if (showcounts) fprintf(stdout, " %6lu %6.2f %8lu %6.2f %6lu %8lu total\n", acount - dcount, e, atotal - dtotal, f, acount, atotal); else fprintf(stdout, " %8lu %6.2f %6lu %6.2f %8lu %6lu total\n", atotal - dtotal, f, acount - dcount, e, atotal, acount); __mp_newtree(&temptree); }