#include "vinumhdr.h"
#ifdef VINUMDEBUG
#include "request.h"
extern struct rqinfo rqinfo[];
extern struct rqinfo *rqip;
int rqinfo_size = RQINFO_SIZE;
#define LongJmp longjmp
#endif
char *
basename(char *file)
{
char *f = rindex(file, '/');
if (f == NULL)
return file;
else
return ++f;
}
void
expand_table(void **table, int oldsize, int newsize)
{
if (newsize > oldsize) {
int *temp;
crit_enter();
temp = (int *) Malloc(newsize);
CHECKALLOC(temp, "vinum: Can't expand table\n");
bzero((char *) temp, newsize);
if (*table != NULL) {
bcopy((char *) *table, (char *) temp, oldsize);
Free(*table);
}
*table = temp;
crit_exit();
}
}
#ifdef VINUMDEBUG
#define MALLOCENTRIES 16384
int malloccount = 0;
int highwater = 0;
struct mc malloced[MALLOCENTRIES];
#define FREECOUNT 64
int freecount = FREECOUNT;
int lastfree = 0;
struct mc freeinfo[FREECOUNT];
int total_malloced;
static int mallocseq = 0;
caddr_t
MMalloc(int size, char *file, int line)
{
caddr_t result;
int i;
if (malloccount >= MALLOCENTRIES) {
log(LOG_ERR, "vinum: can't allocate table space to trace memory allocation");
return 0;
}
result = kmalloc(size, M_DEVBUF, mycpu->gd_intr_nesting_level == 0 ? M_WAITOK : M_INTWAIT);
if (result == NULL)
log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line);
else {
crit_enter();
for (i = 0; i < malloccount; i++) {
if (((result + size) > malloced[i].address)
&& (result < malloced[i].address + malloced[i].size))
Debugger("Malloc overlap");
}
if (result) {
char *f = basename(file);
i = malloccount++;
total_malloced += size;
microtime(&malloced[i].time);
malloced[i].seq = mallocseq++;
malloced[i].size = size;
malloced[i].line = line;
malloced[i].address = result;
bcopy(f, malloced[i].file, min(strlen(f), MCFILENAMELEN - 1));
malloced[i].file[MCFILENAMELEN - 1] = '\0';
}
if (malloccount > highwater)
highwater = malloccount;
crit_exit();
}
return result;
}
void
FFree(void *mem, char *file, int line)
{
int i;
crit_enter();
for (i = 0; i < malloccount; i++) {
if ((caddr_t) mem == malloced[i].address) {
bzero(mem, malloced[i].size);
kfree(mem, M_DEVBUF);
malloccount--;
total_malloced -= malloced[i].size;
if (debug & DEBUG_MEMFREE) {
char *f = rindex(file, '/');
if (f == NULL)
f = file;
else
f++;
microtime(&freeinfo[lastfree].time);
freeinfo[lastfree].seq = malloced[i].seq;
freeinfo[lastfree].size = malloced[i].size;
freeinfo[lastfree].line = line;
freeinfo[lastfree].address = mem;
bcopy(f, freeinfo[lastfree].file, min(strlen(f), MCFILENAMELEN - 1));
freeinfo[lastfree].file[MCFILENAMELEN - 1] = '\0';
if (++lastfree == FREECOUNT)
lastfree = 0;
}
if (i < malloccount)
bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc));
crit_exit();
return;
}
}
log(LOG_ERR,
"Freeing unallocated data at 0x%p from %s, line %d\n",
mem,
file,
line);
Debugger("Free");
crit_exit();
}
void
vinum_meminfo(caddr_t data)
{
struct meminfo *m = (struct meminfo *) data;
m->mallocs = malloccount;
m->total_malloced = total_malloced;
m->malloced = malloced;
m->highwater = highwater;
}
int
vinum_mallocinfo(caddr_t data)
{
struct mc *m = (struct mc *) data;
unsigned int ent = m->seq;
if (ent >= malloccount)
return ENOENT;
m->address = malloced[ent].address;
m->size = malloced[ent].size;
m->line = malloced[ent].line;
m->seq = malloced[ent].seq;
bcopy(malloced[ent].file, m->file, MCFILENAMELEN);
return 0;
}
int
vinum_rqinfo(caddr_t data)
{
struct rqinfo *rq = (struct rqinfo *) data;
int ent = *(int *) data;
int lastent = rqip - rqinfo;
if (ent >= RQINFO_SIZE)
return ENOENT;
if ((ent = lastent - ent - 1) < 0)
ent += RQINFO_SIZE;
bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
return 0;
}
#endif