/* * Memory diagnosics: memTrack.c * * Author: Richard Dickson (dickson@jlab.org) * * $Id: memTrack.c,v 1.1 1999/11/29 23:27:48 borkhuis Exp $ * */ /* Richard Dickson July, 1998 */ /* Routines to report per task memory allocation */ #include <stdio.h> #include <stdlib.h> #include <taskLib.h> #include <symLib.h> /* these three must have been initialized by the routine find_malloc before this module is loaded */ extern void *(*addr_of_malloc)(size_t size); extern void *(*addr_of_calloc)(size_t nelem, size_t size); extern void (*addr_of_free)(void *ptr); extern SYMTAB_ID sysSymTbl; /****************************************************************************/ long getStackPointer(void) { /* assembly routine to return stack pointer value */ static const short code_array[] = { 0x4e56, 0000,/* LINK.W A6,#0 */ 0x200F,/* MOVE.L A7,D0 */ 0x4e5e,/* ULNK A6 */ 0x4e75/* RTS */ }; return (((long(*)()) code_array)()); } /****************************************************************************/ void *malloc(size_t size) { WIND_TCB *tcb; /* pointer to task control block */ void *ret_val; ret_val = (*addr_of_malloc)(size+4); /* call real malloc, ask for 4 extra bytes to store TID */ if (ret_val) { /* if malloc success */ long *sp; /* stack pointer */ tcb = (WIND_TCB*)taskIdSelf(); /* get TID */ *(WIND_TCB**)ret_val = tcb; /* put TID at start of malloc buffer */ tcb->spare1++; /* inc allocated block counter for this task */ tcb->spare2 += (*((int*)ret_val - 1) - 12); /* vxWorks puts length of buff (+ buf's linked list overhead size (8 bytes)) into longword before malloc's return address. Subtract 4 more for the extra 4 asked for (total 12) to find size of caller's request. Add this to this tasks total bytes allocated */ sp = (long*)getStackPointer(); /* get stack pointer so the caller of this routine can be found */ tcb->spare3 = (int)sp[7] - 6; /* caller PC (JSR instruction is 6 bytes long itself) */ } (char*)ret_val += 4; /* adjust malloc return value so caller doesn't see TID info */ return ret_val; } /****************************************************************************/ void *calloc(size_t nelem, size_t size) { WIND_TCB *tcb; /* pointer to task control block */ void *ret_val; unsigned bytes; bytes = nelem*size; /* bytes to calloc */ ret_val = (*addr_of_calloc)(bytes+4, 1); /* call real calloc, ask for 4 extra bytes to store TID */ if (ret_val) { /* if calloc success */ long *sp; /* stack pointer */ tcb = (WIND_TCB*)taskIdSelf(); /* get TID */ *(WIND_TCB**)ret_val = tcb; /* put TID at start of calloc buffer */ tcb->spare1++; /* inc allocated block counter for this task */ tcb->spare2 += (*((int*)ret_val - 1) - 12); /* vxWorks puts length of buff (+ buf's linked list overhead size (8 bytes)) into longword before calloc's return address. Subtract 4 more for the extra 4 asked for (total 12) to find size of caller's request. Add this to this tasks total bytes allocated */ sp = (long*)getStackPointer(); /* get stack pointer so the caller of this routine can be found */ tcb->spare3 = (int)sp[7] - 6; /* caller PC (JSR instruction is 6 bytes long itself) */ } (char*)ret_val += 4; /* adjust calloc return value so caller doesn't see TID info */ return ret_val; } /****************************************************************************/ void free(void *ptr) { WIND_TCB *tcb; /* pointer to task control block */ (char*)ptr -= 4; /* adjust pointer for 4 extra bytes asked for by malloc or calloc */ tcb = *(WIND_TCB**)ptr; /* get TID of task that did malloc or calloc */ if (!((unsigned)tcb & 0x80000000) && taskIdVerify((int)tcb) == OK) { /* if not already freed and TID is real */ *(unsigned*)ptr |= 0x80000000; /* set top bit in TID to indicate not allocated */ tcb->spare1--; /* adjust task's allocated block counter */ tcb->spare2 -= (*((int*)ptr - 1) - 12); /* adjust task's allocated byte counter */ } (*addr_of_free)(ptr); /* call real free routine */ return; } /****************************************************************************/ #define MAX_TASKS 256 int memTrack(void) { int tid[MAX_TASKS]; int i, num_tasks; int blocks = 0; int bytes = 0; char caller[64]; int actual_addr; SYM_TYPE sym_type; num_tasks = taskIdListGet(tid, MAX_TASKS); /* get all TIDs */ printf("\n"); printf("Task Name TID Blocks Bytes Last-caller PC\n"); printf("--------------- -------- ------- -------- ------------------------------ --------\n"); for (i=0; i<num_tasks; i++) { if (((WIND_TCB*)tid[i])->spare1) { /* if blocks allocated by this task */ blocks += ((WIND_TCB*)tid[i])->spare1; /* add up for total */ bytes += ((WIND_TCB*)tid[i])->spare2; /* add up for total */ symFindByValue(sysSymTbl, /* find caller routine name */ ((WIND_TCB*)tid[i])->spare3, caller, &actual_addr, &sym_type); sprintf(caller, "%s + 0x%x", caller, ((WIND_TCB*)tid[i])->spare3 - actual_addr); printf("%-15s %8x %7d %8d %30s %8x\n", taskName(tid[i]), tid[i], ((WIND_TCB*)tid[i])->spare1, ((WIND_TCB*)tid[i])->spare2, caller, ((WIND_TCB*)tid[i])->spare3); } } printf("TOTAL %9d %8d\n", blocks, bytes); return 0; } |
|