/[ascend]/trunk/base/generic/utilities/ascMalloc.c
ViewVC logotype

Contents of /trunk/base/generic/utilities/ascMalloc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (show annotations) (download) (as text)
Thu Nov 25 22:52:42 2004 UTC (19 years, 6 months ago) by ben.allan
File MIME type: text/x-csrc
File size: 15558 byte(s)
replaced nonportable strdup with ascend equivalent.
1 /*
2 * Ascend Memory Allocation Routines
3 * by Tom Epperly
4 * Created: 2/6/90
5 * Version: $Revision: 1.1 $
6 * Version control file: $RCSfile: ascMalloc.c,v $
7 * Date last modified: $Date: 1997/07/18 11:44:49 $
8 * Last modified by: $Author: mthomas $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
13 *
14 * The Ascend Language Interpreter is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * The Ascend Language Interpreter is distributed in hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with the program; if not, write to the Free Software Foundation,
26 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
27 * COPYING.
28 *
29 */
30
31 #include <stdio.h>
32 #include <assert.h>
33 #include <limits.h>
34 #include <time.h>
35 #include <malloc.h>
36 #include <stdlib.h>
37 #include "utilities/ascConfig.h"
38 #include "compiler/compiler.h"
39 #include "utilities/ascPanic.h"
40 #include "utilities/ascMalloc.h"
41
42 #define LOGFILE "memlg"
43 #define MAXPOINTERS 1000000
44
45 #ifndef lint
46 static CONST char AscendMemoryAllocRCSid[]="$Id: ascMalloc.c,v 1.1 1997/07/18 11:44:49 mthomas Exp $";
47 #endif
48
49 char *ascstrdup(char *s) {
50 char *result;
51 if (!s) { return 0; }
52 result = (char *)malloc(strlen(s) + 1);
53 strcpy(result, s);
54 return result;
55 }
56
57 char *asc_memcpy(char *to, char *from, unsigned size)
58 {
59 /* We really should be moving stuff a long at a time, but that mean
60 * handling the leading and trailing unaligned bytes separately.
61 * We also really should just be passing on to the vendor memcpy on
62 * those systems which do overlapping ranges right.
63 */
64 char *fill;
65 if (from < to) {
66 fill = (to + size) - 1;
67 from += (size - 1);
68 while (size-- > 0) {
69 *fill-- = *from--;
70 }
71 } else {
72 if (from > to) {
73 fill = to;
74 while (size-- > 0) {
75 *fill++ = *from++;
76 }
77 } /* else from == to, do nothing */
78 }
79 return to;
80 }
81
82 char *ascreallocPUREF(char *ptr,size_t oldbytes, size_t newbytes)
83 {
84 /* shrink */
85 if (newbytes > 0 && newbytes <= oldbytes) return ptr;
86 /* release */
87 if (!newbytes) {
88 ascfree(ptr);
89 return NULL;
90 }
91 /* create */
92 if (!oldbytes) {
93 if (ptr!=NULL) ascfree(ptr); /* some OS allocate 0 bytes, god help us */
94 return (char *)ascmalloc(newbytes);
95 } else {
96 /* expand */
97 char *ret;
98 ret = ascmalloc(newbytes);
99 if (ret==NULL) return NULL;
100 if (oldbytes%sizeof(long) == 0 && ((unsigned long)ptr)%sizeof(long) == 0) {
101 register unsigned long c,len, *src, *trg;
102 src = (unsigned long *)ptr;
103 trg = (unsigned long *)ret;
104 len = oldbytes/sizeof(long);
105 for (c=0;c < len;c++) trg[c]=src[c]; /* copy data as longs */
106 } else {
107 memcpy(ret,ptr,oldbytes);
108 }
109 ascfree(ptr);
110 return ret;
111 }
112 }
113 #ifdef MALLOC_DEBUG
114 struct memory_rec{
115 CONST VOIDPTR ptr;
116 unsigned size;
117 };
118
119 FILE *g_memory_log_file = NULL;
120 int g_memory_length =0;
121 unsigned long g_memory_allocated=0L;
122 unsigned long g_peak_memory_usage=0L;
123 struct memory_rec g_mem_rec[MAXPOINTERS];
124 char *g_memlog_filename = NULL;
125
126 unsigned long ascmeminuse(void)
127 {
128 #ifndef MALLOC_DEBUG
129 return 0;
130 #else
131 return g_memory_allocated;
132 #endif
133 }
134
135 int SortedList(void)
136 {
137 int c;
138 for(c=1;c<g_memory_length;c++)
139 if (g_mem_rec[c-1].ptr>g_mem_rec[c].ptr) return 0;
140 return 1;
141 }
142
143 CONST VOIDPTR MinMemory(void)
144 {
145 int c;
146 CONST VOIDPTR minm=(VOIDPTR)ULONG_MAX;
147 for(c=0;c<g_memory_length;c++)
148 if (g_mem_rec[c].ptr < minm) minm = g_mem_rec[c].ptr;
149 return minm;
150 }
151
152 CONST VOIDPTR MaxMemory(void)
153 {
154 int c;
155 CONST VOIDPTR maxm=0;
156 for(c=0;c<g_memory_length;c++)
157 if (((CONST char *)g_mem_rec[c].ptr+g_mem_rec[c].size)
158 > (CONST char *)maxm)
159 maxm = (CONST VOIDPTR)((CONST char *)g_mem_rec[c].ptr+
160 g_mem_rec[c].size);
161 return maxm;
162 }
163
164 #define NONZERO(x) ((x) ? (x) : 1)
165
166 CONST VOIDPTR MemoryMean(void)
167 {
168 int c,size;
169 double sum=0.0,bytes=0.0;
170 for(c=0;c<g_memory_length;c++){
171 size = g_mem_rec[c].size;
172 if (size){
173 bytes += (double)size;
174 sum += (double)((size * (size-1))/2)
175 + ((double)size) * ((double)(unsigned long)g_mem_rec[c].ptr);
176 }
177 }
178 return (VOIDPTR)(unsigned long)(sum/NONZERO(bytes));
179 }
180
181 void OpenLogFile(void)
182 {
183 if (!g_memlog_filename){
184 time_t t;
185 g_memlog_filename = tempnam(NULL,LOGFILE);
186 if (g_memlog_filename &&
187 (g_memory_log_file = fopen(g_memlog_filename,"w"))==NULL){
188 Asc_Panic(2, NULL, "Unable to open memory log file.\n");
189 }
190 t = time((time_t *)NULL);
191 FPRINTF(g_memory_log_file,"Ascend memory log file opened %s",
192 asctime(localtime(&t)));
193 fclose(g_memory_log_file);
194 g_memory_log_file = NULL;
195 }
196 }
197
198 void WriteMemoryStatus(FILE *f, CONST char *msg)
199 {
200 CONST VOIDPTR minm;
201 CONST VOIDPTR maxm;
202 minm = MinMemory();
203 maxm = MaxMemory();
204 FPRINTF(f,"%s\n"
205 "Current memory usage(byte allocated): %lu\n"
206 "Current number of blocks: %d\n"
207 "Peak memory usage(bytes allocated): %lu\n"
208 "Lowest address: %lx\n"
209 "Highest address: %lx\n"
210 "Memory density: %g\n"
211 "Memory mean: %lx\n",
212 msg,g_memory_allocated,g_memory_length,g_peak_memory_usage,
213 (unsigned long)minm,(unsigned long)maxm,
214 ((double)g_memory_allocated/(double)
215 NONZERO((CONST char *)maxm-(CONST char *)minm)),
216 (unsigned long)MemoryMean());
217 }
218
219 void ascstatus(CONST char *msg)
220 {
221 OpenLogFile();
222 if ((g_memory_log_file=fopen(g_memlog_filename,"a"))){
223 WriteMemoryStatus(g_memory_log_file,msg);
224 fclose(g_memory_log_file);
225 }
226 else
227 FPRINTF(stderr,"Can't open memory log file.\n");
228 WriteMemoryStatus(stdout,msg);
229 }
230
231 void ascshutdown(CONST char *msg)
232 {
233 unsigned long c;
234 OpenLogFile();
235 if ((g_memory_log_file=fopen(g_memlog_filename,"a"))){
236 WriteMemoryStatus(g_memory_log_file,msg);
237 if (g_memory_length) {
238 FPRINTF(g_memory_log_file,
239 "!!!SHUTDOWN MESSAGE -- POINTERS STILL ALLOCATED\n");
240 for(c=0;c < g_memory_length;c++){
241 FPRINTF(g_memory_log_file,"%9lx %9u\n",g_mem_rec[c].ptr,
242 g_mem_rec[c].size);
243 }
244 FPRINTF(g_memory_log_file, "!!!END OF SHUTDOWN MESSAGE\n");
245 } else {
246 FPRINTF(g_memory_log_file, "NO POINTERS STILL ALLOCATED :-)\n");
247 }
248 fclose(g_memory_log_file);
249 FPRINTF(stderr,"Memory log filename: %s\n",g_memlog_filename);
250 free(g_memlog_filename); /* should not be ascfree() */
251 g_memlog_filename = NULL;
252 }
253 else
254 FPRINTF(stderr,"Can't open memory log file.\n");
255 WriteMemoryStatus(stdout,msg);
256 }
257
258 void WriteAllocation(CONST VOIDPTR adr, unsigned int size,
259 CONST char *file, int line)
260 {
261 if ((g_memory_log_file=fopen(g_memlog_filename,"a"))){
262 FPRINTF(g_memory_log_file,"%9lx %9u %20s%d %s\n",
263 (unsigned long)adr,size,"",line,file);
264 fclose(g_memory_log_file);
265 }
266 else{
267 FPRINTF(stderr,"Unable to append to memory log file.\n");
268 FPRINTF(stderr,"%9lx %9u %20s%d %s\n",
269 (unsigned long)adr,size,"",line,file);
270 }
271 }
272
273 void WriteReAllocation(CONST VOIDPTR adr1, unsigned int size1,
274 CONST VOIDPTR adr2, unsigned int size2,
275 CONST char *file, int line)
276 {
277 if ((g_memory_log_file=fopen(g_memlog_filename,"a"))){
278 FPRINTF(g_memory_log_file,"%9lx %9u %9lx %9u %d %s\n",
279 (unsigned long)adr1,size1,(unsigned long)adr2,size2,line,file);
280 fclose(g_memory_log_file);
281 }
282 else{
283 FPRINTF(stderr,"Unable to append to memory log file.\n");
284 FPRINTF(stderr,"%9lx %9u %9lx %9u %d %s\n",
285 (unsigned long)adr1,size1,(unsigned long)adr2,size2,line,file);
286 }
287 }
288
289 void WriteDeallocation(CONST VOIDPTR adr, unsigned int size,
290 CONST char *file, int line)
291 {
292 if ((g_memory_log_file=fopen(g_memlog_filename,"a"))){
293 FPRINTF(g_memory_log_file,"%20s%9lx %9u %d %s\n","",
294 (unsigned long)adr,size,line,file);
295 fclose(g_memory_log_file);
296 }
297 else{
298 FPRINTF(stderr,"Unable to append to memory log file.\n");
299 FPRINTF(stderr,"%20s%9lx %9u %d %s\n","",
300 (unsigned long)adr,size,line,file);
301 }
302 }
303
304 void WriteError(CONST char *msg, CONST char *file, int line)
305 {
306 FPRINTF(stderr,"%s\nCalled from file: %s on line %d.\n",msg,file,line);
307 if ((g_memory_log_file=fopen(g_memlog_filename,"a"))){
308 FPRINTF(g_memory_log_file,"%s\nCalled from file: %s on line %d.\n",
309 msg,file,line);
310 fclose(g_memory_log_file);
311 }
312 }
313
314 int SearchForMemory(CONST VOIDPTR ptr)
315 {
316 int c,l,u;
317 l = 0;
318 u = g_memory_length-1;
319 if (u<l) return -1;
320 while(l<u){
321 c = (l+u)/2;
322 if (g_mem_rec[c].ptr == ptr) return c;
323 if (g_mem_rec[c].ptr > ptr)
324 u = c-1;
325 else
326 l = c+1;
327 }
328 if (u<l) return l;
329 if (l>u) return u;
330 while((l<(g_memory_length-1))&&(g_mem_rec[l].ptr<ptr)) l++;
331 return l;
332 }
333
334 int AllocatedMemory(CONST VOIDPTR ptr, unsigned int size)
335 {
336 int pos,result=0;
337 pos = SearchForMemory(ptr);
338 if ((pos>=0)&&(g_mem_rec[pos].ptr==ptr)){
339 if (g_mem_rec[pos].size==size) return 2;
340 if (g_mem_rec[pos].size>size) return 1;
341 result = -1;
342 }
343 for(pos=0;pos<g_memory_length;pos++){
344 if ((ptr>=g_mem_rec[pos].ptr)&&
345 ((ptr<=(CONST VOIDPTR)((CONST char *)g_mem_rec[pos].ptr+
346 g_mem_rec[pos].size)))){
347 if ((CONST VOIDPTR)((CONST char *)ptr+size)
348 <=(CONST VOIDPTR)((CONST char *)g_mem_rec[pos].ptr+
349 g_mem_rec[pos].size))
350 return 1;
351 else result = -1;
352 }
353 else if (((CONST VOIDPTR)((CONST char *)ptr+size)
354 >=g_mem_rec[pos].ptr)&&
355 ((CONST VOIDPTR)((CONST char *)ptr+size)
356 <=(CONST VOIDPTR)((CONST char *)g_mem_rec[pos].ptr+
357 g_mem_rec[pos].size)))
358 result = -1;
359 }
360 return result;
361 }
362
363 void AddAllocatedMemory(CONST VOIDPTR ptr, unsigned int size,
364 CONST char *file, int line)
365 {
366 int pos,c;
367 pos = SearchForMemory(ptr);
368 if ((pos<0)||(g_mem_rec[pos].ptr != ptr)){
369 if (pos<0) pos=0;
370 if (g_memory_length+1<MAXPOINTERS){
371 if ((pos==g_memory_length-1)&&
372 (g_mem_rec[pos].ptr < ptr)){
373 pos++;
374 g_memory_length++;
375 g_mem_rec[pos].ptr = ptr;
376 g_mem_rec[pos].size = size;
377 }
378 else{
379 /* make room for the new addition */
380 for(c=g_memory_length;c>pos;c--){
381 g_mem_rec[c] = g_mem_rec[c-1];
382 }
383 g_memory_length++;
384 g_mem_rec[pos].ptr = ptr;
385 g_mem_rec[pos].size = size;
386 }
387 }
388 else{
389 FPRINTF(stderr,
390 "Pointer list filled up. Error messages may be unreliable.\n");
391 }
392 }
393 WriteAllocation(ptr,size,file,line);
394 }
395
396 void DeallocateMemory(CONST VOIDPTR ptr, unsigned int size,
397 CONST char *file, int line)
398 {
399 int pos,c;
400 pos = SearchForMemory(ptr);
401 if ((pos>=0)&&(g_mem_rec[pos].ptr==ptr)){
402 assert(g_mem_rec[pos].size==size);
403 for(c=pos+1;c<g_memory_length;c++)
404 g_mem_rec[c-1] = g_mem_rec[c];
405 g_memory_length--;
406 }
407 WriteDeallocation(ptr,size,file,line);
408 }
409
410 void ReallocateMemory(CONST VOIDPTR ptr1, unsigned int size1,
411 CONST VOIDPTR ptr2, unsigned int size2,
412 CONST char *file, int line)
413 {
414 int pos,c;
415 pos = SearchForMemory(ptr1);
416 if ((pos>=0)&&(g_mem_rec[pos].ptr==ptr1)){
417 assert(g_mem_rec[pos].size==size1);
418 for(c=pos+1;c<g_memory_length;c++)
419 g_mem_rec[c-1] = g_mem_rec[c];
420 g_memory_length--;
421 }
422 pos = SearchForMemory(ptr2);
423 if ((pos<0)||(g_mem_rec[pos].ptr!=ptr2)){
424 if (pos<0) pos=0;
425 if (g_memory_length+1<MAXPOINTERS){
426 if ((pos==g_memory_length-1)&&
427 (g_mem_rec[pos].ptr<ptr2)){
428 pos++;
429 g_memory_length++;
430 g_mem_rec[pos].ptr = ptr2;
431 g_mem_rec[pos].size = size2;
432 }
433 else{
434 /* make room for the new addition */
435 for(c=g_memory_length;c>pos;c--){
436 g_mem_rec[c] = g_mem_rec[c-1];
437 }
438 g_memory_length++;
439 g_mem_rec[pos].ptr = ptr2;
440 g_mem_rec[pos].size = size2;
441 }
442 }
443 else{
444 FPRINTF(stderr,
445 "Pointer list filled up. Error messages may be unreliable.\n");
446 }
447 }
448 WriteReAllocation(ptr1,size1,ptr2,size2,file,line);
449 }
450
451 VOIDPTR asccallocf(unsigned int nelem, unsigned int elsize,
452 CONST char *file, int line)
453 {
454 VOIDPTR result;
455 OpenLogFile();
456 result = calloc(nelem,elsize);
457 /* adjust statistical variables */
458 g_memory_allocated += nelem*elsize;
459 if (g_memory_allocated > g_peak_memory_usage)
460 g_peak_memory_usage = g_memory_allocated;
461 if (AllocatedMemory(result,nelem*elsize)){
462 WriteError("calloc returned a piece of memory that is already being used.",
463 file,line);
464 }
465 AddAllocatedMemory(result,nelem*elsize,file,line);
466 return result;
467 }
468
469 VOIDPTR ascmallocf(unsigned int size, CONST char *file, int line)
470 {
471 VOIDPTR result;
472 OpenLogFile();
473 result = malloc(size);
474 g_memory_allocated += size;
475 if (g_memory_allocated > g_peak_memory_usage)
476 g_peak_memory_usage = g_memory_allocated;
477 if (AllocatedMemory(result,size)){
478 WriteError("malloc returned a piece of memory that is already being used.",
479 file,line);
480 }
481 AddAllocatedMemory(result,size,file,line);
482 return result;
483 }
484
485 unsigned FindMemorySize(CONST VOIDPTR ptr, int * CONST found)
486 {
487 int pos;
488 pos = SearchForMemory(ptr);
489 if (pos>=0){
490 *found = 1;
491 if (g_mem_rec[pos].ptr==ptr) return g_mem_rec[pos].size;
492 }
493 *found = 0;
494 return 0;
495 }
496
497 VOIDPTR ascreallocf(VOIDPTR ptr, unsigned int size, CONST char *file, int line)
498 {
499 unsigned old_size;
500 int found;
501 VOIDPTR result;
502 OpenLogFile();
503 if (AllocatedMemory(ptr,0)){
504 old_size = FindMemorySize(ptr,&found);
505 if (!found){
506 FPRINTF(stderr,"realloc'ing a piece of an allocated block.\n");
507 }
508 result = realloc(ptr,size);
509 ReallocateMemory(ptr,old_size,result,size,file,line);
510 }
511 else{
512 WriteError("ascreallocf called on a deallocated piece of memory.",file,
513 line);
514 old_size = 0;
515 if (ptr==NULL) {
516 result = malloc(size);
517 } else {
518 result = realloc(ptr,size);
519 }
520 ReallocateMemory(ptr,old_size,result,size,file,line);
521 }
522 if (size >= old_size) g_memory_allocated += (size-old_size);
523 else g_memory_allocated -= (old_size-size);
524 if (g_memory_allocated > g_peak_memory_usage)
525 g_peak_memory_usage = g_memory_allocated;
526 return result;
527 }
528
529 void ascfreef(VOIDPTR ptr, CONST char *file, int line)
530 {
531 unsigned size;
532 int found;
533 OpenLogFile();
534 if (AllocatedMemory(ptr,0)){
535 size = FindMemorySize(ptr,&found);
536 if (!found){ /* indicates a problem */
537 WriteError("Deallocating a piece of an allocated block.",file,line);
538 }
539 else
540 memset((char *)ptr,0,(int)size); /* clear the memory */
541 }
542 else{
543 WriteError("ascfreef called on a deallocated piece of memory.",file,line);
544 size = 0;
545 }
546 DeallocateMemory(ptr,size,file,line);
547 g_memory_allocated -= size;
548 free(ptr);
549 }
550
551 void ascbcopyf(CONST VOIDPTR b1, VOIDPTR b2, int size,
552 CONST char *file, int line)
553 {
554 OpenLogFile();
555 memcpy(b2,b1,size);
556 }
557
558 void ascbzerof(VOIDPTR b1, int length, CONST char *file, int line)
559 {
560 OpenLogFile();
561 memset((char *)b1,0,length);
562 }
563
564 int InMemoryBlock(CONST VOIDPTR ptr1, CONST VOIDPTR ptr2)
565 {
566 int pos;
567 pos = SearchForMemory(ptr1);
568 if (g_mem_rec[pos].ptr==ptr1)
569 return (ptr2>=ptr1)&&(ptr2 <= (CONST VOIDPTR)((CONST char *)ptr1+
570 g_mem_rec[pos].size));
571 else
572 return 0;
573 }
574 #else
575 void ascstatus(CONST char *msg)
576 {
577 (void) msg;
578 }
579
580 void ascshutdown(CONST char *msg)
581 {
582 (void) msg;
583 }
584 #endif /* MALLOC_DEBUG */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22