1 
2 #include <stdlib.h>
3 #include "taucs.h"
4 
5 #undef malloc
6 #undef calloc
7 #undef realloc
8 #undef free
9 
taucs_malloc_stub(size_t size)10 void* taucs_malloc_stub (size_t size)               { return malloc(size); }
taucs_calloc_stub(size_t nmemb,size_t size)11 void* taucs_calloc_stub (size_t nmemb, size_t size) { return calloc(nmemb,size); }
taucs_realloc_stub(void * ptr,size_t size)12 void* taucs_realloc_stub(void* ptr, size_t size)    { return realloc(ptr,size); }
taucs_free_stub(void * ptr)13 void  taucs_free_stub   (void* ptr)                 { free(ptr); }
14 
15 #if !defined(TAUCS_MEMORY_TEST_yes)
16 
taucs_allocation_amount()17 double taucs_allocation_amount()   { return 0.0; }
taucs_allocation_count()18 int    taucs_allocation_count()    { return 0; }
taucs_allocation_attempts()19 int    taucs_allocation_attempts() { return 0; }
taucs_allocation_assert_clean()20 void   taucs_allocation_assert_clean() {}
taucs_allocation_mark_clean()21 void   taucs_allocation_mark_clean() {}
taucs_allocation_induce_failure(int i)22 void   taucs_allocation_induce_failure(int i) {}
23 
24 #else /* we do want memory testing */
25 
26 #define TABLE_SIZE 100000
27 
28 static int    allocation_initialized = 0;
29 
30 static void*  allocation_ptr  [TABLE_SIZE];
31 static double allocation_size [TABLE_SIZE];
32 static char*  allocation_file [TABLE_SIZE];
33 static int    allocation_line [TABLE_SIZE];
34 static int    allocation_clean[TABLE_SIZE];
35 
36 static int    allocation_attempts;
37 static int    allocation_count;
38 static double allocation_amount;
39 static int    allocation_clean_count;
40 static double allocation_clean_amount;
41 
42 static int    allocation_induced_failure;
43 
allocation_init()44 static void allocation_init()
45 {
46   int i;
47 
48   allocation_initialized = 1;
49 
50   allocation_induced_failure = -1;
51   allocation_attempts = 0;
52   allocation_count = 0;
53   allocation_amount = 0.0;
54 
55   for (i=0; i<TABLE_SIZE; i++)
56     allocation_ptr[i] = NULL;
57 }
58 
allocation_insert(void * ptr,double size,char * file,int line)59 static void allocation_insert(void* ptr, double size, char* file, int line)
60 {
61   int i,j,slot;
62   union {
63     void* p;
64     int   i;
65   } converter;
66 
67   slot = -1; /* none found yet */
68 
69   converter.p = ptr;
70   j = converter.i % TABLE_SIZE;
71 
72   for (i=0; i<TABLE_SIZE; i++) {
73     if (allocation_ptr[j] == NULL) {
74       slot = j;
75       break;
76     }
77     j++;
78   }
79 
80   if (slot == -1) {
81     taucs_printf("TAUCS ALLOCATION ERROR: ALLOCATION TABLE IS FULL\n");
82     exit(1);
83   }
84 
85   allocation_ptr  [slot] = ptr;
86   allocation_size [slot] = size;
87   allocation_file [slot] = file;
88   allocation_line [slot] = line;
89   allocation_clean[slot] = 0;
90 }
91 
allocation_delete(void * ptr)92 static double allocation_delete(void* ptr)
93 {
94   int i,j,slot;
95   union {
96     void* p;
97     int   i;
98   } converter;
99   double size;
100 
101   slot = -1; /* none found yet */
102 
103   converter.p = ptr;
104   j = converter.i % TABLE_SIZE;
105 
106   for (i=0; i<TABLE_SIZE; i++) {
107     if (allocation_ptr[j] == ptr) {
108       slot = j;
109       break;
110     }
111     j++;
112   }
113 
114   if (slot == -1) return -1.0;
115 
116   size = allocation_size[slot];
117 
118   allocation_ptr[slot] = NULL;
119 
120   return size;
121 }
122 
taucs_allocation_amount()123 double taucs_allocation_amount()   { return allocation_amount; }
taucs_allocation_count()124 int    taucs_allocation_count()    { return allocation_count; }
taucs_allocation_attempts()125 int    taucs_allocation_attempts() { return allocation_attempts; }
126 
taucs_allocation_induce_failure(int i)127 void   taucs_allocation_induce_failure(int i)  { allocation_induced_failure = i; }
128 
taucs_allocation_assert_clean()129 void taucs_allocation_assert_clean()
130 {
131   int i,clean = 1;
132 
133   for (i=0; i<TABLE_SIZE; i++) {
134     if (allocation_ptr[i] != NULL && !allocation_clean[i]) {
135       clean = 0;
136     }
137   }
138 
139   if (!clean) {
140     taucs_printf("TAUCS ALLOCATION ERROR: ASSERTED CLEAN, BUT FOUND\n");
141 
142     for (i=0; i<TABLE_SIZE; i++) {
143       if (allocation_ptr[i] != NULL && !allocation_clean[i]) {
144 	taucs_printf("\tBLOCK ALLOCATED AT %s:%d STILL ALLOCATED (%.2e BYTES)\n",
145 		     allocation_file[i],allocation_line[i],allocation_size[i]);
146       }
147     }
148     exit(1);
149   }
150 }
151 
taucs_allocation_mark_clean()152 void taucs_allocation_mark_clean()
153 {
154   int i;
155 
156   allocation_attempts = 0;
157   allocation_clean_count  = allocation_count;
158   allocation_clean_amount = allocation_amount;
159 
160   for (i=0; i<TABLE_SIZE; i++) {
161     if (allocation_ptr[i] != NULL)
162       allocation_clean[i] = 1;
163   }
164 }
165 
taucs_internal_calloc(size_t nmemb,size_t size,char * file,int line)166 void* taucs_internal_calloc(size_t nmemb, size_t size,
167 			    char* file, int line)
168 {
169   void* ptr;
170 
171   if (nmemb*size == 0) {
172     taucs_printf("TAUCS ALLOCATION: ZERO SIZE (%s:%d)\n",
173 		 file, line);
174     return NULL;
175   }
176 
177   if (!allocation_initialized) allocation_init();
178 
179   if (allocation_induced_failure == allocation_attempts) {
180     allocation_induced_failure = -1;
181     taucs_printf("TAUCS ALLOCATION: INDUCING FAILURE (%s:%d, count=%d)\n",
182 		 file, line, allocation_attempts);
183     return NULL;
184   }
185 
186   ptr = calloc(nmemb,size);
187 
188   if (ptr) {
189     allocation_count++;
190     allocation_attempts++;
191     allocation_amount += (double) nmemb * (double) size;
192     allocation_insert(ptr, (double) nmemb * (double) size, file, line);
193   } else
194     taucs_printf("TAUCS ALLOCATION WARNING: CALLOC AT %s:%d FAILED\n",
195 		 file,line);
196 
197   return ptr;
198 }
199 
taucs_internal_malloc(size_t size,char * file,int line)200 void* taucs_internal_malloc(size_t size,
201 			    char* file, int line)
202 {
203   void* ptr;
204 
205   if (size == 0) {
206     taucs_printf("TAUCS ALLOCATION: ZERO SIZE (%s:%d)\n",
207 		 file, line);
208     return NULL;
209   }
210 
211   if (!allocation_initialized) allocation_init();
212 
213   if (allocation_induced_failure == allocation_attempts) {
214     allocation_induced_failure = -1;
215     taucs_printf("TAUCS ALLOCATION: INDUCING FAILURE (%s:%d, count=%d)\n",
216 		 file, line, allocation_attempts);
217     return NULL;
218   }
219 
220   ptr = malloc(size);
221 
222   if (ptr) {
223     allocation_count++;
224     allocation_attempts++;
225     allocation_amount += (double) size;
226     allocation_insert(ptr, (double) size, file, line);
227   } else
228     taucs_printf("TAUCS ALLOCATION WARNING: CALLOC AT %s:%d FAILED\n",
229 		 file,line);
230 
231   return ptr;
232 }
233 
taucs_internal_realloc(void * oldptr,size_t size,char * file,int line)234 void* taucs_internal_realloc(void *oldptr, size_t size,
235 			    char* file, int line)
236 
237 {
238   void* ptr;
239 
240   if (size == 0) {
241     taucs_printf("TAUCS ALLOCATION: ZERO SIZE (%s:%d)\n",
242 		 file, line);
243     return NULL;
244   }
245 
246   if (!allocation_initialized) allocation_init();
247 
248 
249   if (allocation_induced_failure == allocation_attempts) {
250     allocation_induced_failure = -1;
251     taucs_printf("TAUCS ALLOCATION: INDUCING FAILURE (%s:%d, count=%d)\n",
252 		 file, line, allocation_attempts);
253     return NULL;
254   }
255 
256   ptr= realloc(oldptr,size);
257 
258   /* if realloc returns NULL, nothing happened (memory is not freed) */
259 
260   if (ptr) {
261     double oldsize;
262 
263     oldsize = allocation_delete(oldptr);
264     if (oldsize == -1.0) {
265       taucs_printf("TAUCS ALLOCATION ERROR: REALLOC AT %s:%d NOT ALLOCATED\n",
266 		   file,line);
267       exit(1);
268     }
269     allocation_count--;
270     allocation_amount -= oldsize;
271 
272     allocation_count++;
273     allocation_attempts++;
274     allocation_amount += (double) size;
275     allocation_insert(ptr, (double) size, file, line);
276   } else
277     taucs_printf("TAUCS ALLOCATION WARNING: REALLOC AT %s:%d FAILED\n",
278 		 file,line);
279 
280   return ptr;
281 }
282 
taucs_internal_free(void * oldptr,char * file,int line)283 void taucs_internal_free(void *oldptr,
284 			 char* file, int line)
285 {
286   double oldsize;
287 
288   if (!allocation_initialized) allocation_init();
289 
290   if (!oldptr) return;
291 
292   oldsize = allocation_delete(oldptr);
293   if (oldsize == -1.0) {
294     taucs_printf("TAUCS ALLOCATION ERROR: FREE AT %s:%d NOT ALLOCATED\n",
295 		 file,line);
296     exit(1);
297   }
298   allocation_count--;
299   allocation_amount -= oldsize;
300 
301   free(oldptr);
302 }
303 
304 #endif /* TAUCS_MEMORY_TEST_yes */
305 
306