}
/*
* Memory diagnosics: memTrack.c
*
* Author: Richard Dickson ([email protected])
*
* $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;
}