1 /*
2 * Copyright (C) 1988-1992 Yale University
3 *
4 * This work is distributed in the hope that it will be useful; you can
5 * redistribute it and/or modify it under the terms of the
6 * GNU General Public License as published by the Free Software Foundation;
7 * either version 2 of the License,
8 * or any later version, on the following conditions:
9 *
10 * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
11 * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
12 * SALE OR
13 * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
14 * PATENT OR
15 * OTHER RIGHTS NOT VESTED IN YALE.
16 *
17 * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
18 * WARRANTIES
19 * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
20 * INCLUDING,
21 * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
22 * PARTICULAR
23 * PURPOSE.
24 *
25 * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
26 * WHATSOEVER TO
27 * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
28 * ARTICLE
29 * (a) AND (b) above.
30 *
31 * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
32 * EMPLOYEES AND
33 * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
34 * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
35 * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
36 * POSSIBILITY OF THE FOREGOING.
37 *
38 */
39
40 /* -----------------------------------------------------------------
41 FILE: okmalloc.c
42 DESCRIPTION:This file contains memory management routines.
43 User should always call safe_malloc, safe_free, etc.
44 A conditional compile allows the choice between this
45 memory manager and system. Using the memory manager
46 helps make the environment similar on all machines.
47 CONTENTS:
48 ++++++++++++ HEAP MANAGEMENT ROUTINES ++++++++++++++
49 static status_t heapDispose (ptr)
50 char_p ptr;
51 static status_t allocateRegion (min_size)
52 INT min_size;
53 static status_t heapInit (initial_size)
54 INT initial_size;
55 static status_t heapNew (ptr, req_size)
56 char_p *ptr;
57 INT req_size;
58 +++++++++ END HEAP MANAGEMENT ROUTINES ++++++++++++
59 USER CALLS FOR C RUN TIME LIBRARY
60 VOID Ysafe_free(ptr)
61 char *ptr;
62 VOID Ysafe_cfree(ptr)
63 char *ptr;
64 char *Ysafe_malloc(bytes)
65 long bytes;
66 char *Ysafe_calloc(num_entries, bytes)
67 long num_entries;
68 long bytes;
69 char *Ysafe_realloc(ptr, bytes)
70 char *ptr;
71 long bytes;
72 INT YgetCurMemUse()
73 INT YcheckMemObj(ptr)
74 char *ptr ;
75 INT Yinit_memsize(memsize)
76 INT memsize ;
77 INT YgetListSize(ptr, offsetPtr)
78 char *ptr ;
79 char *offsetPtr ;
80 YdebugMemory( flag )
81 BOOL flag ;
82 Ypmemerror( s )
83 char *s ;
84 YcheckDebug( where )
85 INT where ;
86 char *Yvector_alloc( lo, hi, size )
87 INT size, lo, hi ;
88 char *Yvector_calloc( lo, hi, size )
89 INT size, lo, hi ;
90 char *Yvector_realloc( array_orig, lo, hi, size )
91 VOIDPTR array_orig ;
92 INT size, lo, hi ;
93 VOID Yvector_free( array, lo, size )
94 VOIDPTR array ;
95 INT lo, size ;
96 DATE: Feb 2, 1988
97 REVISIONS: Sep 25, 1988 - converted to common utility.
98 Feb 22, 1989 - added new memory check for debugger.
99 made local function calls static - hide from linker.
100 Apr 18, 1989 - added Yinit_memsize for init memory size.
101 May 3, 1989 - added Y prefixes.
102 Sep 16, 1989 - all debug directed to stderr.
103 Dec 21, 1989 - now initialize freed memory to -1 to
104 catch more bugs.
105 Jan 31, 1990 - corrected arg reversal in calloc call.
106 Feb 4, 1990 - fixed bug in initializing freed memory.
107 Also renamed static variables.
108 Tue Oct 23 03:33:19 EDT 1990 - fixed for prototypes in
109 base.h.
110 Tue Jan 15 02:06:35 EST 1991 - added vector allocation
111 routines.
112 Thu Jan 24 20:19:46 PST 1991 - added more vector routines.
113 Thu Jan 31 15:42:52 EST 1991 - added char * cast to
114 voidptr use in vector routines.
115 Fri Feb 15 15:37:16 EST 1991 - added call to message
116 system so that silent mode will work.
117 Sat May 11 22:53:49 EDT 1991 - added a conditional compile
118 for HPUX.
119 Sat Dec 14 14:33:10 EST 1991 - added YgetMaxMemUse()
120 Sun Dec 15 02:30:59 EST 1991 - added the MEM_DEBUG conditional
121 compile. We added extra arguments to the alloc routines
122 so that we could pass the line that the memory was
123 created. We now can dump all the allocated memory by
124 calling Ydump_mem().
125 Tue Jan 7 18:03:31 EST 1992 - fixed memory manager
126 on the MAC.
127 ----------------------------------------------------------------- */
128
129 #include <stdio.h>
130 #include <unistd.h>
131 #include <signal.h>
132 #include <errno.h>
133 #include <yalecad/base.h>
134 #include <yalecad/message.h>
135
136 #ifdef HPUX
137 #undef NBPG
138 #include <machine/parm.h>
139 #endif
140
141
142 /* memory errors */
143 #define heap_error_base 0x40060000
144 #define heap_bad_block (heap_error_base + 1)
145 #define heap_no_mem (heap_error_base + 2)
146 #define heap_ok 0
147
148 #ifdef MEM_DEBUG
149 #include <yalecad/file.h>
150 /* -----------------------------------------------------------------
151 These two unusual definitions MEM_DEBUG1 and MEM_DEBUG2 add
152 arguments to memory user routines so that we can pass the file
153 and line number from the preprocessor.
154 ----------------------------------------------------------------- */
155 #define MEM_DEBUG1 ,file,line
156 #define MEM_DEBUG2 char *file ; int line ;
157 #define ALLOC_NAME_SIZE 40
158 #else
159 #define MEM_DEBUG1
160 #define MEM_DEBUG2
161 #endif /* MEM_DEBUG */
162
163 /* conditional compile for the memory manager */
164 /* if MEMORYMAN is not defined use system malloc calloc etc. */
165
166 #ifdef MEMORYMAN
167
168 #define systype "bsd4.2"
169 /*
170 *--------------------------------------------------------------
171 * C MEMORY MANAGEMENT SYSTEM
172 * Description : These Routines replace malloc/calloc
173 * & free calls. AVOID deficiencies in
174 * APOLLO heap management routines.
175 *
176 * CODED BY : Bill Swartz
177 *--------------------------------------------------------------
178 */
179
180 #define mp_block_cnt 256
181 #define region_mask 0xFFFF8000
182 #define region_overhead 8
183 #define DFL_REGION_SIZE (4095 * 1024)
184 #define expected_size (256 * 1024)
185 #define waste_allowed 28
186 #define FOREVER 1
187
188 #define block_overhead (sizeof(header_t) + sizeof(trailer_t))
189 #define double_word_mask 0xFFFFFFFC
190
191 #define char_p char *
192
193 typedef struct {
194 INT size;
195 } header_t;
196
197 typedef struct {
198 INT all;
199 } status_t;
200
201 typedef struct block_type {
202 header_t head;
203 union {
204 struct {
205 struct block_type *link;
206 struct block_type *back;
207 } zero_case;
208 INT data;
209 } case_of_two;
210 } block_t, *block_p;
211
212 typedef INT region_head_t, *region_head_p;
213
214 typedef struct {
215 INT size;
216 } trailer_t, *trailer_p;
217
218 typedef struct {
219 block_t avail;
220 block_p alloc_rover;
221 region_head_p highest_region;
222 INT cnt_blks;
223 INT max_blks;
224 } zone_t;
225
226 static zone_t zoneS ;
227 static status_t statuS;
228 static BOOL heapNotStartedS = TRUE;
229 static INT totalAllocationS = 0 ;
230 static BOOL debugFlagS = FALSE ;
231 static INT inUseS = 0 ;
232 static INT regionSizeS = DFL_REGION_SIZE ;
233 static INT max_usedS = 0 ;
234
235 #ifdef MEM_DEBUG
236
237 /* keep an linked list of allocated memory */
238 typedef struct mem_obj {
239 char name[ALLOC_NAME_SIZE] ;
240 char *ptr_p ;
241 struct mem_obj *next ;
242 struct mem_obj *prev ;
243 } MEMOBJ, *MEMOBJPTR ;
244
245 static MEMOBJ name_sentinelS ;
246 static MEMOBJPTR name_listS = &name_sentinelS ;
247
248 #endif /* MEM_DEBUG */
249
250
251 /* ++++++++++++++++++ HEAP MANAGEMENT ROUTINES ++++++++++++++ */
252 /* ---------heap_dispose--------- */
heapDispose(ptr)253 static status_t heapDispose (ptr)
254 char_p ptr;
255 {
256 status_t st;
257 trailer_p tail;
258 block_p headPtr;
259 block_p check;
260 block_p lower;
261 block_p higher;
262 block_p temp;
263 long l ;
264 long *i ;
265
266 /* Begin procedure heap dispose. */
267
268 headPtr = (block_p) ((INT) ptr - sizeof(header_t));
269 inUseS += headPtr->head.size ;
270 tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size - sizeof(trailer_t));
271 if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) {
272 st.all = heap_bad_block;
273 return (st);
274 } else if( debugFlagS ) {
275 /* set the old memory to -1 */
276 headPtr = (block_p) ((INT) ptr - sizeof(header_t));
277 /* find number of words; - 2 accounts for header and trailer */
278 l = ABS( headPtr->head.size ) / sizeof(long) - 2 ;
279 for(i=(long *) ptr;l>0;i++, l--){
280 *i=(long)-1;
281 }
282 }
283
284 headPtr->head.size *= -1;
285 tail = (trailer_p) ( ((INT)headPtr) - sizeof(trailer_t));
286 if (tail->size > 0) {
287 check = (block_p) ( ((INT)headPtr) - tail->size);
288 higher = check->case_of_two.zero_case.link;
289 lower = check->case_of_two.zero_case.back;
290 higher->case_of_two.zero_case.back = lower;
291 lower->case_of_two.zero_case.link = higher;
292 check->head.size += headPtr->head.size;
293 headPtr = check;
294 }
295
296 check = (block_p) ( ((INT)headPtr) + headPtr->head.size);
297 if (check->head.size > 0) {
298 if (zoneS.alloc_rover == (block_p) &(check->head.size)) {
299 zoneS.alloc_rover = (block_p) &(headPtr->head.size);
300 }
301 higher = check->case_of_two.zero_case.link;
302 lower = check->case_of_two.zero_case.back;
303 higher->case_of_two.zero_case.back = lower;
304 lower->case_of_two.zero_case.link = higher;
305 headPtr->head.size += check->head.size;
306 }
307 tail = (trailer_p) ( ((INT)headPtr) + headPtr->head.size - sizeof(trailer_t));
308 tail->size = headPtr->head.size;
309 headPtr->case_of_two.zero_case.link = zoneS.avail.case_of_two.zero_case.link;
310 headPtr->case_of_two.zero_case.back = (block_p) &(zoneS.avail);
311 temp = (block_p) &(headPtr->head);
312 zoneS.avail.case_of_two.zero_case.link->case_of_two.zero_case.back = temp ;
313 zoneS.avail.case_of_two.zero_case.link = temp ;
314
315 #ifdef MEM_DEBUG
316 {
317 MEMOBJPTR mem_p ;
318 /* this is brain dead for now */
319 for( mem_p = name_listS->next; mem_p != name_listS; mem_p = mem_p->next ){
320 if( mem_p->ptr_p == ptr ){
321 /* delete this from memory */
322 mem_p->prev->next = mem_p->next ;
323 mem_p->next->prev = mem_p->prev ;
324 heapDispose( mem_p ) ;
325 break ;
326 }
327 }
328 }
329 #endif /* end MEM_DEBUG */
330
331 st.all = heap_ok;
332 return (st);
333 } /* End of procedure heap dispose. */
334
335
336 /* ---------- Utility Routines ---------- */
337
allocateRegion(min_size)338 static status_t allocateRegion (min_size)
339 INT min_size;
340 {
341 typedef INT *tag_p;
342
343 status_t st;
344 block_p head;
345 trailer_p tail;
346 INT allocation;
347 INT pageSize;
348 INT i;
349 INT *memory;
350
351 /* Begin procedure allocate region. */
352 #ifndef SYS5
353 pageSize = getpagesize() ;
354 #else /* SYS5 */
355 pageSize = NBPG ;
356 #endif /* SYS5 */
357 if( min_size < expected_size ){
358 min_size = expected_size ;
359 }
360 allocation = min_size + 2*sizeof(INT);
361 allocation += pageSize - (allocation % pageSize) ;
362 totalAllocationS += allocation ;
363 head = (block_p) sbrk(0) ;
364 sprintf( YmsgG, "Alternate MEMORY MANagement system invoked - allocation:%d bytes\n", allocation ) ;
365 M( MSG, NULL, YmsgG ) ;
366 if( debugFlagS ){
367 fprintf( stderr, "Memory debug switch on\n") ;
368 fprintf( stderr, "old starting memory address:%0x Page size = %d\n",
369 head,pageSize) ;
370 }
371 head = (block_p) sbrk(allocation) ;
372 if( debugFlagS ){
373 fprintf( stderr,
374 "new starting memory address:%0x with allocation:%d bytes\n",
375 head, allocation) ;
376 if( !( heapNotStartedS) ){
377 fprintf( stderr,
378 "current memory request = %d bytes approx. %d pages\n",
379 min_size,min_size/pageSize) ;
380 fprintf( stderr,
381 "total user memory allocated = %d bytes approx. %d pages\n",
382 inUseS,inUseS/pageSize) ;
383 }
384 fprintf( stderr,
385 "new memory space = %d pages of %d bytes\n",
386 totalAllocationS / pageSize, pageSize) ;
387 fprintf( stderr,"total current allocation = %d\n\n",totalAllocationS ) ;
388 }
389 /* head = (block_p) malloc(allocation) */ ;
390 if ( !(head) || head == (block_p) -1) {
391 st.all = heap_no_mem ;
392 return( st ) ;
393 }
394 if( debugFlagS ){
395 /* initialize all bytes of memory to 1 to catch bugs */
396 memory = (INT *) head ;
397 for( i=0;i<allocation/4;i++){
398 memory[i] = -1 ;
399 }
400 }
401
402 inUseS += allocation - 2*sizeof(INT) ;
403 tail = (trailer_p) ((INT) head + allocation - sizeof(INT));
404 if (zoneS.highest_region != NULL) {
405 if (zoneS.highest_region + ABS(*zoneS.highest_region) == (INT *) head) {
406 *zoneS.highest_region = *zoneS.highest_region - allocation;
407 head = (block_p) ((INT) head - sizeof(INT));
408 } else {
409 zoneS.highest_region = (INT *) head;
410 *zoneS.highest_region = -allocation;
411 head = (block_p) ((INT) head + sizeof(INT));
412 allocation = allocation - 2*sizeof(INT);
413 }
414 } else {
415 zoneS.highest_region = (INT *) head;
416 *zoneS.highest_region = -allocation;
417 head = (block_p) ((INT) head + sizeof(INT));
418 allocation = allocation - 2*sizeof(INT);
419 }
420
421 tail->size = *zoneS.highest_region;
422 tail = (trailer_p) ((INT) head + allocation - sizeof(INT));
423 head->head.size = tail->size = -allocation;
424 head = (block_p) ((INT) head + sizeof(INT));
425 st = heapDispose (head);
426 zoneS.alloc_rover = zoneS.avail.case_of_two.zero_case.link;
427 st.all = heap_ok;
428 return (st);
429 } /* End procedure allocate region. */
430
431
432 /* -------- heap_init -------- */
heapInit(initial_size)433 static status_t heapInit (initial_size)
434 INT initial_size;
435 {
436 status_t st;
437 block_p block;
438 INT allocation;
439
440 /* Begin procedure heap init. */
441
442 /* initialize zone record */
443 zoneS.avail.head.size = 0 ;
444 zoneS.avail.case_of_two.zero_case.link = &(zoneS.avail) ;
445 zoneS.avail.case_of_two.zero_case.back = &(zoneS.avail) ;
446 zoneS.alloc_rover = &(zoneS.avail) ;
447 zoneS.highest_region = NULL ;
448 zoneS.cnt_blks = 0 ;
449 zoneS.max_blks = 0 ;
450 #ifdef MEM_DEBUG
451 name_listS->next = name_listS ;
452 name_listS->prev = name_listS ;
453 #endif /* MEM_DEBUG */
454
455 if (initial_size > 0) {
456 st = allocateRegion (initial_size);
457 if (st.all != heap_ok){
458 return (st);
459 } else {
460 heapNotStartedS = FALSE;
461 }
462 }
463 st.all = heap_ok;
464 return (st);
465 } /* End of procedure heap init. */
466
467
468 /* -------- heap_new --------- */
469 static status_t heapNew (ptr, req_size MEM_DEBUG1 )
470 char_p *ptr;
471 INT req_size;
472 MEM_DEBUG2
473 {
474 status_t st;
475 INT excess;
476 INT allocation;
477 INT block_size;
478 block_p new_block;
479 block_p check;
480 trailer_p trailer;
481 region_head_p region;
482
483 /* Begin procedure heap new. */
484 if (req_size <= 0) {
485 *ptr = NULL;
486 st.all = heap_ok;
487 return (st);
488 } else if (heapNotStartedS){
489 heapInit(regionSizeS);
490 }
491 block_size = (req_size + 3 + block_overhead) & double_word_mask;
492 check = zoneS.alloc_rover;
493 do {
494 if (check->head.size < block_size) {
495 check = check->case_of_two.zero_case.link;
496 } else {
497 excess = check->head.size - block_size;
498 zoneS.alloc_rover = check->case_of_two.zero_case.link;
499 if (excess < waste_allowed) {
500 check->case_of_two.zero_case.back->case_of_two.zero_case.link =
501 check->case_of_two.zero_case.link;
502 check->case_of_two.zero_case.link->case_of_two.zero_case.back =
503 check->case_of_two.zero_case.back;
504 block_size = check->head.size;
505 } else {
506 check->head.size = excess;
507 trailer = (trailer_p) ((INT) check + excess - sizeof(trailer_t));
508 trailer->size = excess;
509 check = (block_p) ((INT) check + excess);
510 }
511 check->head.size = -block_size;
512 trailer = (trailer_p) ((INT) check + block_size - sizeof(trailer_t));
513 trailer->size = -block_size;
514 *ptr = (char_p) &(check->case_of_two.data);
515 #ifdef MEM_DEBUG
516 {
517 INT len ;
518 char alloc_name[BUFSIZ] ;
519 MEMOBJPTR name_data ;
520 if( file ){
521 sprintf( alloc_name, "%s:%d", file, line ) ;
522 len = strlen( alloc_name ) ;
523 if( len < ALLOC_NAME_SIZE ){
524 /* allocate space for record info but don't put in tree */
525 statuS = heapNew (&name_data, sizeof(MEMOBJ), NULL, 0 ) ;
526 if (statuS.all!=heap_ok){
527 errno = statuS.all ;
528 kill(getpid(),SIGUSR1);
529 }
530 strcpy( name_data->name, alloc_name ) ;
531 name_data->ptr_p = *ptr ;
532 name_data->next = name_listS->next ;
533 name_listS->next->prev = name_data ;
534 name_listS->next = name_data ;
535 name_data->prev = name_listS ;
536 } else {
537 fprintf( stderr,
538 "Alloc name:%s too long to store\n",alloc_name ) ;
539 }
540 }
541 }
542 #endif /* MEM_DEBUG */
543 inUseS += block_size ;
544 if( inUseS > max_usedS ) max_usedS = inUseS ;
545 st.all = heap_ok;
546 return (st);
547 }
548 if (check == zoneS.alloc_rover) {
549 st = allocateRegion (block_size);
550 if( inUseS > max_usedS ) max_usedS = inUseS ;
551 if (st.all != heap_ok)
552 return (st);
553 check = zoneS.alloc_rover;
554 }
555 } while (FOREVER);
556 } /* End procedure heap new. */
557
Ydump_mem()558 VOID Ydump_mem()
559 {
560 #ifdef MEM_DEBUG
561 FILE *fp ;
562 MEMOBJPTR mem_p ;
563 static INT dump_noL = 0 ;
564 char filename[LRECL] ;
565 INT sum_allocated ;
566 INT size ;
567
568 sum_allocated = 0 ;
569 sprintf( filename, "mem.data.%d", ++dump_noL ) ;
570 fp = TWOPEN( filename, "w", ABORT ) ;
571 fprintf( fp, "Address:amount_allocated file:line_number\n" ) ;
572 for( mem_p = name_listS->next; mem_p != name_listS; mem_p = mem_p->next ){
573 size = YcheckMemObj(mem_p->ptr_p) ;
574 fprintf( fp, "%x:%d %s\n", mem_p->ptr_p, size, mem_p->name ) ;
575 sum_allocated += size ;
576 }
577 fprintf( fp, "-----------------------------------------------------------\n");
578 fprintf( fp, "Total allocation:%d\n", sum_allocated ) ;
579
580 TWCLOSE( fp ) ;
581 #else /* MEM_DEBUG */
582 fprintf( stderr, "Ydump_mem() is not available. Use libycad.mem-d.a\n" ) ;
583 #endif /* MEM_DEBUG */
584 } /* end Ydump_mem() */
585
586
587 /* ++++++++++++++++++ END HEAP MANAGEMENT ROUTINES ++++++++++++++ */
588
589 /* SUBSTITION CALLS FOR C RUN TIME LIBRARY */
590
591 VOID Ysafe_free(ptr MEM_DEBUG1 )
592 VOIDPTR ptr;
593 MEM_DEBUG2
594 {
595 if( !( ptr ) ){
596 fprintf( stderr,
597 "WARNING[safe_free]:pointer = nil. Ignoring safe_free.\n") ;
598 return ;
599 }
600
601 statuS = heapDispose (ptr);
602 if (statuS.all != heap_ok){
603 errno = statuS.all ;
604 kill(getpid(),SIGUSR1);
605 }
606 }
607
608 VOID Ysafe_cfree(ptr MEM_DEBUG1 )
609 VOIDPTR ptr;
610 MEM_DEBUG2
611 {
612 if( !( ptr ) ){
613 fprintf(stderr,
614 "WARNING[safe_cfree]:pointer = nil. Ignoring safe_cfree.\n") ;
615 return ;
616 }
617
618 statuS = heapDispose (ptr);
619 if (statuS.all!=heap_ok){
620 errno = statuS.all ;
621 kill(getpid(),SIGUSR1);
622 }
623 }
624
625
626 char *Ysafe_malloc(bytes MEM_DEBUG1 )
627 INT bytes;
628 MEM_DEBUG2
629 {
630 char *ptr;
631 char *i;
632 if (bytes<5) {
633 bytes = 8;
634 }
635 statuS = heapNew (&ptr, bytes MEM_DEBUG1 );
636 if (statuS.all!=heap_ok){
637 errno = statuS.all ;
638 kill(getpid(),SIGUSR1);
639 }
640 return(ptr);
641 }
642
643 char *Ysafe_calloc(num_entries, bytes MEM_DEBUG1 )
644 INT num_entries;
645 INT bytes;
646 MEM_DEBUG2
647 {
648 char *ptr;
649 long *i;
650 long k,l;
651
652 k = bytes*num_entries;
653 if (k<5) {
654 k = 8;
655 }
656 statuS = heapNew (&ptr, k MEM_DEBUG1 );
657 if (statuS.all!=heap_ok){
658 errno = statuS.all ;
659 kill(getpid(),SIGUSR1);
660 }
661 l = (k+3)>>2;
662 for(i=(long *)ptr;l>0;i++, l--){
663 *i=(long)0;
664 }
665 return(ptr);
666 }
667
668 char *Ysafe_realloc(ptr, bytes MEM_DEBUG1 )
669 VOIDPTR ptr;
670 INT bytes;
671 MEM_DEBUG2
672 {
673
674 char *ptr2;
675 INT oldSize;
676 INT i;
677 block_p headPtr;
678 trailer_p tail;
679
680 /* allocate new memory */
681 ptr2 = Ysafe_malloc(bytes MEM_DEBUG1 );
682
683 /* get current size of ptr */
684 headPtr = (block_p) ((INT) ptr - sizeof(header_t));
685 tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size
686 - sizeof(trailer_t));
687 if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) {
688 errno = heap_bad_block ;
689 kill(getpid(),SIGUSR1);
690 }
691 /* copy only the smaller amount of two blocks */
692 oldSize = - (headPtr->head.size) ;
693 if( oldSize < bytes ){
694 bytes = oldSize ;
695 }
696
697 for (i=0; i<bytes; i++){
698 ptr2[i] = ((char *) ptr)[i];
699 }
700
701
702 Ysafe_free(ptr MEM_DEBUG1 );
703
704 return(ptr2);
705 }
706
Yinit_memsize(memsize)707 VOID Yinit_memsize( memsize )
708 INT memsize ;
709 {
710 regionSizeS = memsize ;
711 } /* end Yinit_memsize */
712
713 /* getCurMemUse - returns the current allocated memory by user */
YgetCurMemUse()714 INT YgetCurMemUse()
715 {
716 return(inUseS) ;
717 }
718
719 /* getMaxMemUse - returns the maximum allocated memory by user */
YgetMaxMemUse()720 INT YgetMaxMemUse()
721 {
722 return(max_usedS) ;
723 }
724
725 /* checkMemObj(ptr) - returns the size of the object pointed to */
726 /* returns size in bytes. returns -1 if invalid object */
YcheckMemObj(ptr)727 INT YcheckMemObj(ptr)
728 char *ptr ;
729 {
730 block_p headPtr;
731 trailer_p tail;
732
733 /* get current size of ptr */
734 headPtr = (block_p) ((INT) ptr - sizeof(header_t));
735 tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size
736 - sizeof(trailer_t));
737 if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) {
738 return(-1) ;
739 }
740 return(-headPtr->head.size - block_overhead) ;
741 } /* end checkMemObj */
742
743 /* checkDebug call checkMemObj so it can be used in debugger */
YcheckDebug(where)744 INT YcheckDebug( where )
745 VOIDPTR where ; /* must be integer to work in dbx */
746 {
747 INT size ;
748
749 if( (size = YcheckMemObj( (char *) where )) == -1 ){
750 fprintf( stderr, "Memory has been damaged\n" ) ;
751 return( 0 ) ;
752 } else {
753 return( size ) ;
754 }
755 } /* end checkDebug */
756
757 /* getListSize(ptr,offset) - returns the size of a linked-list */
758 /* returns size in bytes. returns -1 if invalid object */
759 /* example. getListSize(netPtr,&(netPtr->next) ) ; */
YgetListSize(ptr,offsetPtr)760 INT YgetListSize(ptr, offsetPtr)
761 char *ptr ; /* pointer to beginning of list structure */
762 char *offsetPtr ; /* pointer to "next" field within structure */
763 {
764 block_p headPtr;
765 trailer_p tail;
766 INT recordCount = 0 ;
767 INT memInUse = 0 ;
768 INT offset ;
769 INT limit ; /* max number of records */
770 INT *intPtr ;
771 INT temp ;
772
773 /* first calculate offset of next field */
774 offset = offsetPtr - ptr ;
775
776 /* calculate limit to detect circular link list */
777 /* the max number of records = MaxMemory/sizeof(record)
778 /* need current size of ptr for calculation */
779 headPtr = (block_p) ((INT) ptr - sizeof(header_t));
780 tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size
781 - sizeof(trailer_t));
782 if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) {
783 return(-1) ;
784 }
785 if( headPtr->head.size ){
786 limit = - totalAllocationS / headPtr->head.size ;
787 } else {
788 return(-1) ;
789 }
790
791 while( ptr ) { /* perform check while pointer is not null */
792
793 headPtr = (block_p) ((INT) ptr - sizeof(header_t));
794 tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size
795 - sizeof(trailer_t));
796 if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) {
797 if( debugFlagS ){
798 fprintf( stderr, "ERROR[getListSize]:record has corrupted data\n") ;
799 }
800 return(-1) ;
801 }
802 memInUse += - headPtr->head.size ;
803 /* check for circular linked list */
804 if( recordCount > limit) {
805 fprintf( stderr, "Detected a circular linked list\n") ;
806 return(-1) ;
807 }
808
809 /* update pointer */
810 /* calculate addresss of next field */
811 intPtr = (INT *) (ptr + offset) ;
812 /* next line does indirect addressing - contents of */
813 /* field is put in temp. Note we use char point but */
814 /* we need all four bytes of the next field for new pointer */
815 temp = *intPtr ;
816 ptr = (char *) temp ;
817 recordCount++ ;
818 }
819 return(memInUse) ;
820 }
821
822 /* debugMemory - turns on memory check debug messages and */
823 /* memory to all 1's to detect access violations. */
YdebugMemory(flag)824 VOID YdebugMemory( flag )
825 BOOL flag ;
826 {
827 debugFlagS = flag ;
828 }
829
830 /*
831 *--------------------------------------------------------------
832 * END OF C MEMORY MANAGEMENT SYSTEM
833 *--------------------------------------------------------------
834 */
835
836 #else
837
838 /*
839 *--------------------------------------------------------------
840 * BEGIN NORMAL C MEMORY MANAGEMENT SYSTEM
841 *--------------------------------------------------------------
842 */
843
844 /* use standard calls to malloc, calloc, etc */
845
Ysafe_malloc(size)846 char *Ysafe_malloc(size)
847 INT size;
848 {
849 char *p;
850
851 /*extern char *malloc() ;*/
852
853 if ((p = malloc(size)) == (char *) 0) {
854 errno = heap_no_mem ;
855 kill(getpid(),SIGUSR1);
856 }
857 return p;
858 }
859
860
Ysafe_realloc(obj,size)861 char *Ysafe_realloc(obj, size)
862 VOIDPTR obj;
863 INT size;
864 {
865 char *p;
866
867 /* extern char *realloc() ;*/
868
869 if ((p = realloc(obj, size)) == (char *) 0) {
870 errno = heap_no_mem ;
871 kill(getpid(),SIGUSR1);
872 }
873 return p;
874 }
875
876
Ysafe_calloc(num,size)877 char *Ysafe_calloc(num, size)
878 INT size, num;
879 {
880 char *p;
881
882 /*extern char *calloc() ;*/
883
884 if ((p = calloc(num,size)) == (char *) 0) {
885 errno = heap_no_mem ;
886 kill(getpid(),SIGUSR1);
887 }
888 return p;
889 }
890 /* when not testing memory just call system free */
Ysafe_free(ptr)891 VOID Ysafe_free(ptr)
892 VOIDPTR ptr;
893 {
894 free(ptr);
895 return;
896 }
897
Ysafe_cfree(ptr)898 VOID Ysafe_cfree(ptr)
899 VOIDPTR ptr;
900 {
901 free(ptr);
902 return;
903 }
904
905 /* ***********DUMMY ROUTINES TO RESOLVE GLOBALS **************** */
906 /* see above for normal use */
YgetCurMemUse()907 INT YgetCurMemUse()
908 {
909 return(0) ;
910 }
911
YgetMaxMemUse()912 INT YgetMaxMemUse()
913 {
914 return(0) ;
915 }
916
YcheckMemObj(ptr)917 INT YcheckMemObj(ptr)
918 char *ptr ;
919 {
920 return(0) ;
921 }
922
YgetListSize(ptr,offsetPtr)923 INT YgetListSize(ptr, offsetPtr)
924 char *ptr ; /* pointer to beginning of list structure */
925 char *offsetPtr ; /* pointer to "next" field within structure */
926 {
927 return(0) ;
928 }
929
YdebugMemory(flag)930 VOID YdebugMemory( flag )
931 INT flag ;
932 {
933 return ;
934 }
935
YcheckDebug(where)936 INT YcheckDebug( where )
937 VOIDPTR where ;
938 {
939 return ( INT_MAX ) ;
940 } /* end checkDebug */
941
Yinit_memsize(memsize)942 VOID Yinit_memsize( memsize )
943 INT memsize ;
944 {
945 return ;
946 } /* end Yinit_memsize */
947
Ydump_mem()948 VOID Ydump_mem()
949 {
950 } /* end Ydump_mem() */
951 /*
952 *--------------------------------------------------------------
953 * END NORMAL C MEMORY MANAGEMENT SYSTEM
954 *--------------------------------------------------------------
955 */
956 #endif
957
958 /* print memory error in the same style as perror and psignal */
Ypmemerror(s)959 VOID Ypmemerror( s )
960 char *s ;
961 {
962 /* first print user message if available */
963 if( s ){
964 fprintf( stderr, "%s:", s ) ;
965 }
966 switch(errno){
967 case heap_ok:
968 fprintf(stderr,
969 "Memory ok - Problem in memory management logic.\n" ) ;
970 break;
971 case heap_bad_block:
972 fprintf(stderr,
973 "Memory block was found to be corrupted.\n" ) ;
974 break;
975 case heap_no_mem:
976 fprintf(stderr,
977 "No memory available to allocate.\n" ) ;
978 break;
979 default:
980 fprintf(stderr,
981 "Error = %0x Unrecognized error code.\n",errno ) ;
982 }
983 } /* end Ypmemerror */
984
985 /* ******* memory convenience functions ******* */
986 /* ALLOCATE an array [lo..hi] of the given size not initialized */
987 char *Yvector_alloc( lo, hi, size MEM_DEBUG1 )
988 INT size, lo, hi ;
989 MEM_DEBUG2
990 {
991 char *array_return ;
992
993 array_return = (char *) Ysafe_malloc((unsigned) (hi-lo+1)*size MEM_DEBUG1 ) ;
994 if( array_return ){
995 return( array_return - size * lo ) ;
996 }
997 return( NIL(char *) ) ;
998
999 } /* end Yvector_alloc */
1000
1001 /* ALLOCATE an array [lo..hi] of the given size initialized to zero */
1002 char *Yvector_calloc( lo, hi, size MEM_DEBUG1 )
1003 INT size, lo, hi ;
1004 MEM_DEBUG2
1005 {
1006 char *array_return ;
1007
1008 array_return = (char *) Ysafe_calloc((unsigned) (hi-lo+1),size MEM_DEBUG1 ) ;
1009 if( array_return ){
1010 return( array_return - size * lo ) ;
1011 }
1012 return( NIL(char *) ) ;
1013
1014 } /* end Yvector_calloc */
1015
1016 /* REALLOCATE an array [lo..hi] of the given size no initialization */
1017 char *Yvector_realloc( array_orig, lo, hi, size MEM_DEBUG1 )
1018 VOIDPTR array_orig ;
1019 INT size, lo, hi ;
1020 MEM_DEBUG2
1021 {
1022 char *adj_array ; /* put back the offset */
1023 char *array_return ; /* the new offset */
1024
1025 adj_array = ((char *) array_orig) + lo * size ;
1026 array_return = (char *)
1027 Ysafe_realloc( adj_array, (unsigned) (hi-lo+1)*size MEM_DEBUG1 ) ;
1028 if( array_return ){
1029 return( array_return - size * lo ) ;
1030 }
1031 return( NIL(char *) ) ;
1032
1033 } /* end Yvector_realloc */
1034
1035 VOID Yvector_free( array, lo, size MEM_DEBUG1 )
1036 VOIDPTR array ;
1037 INT lo, size ;
1038 MEM_DEBUG2
1039 {
1040 Ysafe_free( ((char *)array) + lo * size MEM_DEBUG1 ) ;
1041 } /* end Yvector_free */
1042
1043 /* ************************* TEST ROUTINES ******************************** */
1044 #ifdef TEST
1045
1046 typedef struct {
1047 INT bogus_dude ;
1048 DOUBLE narly ;
1049 char *awesome ;
1050 } MEMDATA, *MEMDATAPTR ;
1051
main()1052 main()
1053 {
1054 MEMDATAPTR array ;
1055 MEMDATAPTR vector ;
1056 char *string, *Ystrclone() ;
1057
1058 YdebugMemory( TRUE ) ;
1059 Yinit_memsize( 1024 ) ;
1060
1061 /* allocate an array 0..9 */
1062 array = YMALLOC( 10, MEMDATA ) ;
1063 fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ;
1064 /* allocate an array 1..10 */
1065 vector = YVECTOR_MALLOC( 1, 10, MEMDATA ) ;
1066 fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ;
1067 /* clone this string */
1068 string = Ystrclone( "Droog" ) ;
1069 fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ;
1070 /* look at mem.data at this point */
1071 Ydump_mem() ;
1072 /* free all the memory */
1073 YFREE( array ) ;
1074 YFREE( string ) ;
1075 YVECTOR_FREE( vector, 1 ) ;
1076 fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ;
1077 fprintf( stderr, "Memory max size :%d\n", YgetMaxMemUse() ) ;
1078 Ydump_mem() ;
1079
1080 exit(0) ;
1081
1082 }/* end main() */
1083
1084 #endif /* TEST */
1085
1086