| /************************************************************************ |
| * 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); |
| } |
| } |
| |