Fix memory leak in psy code.
[platform/upstream/libvorbis.git] / lib / misc.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************/
12
13 #define HEAD_ALIGN 32
14 #include <pthread.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include "vorbis/codec.h"
19 #define MISC_C
20 #include "misc.h"
21 #include <sys/time.h>
22
23 static pthread_mutex_t memlock=PTHREAD_MUTEX_INITIALIZER;
24 static void **pointers=NULL;
25 static long *insertlist=NULL; /* We can't embed this in the pointer list;
26                           a pointer can have any value... */
27
28 static char **files=NULL;
29 static long *file_bytes=NULL;
30 static int  filecount=0;
31
32 static int ptop=0;
33 static int palloced=0;
34 static int pinsert=0;
35
36 typedef struct {
37   char *file;
38   long line;
39   long ptr;
40   long bytes;
41 } head;
42
43 long global_bytes=0;
44 long start_time=-1;
45
46 static void *_insert(void *ptr,long bytes,char *file,long line){
47   ((head *)ptr)->file=file;
48   ((head *)ptr)->line=line;
49   ((head *)ptr)->ptr=pinsert;
50   ((head *)ptr)->bytes=bytes-HEAD_ALIGN;
51
52   pthread_mutex_lock(&memlock);
53   if(pinsert>=palloced){
54     palloced+=64;
55     if(pointers){
56       pointers=(void **)realloc(pointers,sizeof(void **)*palloced);
57       insertlist=(long *)realloc(insertlist,sizeof(long *)*palloced);
58     }else{
59       pointers=(void **)malloc(sizeof(void **)*palloced);
60       insertlist=(long *)malloc(sizeof(long *)*palloced);
61     }
62   }
63
64   pointers[pinsert]=ptr;
65
66   if(pinsert==ptop)
67     pinsert=++ptop;
68   else
69     pinsert=insertlist[pinsert];
70
71 #ifdef _VDBG_GRAPHFILE
72   {
73     FILE *out;
74     struct timeval tv;
75     static struct timezone tz;
76     int i;
77     char buffer[80];
78     gettimeofday(&tv,&tz);
79
80     for(i=0;i<filecount;i++)
81       if(!strcmp(file,files[i]))break;
82
83     if(i==filecount){
84       filecount++;
85       if(!files){
86         files=malloc(filecount*sizeof(*files));
87         file_bytes=malloc(filecount*sizeof(*file_bytes));
88       }else{
89         files=realloc(files,filecount*sizeof(*files));
90         file_bytes=realloc(file_bytes,filecount*sizeof(*file_bytes));
91       }
92       files[i]=strdup(file);
93       file_bytes[i]=0;
94     }
95
96     file_bytes[i]+=bytes-HEAD_ALIGN;
97
98     if(start_time==-1)start_time=(tv.tv_sec*1000)+(tv.tv_usec/1000);
99
100     snprintf(buffer,80,"%s%s",file,_VDBG_GRAPHFILE);
101     out=fopen(buffer,"a");
102     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
103             file_bytes[i]-(bytes-HEAD_ALIGN));
104     fprintf(out,"%ld, %ld # FILE %s LINE %ld\n",
105             -start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
106             file_bytes[i],file,line);
107     fclose(out);
108
109     out=fopen(_VDBG_GRAPHFILE,"a");
110     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
111             global_bytes);
112     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
113             global_bytes+(bytes-HEAD_ALIGN));
114     fclose(out);
115   }
116 #endif
117
118   global_bytes+=(bytes-HEAD_ALIGN);
119
120   pthread_mutex_unlock(&memlock);
121   return(ptr+HEAD_ALIGN);
122 }
123
124 static void _ripremove(void *ptr){
125   int insert;
126   pthread_mutex_lock(&memlock);
127
128 #ifdef _VDBG_GRAPHFILE
129   {
130     FILE *out=fopen(_VDBG_GRAPHFILE,"a");
131     struct timeval tv;
132     static struct timezone tz;
133     char buffer[80];
134     char *file =((head *)ptr)->file;
135     long bytes =((head *)ptr)->bytes;
136     int i;
137
138     gettimeofday(&tv,&tz);
139     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
140             global_bytes);
141     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
142             global_bytes-((head *)ptr)->bytes);
143     fclose(out);
144
145     for(i=0;i<filecount;i++)
146       if(!strcmp(file,files[i]))break;
147
148     snprintf(buffer,80,"%s%s",file,_VDBG_GRAPHFILE);
149     out=fopen(buffer,"a");
150     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
151             file_bytes[i]);
152     fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
153             file_bytes[i]-bytes);
154     fclose(out);
155
156     file_bytes[i]-=bytes;
157
158   }
159 #endif
160
161   global_bytes-=((head *)ptr)->bytes;
162
163   insert=((head *)ptr)->ptr;
164   insertlist[insert]=pinsert;
165   pinsert=insert;
166
167   if(pointers[insert]==NULL){
168     fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing previously freed memory\n");
169     fprintf(stderr,"\t%s %ld\n",((head *)ptr)->file,((head *)ptr)->line);
170   }
171
172   if(global_bytes<0){
173     fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing unmalloced memory\n");
174   }
175
176   pointers[insert]=NULL;
177   pthread_mutex_unlock(&memlock);
178 }
179
180 void _VDBG_dump(void){
181   int i;
182   pthread_mutex_lock(&memlock);
183   for(i=0;i<ptop;i++){
184     head *ptr=pointers[i];
185     if(ptr)
186       fprintf(stderr,"unfreed bytes from %s:%ld\n",
187               ptr->file,ptr->line);
188   }
189
190   pthread_mutex_unlock(&memlock);
191 }
192
193 extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line){
194   bytes+=HEAD_ALIGN;
195   if(ptr){
196     ptr-=HEAD_ALIGN;
197     _ripremove(ptr);
198     ptr=realloc(ptr,bytes);
199   }else{
200     ptr=malloc(bytes);
201     memset(ptr,0,bytes);
202   }
203   return _insert(ptr,bytes,file,line);
204 }
205
206 extern void _VDBG_free(void *ptr,char *file,long line){
207   if(ptr){
208     ptr-=HEAD_ALIGN;
209     _ripremove(ptr);
210     free(ptr);
211   }
212 }
213