Malloc wrapper for tracking memory usage during debugging.
[platform/upstream/libvorbis.git] / lib / misc.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
6  * PLEASE READ THESE TERMS DISTRIBUTING.                            *
7  *                                                                  *
8  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
9  * by Monty <monty@xiph.org> and The XIPHOPHORUS Company            *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************/
13
14 #define HEAD_ALIGN 32
15 #include <pthread.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include "vorbis/codec.h"
19 #define MISC_C
20 #include "misc.h"
21
22 static pthread_mutex_t memlock=PTHREAD_MUTEX_INITIALIZER;
23 void **pointers=NULL;
24 long *insertlist=NULL; /* We can't embed this in the pointer list;
25                           a pointer can have any value... */
26 int ptop=0;
27 int palloced=0;
28 int pinsert=0;
29
30 typedef struct {
31   char *file;
32   long line;
33   long ptr;
34 } head;
35
36 static void *_insert(void *ptr,char *file,long line){
37   ((head *)ptr)->file=file;
38   ((head *)ptr)->line=line;
39   ((head *)ptr)->ptr=pinsert;
40
41   pthread_mutex_lock(&memlock);
42   if(pinsert>=palloced){
43     palloced+=64;
44     if(pointers){
45       pointers=(void **)realloc(pointers,sizeof(void **)*palloced);
46       insertlist=(long *)realloc(insertlist,sizeof(long *)*palloced);
47     }else{
48       pointers=(void **)malloc(sizeof(void **)*palloced);
49       insertlist=(long *)malloc(sizeof(long *)*palloced);
50     }
51   }
52
53   pointers[pinsert]=ptr;
54
55   if(pinsert==ptop)
56     pinsert=++ptop;
57   else
58     pinsert=insertlist[pinsert];
59   
60   pthread_mutex_unlock(&memlock);
61   return(ptr+HEAD_ALIGN);
62 }
63
64 static void _ripremove(void *ptr){
65   int insert;
66   pthread_mutex_lock(&memlock);
67   insert=((head *)ptr)->ptr;
68   insertlist[insert]=pinsert;
69   pinsert=insert;
70   pointers[insert]=NULL;
71   pthread_mutex_unlock(&memlock);
72 }
73
74 void _VDBG_dump(void){
75   int i;
76   pthread_mutex_lock(&memlock);
77   for(i=0;i<ptop;i++){
78     head *ptr=pointers[i];
79     if(ptr)
80       fprintf(stderr,"unfreed bytes from %s:%ld\n",
81               ptr->file,ptr->line);
82   }
83
84   pthread_mutex_unlock(&memlock);
85 }
86
87 extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line){
88   bytes+=HEAD_ALIGN;
89   if(ptr){
90     ptr-=HEAD_ALIGN;
91     _ripremove(ptr);
92     ptr=realloc(ptr,bytes);
93   }else{
94     ptr=malloc(bytes);
95     memset(ptr,0,bytes);
96   }
97   return _insert(ptr,file,line);
98 }
99
100 extern void _VDBG_free(void *ptr,char *file,long line){
101   if(ptr){
102     ptr-=HEAD_ALIGN;
103     _ripremove(ptr);
104     free(ptr);
105   }
106 }
107