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