1 /************************************************************************
2  * Copyright (C) 2002-2009, Xiph.org Foundation
3  * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  *     * Neither the names of the Xiph.org Foundation nor Pinknoise
17  * Productions Ltd nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without
19  * specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  ************************************************************************/
33 
34 #define HEAD_ALIGN 64
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
38 #define MISC_C
39 #include "misc.h"
40 //#include <sys/time.h>
41 
42 static void **pointers=NULL;
43 static long *insertlist=NULL; /* We can't embed this in the pointer list;
44 			  a pointer can have any value... */
45 
46 static char **files=NULL;
47 static long *file_bytes=NULL;
48 static int  filecount=0;
49 
50 static int ptop=0;
51 static int palloced=0;
52 static int pinsert=0;
53 
54 typedef struct {
55   char *file;
56   long line;
57   long ptr;
58   long bytes;
59 } head;
60 
61 long global_bytes=0;
62 long start_time=-1;
63 
_insert(void * ptr,long bytes,char * file,long line)64 static void *_insert(void *ptr,long bytes,char *file,long line){
65   ((head *)ptr)->file=file;
66   ((head *)ptr)->line=line;
67   ((head *)ptr)->ptr=pinsert;
68   ((head *)ptr)->bytes=bytes-HEAD_ALIGN;
69 
70   if(pinsert>=palloced){
71     palloced+=64;
72     if(pointers){
73       pointers=(void **)realloc(pointers,sizeof(void **)*palloced);
74       insertlist=(long *)realloc(insertlist,sizeof(long *)*palloced);
75     }else{
76       pointers=(void **)malloc(sizeof(void **)*palloced);
77       insertlist=(long *)malloc(sizeof(long *)*palloced);
78     }
79   }
80 
81   pointers[pinsert]=ptr;
82 
83   if(pinsert==ptop)
84     pinsert=++ptop;
85   else
86     pinsert=insertlist[pinsert];
87 
88 #ifdef _VDBG_GRAPHFILE
89   {
90     FILE *out;
91     struct timeval tv;
92     static struct timezone tz;
93     int i;
94     char buffer[80];
95     gettimeofday(&tv,&tz);
96 
97     for(i=0;i<filecount;i++)
98       if(!strcmp(file,files[i]))break;
99 
100     if(i==filecount){
101       filecount++;
102       if(!files){
103 	files=malloc(filecount*sizeof(*files));
104 	file_bytes=malloc(filecount*sizeof(*file_bytes));
105       }else{
106 	files=realloc(files,filecount*sizeof(*files));
107 	file_bytes=realloc(file_bytes,filecount*sizeof(*file_bytes));
108       }
109       files[i]=strdup(file);
110       file_bytes[i]=0;
111     }
112 
113     file_bytes[i]+=bytes-HEAD_ALIGN;
114 
115     if(start_time==-1)start_time=(tv.tv_sec*1000)+(tv.tv_usec/1000);
116 
117     snprintf(buffer,80,"%s",file);
118     if(strchr(buffer,'.'))strchr(buffer,'.')[0]=0;
119     strcat(buffer,_VDBG_GRAPHFILE);
120     out=fopen(buffer,"a");
121     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
122 	    file_bytes[i]-(bytes-HEAD_ALIGN));
123     fprintf(out,"%ld, %ld # FILE %s LINE %ld\n",
124 	    -start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
125 	    file_bytes[i],file,line);
126     fclose(out);
127 
128     out=fopen("total"_VDBG_GRAPHFILE,"a");
129     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
130 	    global_bytes);
131     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
132 	    global_bytes+(bytes-HEAD_ALIGN));
133     fclose(out);
134   }
135 #endif
136 
137   global_bytes+=(bytes-HEAD_ALIGN);
138 
139   return(void *)(((char *)ptr)+HEAD_ALIGN);
140 }
141 
_ripremove(void * ptr)142 static void _ripremove(void *ptr){
143   int insert;
144 
145 #ifdef _VDBG_GRAPHFILE
146   {
147     FILE *out=fopen("total"_VDBG_GRAPHFILE,"a");
148     struct timeval tv;
149     static struct timezone tz;
150     char buffer[80];
151     char *file =((head *)ptr)->file;
152     long bytes =((head *)ptr)->bytes;
153     int i;
154 
155     gettimeofday(&tv,&tz);
156     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
157 	    global_bytes);
158     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
159 	    global_bytes-((head *)ptr)->bytes);
160     fclose(out);
161 
162     for(i=0;i<filecount;i++)
163       if(!strcmp(file,files[i]))break;
164 
165     snprintf(buffer,80,"%s",file);
166     if(strchr(buffer,'.'))strchr(buffer,'.')[0]=0;
167     strcat(buffer,_VDBG_GRAPHFILE);
168     out=fopen(buffer,"a");
169     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
170 	    file_bytes[i]);
171     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
172 	    file_bytes[i]-bytes);
173     fclose(out);
174 
175     file_bytes[i]-=bytes;
176 
177   }
178 #endif
179 
180   global_bytes-=((head *)ptr)->bytes;
181 
182   insert=((head *)ptr)->ptr;
183   insertlist[insert]=pinsert;
184   pinsert=insert;
185 
186   if(pointers[insert]==NULL){
187     fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing previously freed memory\n");
188     fprintf(stderr,"\t%s %ld\n",((head *)ptr)->file,((head *)ptr)->line);
189   }
190 
191   if(global_bytes<0){
192     fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing unmalloced memory\n");
193   }
194 
195   pointers[insert]=NULL;
196 }
197 
_VDBG_dump(void)198 void _VDBG_dump(void){
199   int i;
200   for(i=0;i<ptop;i++){
201     head *ptr=pointers[i];
202     if(ptr)
203       fprintf(stderr,"unfreed bytes from %s:%ld\n",
204 	      ptr->file,ptr->line);
205   }
206 
207 }
208 
_VDBG_malloc(void * ptr,long bytes,char * file,long line)209 extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line){
210   bytes+=HEAD_ALIGN;
211   if(ptr){
212     ptr=(void *)(((char *)ptr)-HEAD_ALIGN);
213     _ripremove(ptr);
214     ptr=realloc(ptr,bytes);
215   }else{
216     ptr=malloc(bytes);
217     memset(ptr,0,bytes);
218   }
219   return _insert(ptr,bytes,file,line);
220 }
221 
_VDBG_free(void * ptr,char * file,long line)222 extern void _VDBG_free(void *ptr,char *file,long line){
223   if(ptr){
224     ptr=(void *)(((char *)ptr)-HEAD_ALIGN);
225     _ripremove(ptr);
226     free(ptr);
227   }
228 }
229 
230