/************************************************************************
* Copyright (C) 2002-2009, Xiph.org Foundation
* Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the names of the Xiph.org Foundation nor Pinknoise
* Productions Ltd nor the names of its contributors may be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
#define HEAD_ALIGN 64
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MISC_C
#include "misc.h"
//#include <sys/time.h>
static void **pointers=NULL;
static long *insertlist=NULL; /* We can't embed this in the pointer list;
a pointer can have any value... */
static char **files=NULL;
static long *file_bytes=NULL;
static int filecount=0;
static int ptop=0;
static int palloced=0;
static int pinsert=0;
typedef struct {
char *file;
long line;
long ptr;
long bytes;
} head;
long global_bytes=0;
long start_time=-1;
static void *_insert(void *ptr,long bytes,char *file,long line){
((head *)ptr)->file=file;
((head *)ptr)->line=line;
((head *)ptr)->ptr=pinsert;
((head *)ptr)->bytes=bytes-HEAD_ALIGN;
if(pinsert>=palloced){
palloced+=64;
if(pointers){
pointers=(void **)realloc(pointers,sizeof(void **)*palloced);
insertlist=(long *)realloc(insertlist,sizeof(long *)*palloced);
}else{
pointers=(void **)malloc(sizeof(void **)*palloced);
insertlist=(long *)malloc(sizeof(long *)*palloced);
}
}
pointers[pinsert]=ptr;
if(pinsert==ptop)
pinsert=++ptop;
else
pinsert=insertlist[pinsert];
#ifdef _VDBG_GRAPHFILE
{
FILE *out;
struct timeval tv;
static struct timezone tz;
int i;
char buffer[80];
gettimeofday(&tv,&tz);
for(i=0;i<filecount;i++)
if(!strcmp(file,files[i]))break;
if(i==filecount){
filecount++;
if(!files){
files=malloc(filecount*sizeof(*files));
file_bytes=malloc(filecount*sizeof(*file_bytes));
}else{
files=realloc(files,filecount*sizeof(*files));
file_bytes=realloc(file_bytes,filecount*sizeof(*file_bytes));
}
files[i]=strdup(file);
file_bytes[i]=0;
}
file_bytes[i]+=bytes-HEAD_ALIGN;
if(start_time==-1)start_time=(tv.tv_sec*1000)+(tv.tv_usec/1000);
snprintf(buffer,80,"%s",file);
if(strchr(buffer,'.'))strchr(buffer,'.')[0]=0;
strcat(buffer,_VDBG_GRAPHFILE);
out=fopen(buffer,"a");
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
file_bytes[i]-(bytes-HEAD_ALIGN));
fprintf(out,"%ld, %ld # FILE %s LINE %ld\n",
-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
file_bytes[i],file,line);
fclose(out);
out=fopen("total"_VDBG_GRAPHFILE,"a");
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
global_bytes);
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
global_bytes+(bytes-HEAD_ALIGN));
fclose(out);
}
#endif
global_bytes+=(bytes-HEAD_ALIGN);
return(void *)(((char *)ptr)+HEAD_ALIGN);
}
static void _ripremove(void *ptr){
int insert;
#ifdef _VDBG_GRAPHFILE
{
FILE *out=fopen("total"_VDBG_GRAPHFILE,"a");
struct timeval tv;
static struct timezone tz;
char buffer[80];
char *file =((head *)ptr)->file;
long bytes =((head *)ptr)->bytes;
int i;
gettimeofday(&tv,&tz);
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
global_bytes);
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
global_bytes-((head *)ptr)->bytes);
fclose(out);
for(i=0;i<filecount;i++)
if(!strcmp(file,files[i]))break;
snprintf(buffer,80,"%s",file);
if(strchr(buffer,'.'))strchr(buffer,'.')[0]=0;
strcat(buffer,_VDBG_GRAPHFILE);
out=fopen(buffer,"a");
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
file_bytes[i]);
fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
file_bytes[i]-bytes);
fclose(out);
file_bytes[i]-=bytes;
}
#endif
global_bytes-=((head *)ptr)->bytes;
insert=((head *)ptr)->ptr;
insertlist[insert]=pinsert;
pinsert=insert;
if(pointers[insert]==NULL){
fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing previously freed memory\n");
fprintf(stderr,"\t%s %ld\n",((head *)ptr)->file,((head *)ptr)->line);
}
if(global_bytes<0){
fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing unmalloced memory\n");
}
pointers[insert]=NULL;
}
void _VDBG_dump(void){
int i;
for(i=0;i<ptop;i++){
head *ptr=pointers[i];
if(ptr)
fprintf(stderr,"unfreed bytes from %s:%ld\n",
ptr->file,ptr->line);
}
}
extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line){
bytes+=HEAD_ALIGN;
if(ptr){
ptr=(void *)(((char *)ptr)-HEAD_ALIGN);
_ripremove(ptr);
ptr=realloc(ptr,bytes);
}else{
ptr=malloc(bytes);
memset(ptr,0,bytes);
}
return _insert(ptr,bytes,file,line);
}
extern void _VDBG_free(void *ptr){
if(ptr){
ptr=(void *)(((char *)ptr)-HEAD_ALIGN);
_ripremove(ptr);
free(ptr);
}
}