|
|
1 # include "dgd.h"
2
3 # ifndef STRUCT_AL
4 # define STRUCT_AL 2 /* default memory alignment */
5 # endif
6
7 # define MAGIC_MASK 0xc0000000L /* magic number mask */
8 # define SIZE_MASK 0x3fffffffL /* size mask */
9
10 # define SM_MAGIC 0x80000000L /* static mem */
11 # define DM_MAGIC 0xc0000000L /* dynamic mem */
12
13 # define UINTSIZE ALGN(sizeof(Uint), STRUCT_AL)
14 # define SIZETSIZE ALGN(sizeof(size_t), STRUCT_AL)
15
16 # ifdef DEBUG
17 # define MOFFSET ALGN(sizeof(header), STRUCT_AL)
18 # else
19 # define MOFFSET UINTSIZE
20 # endif
21
22 typedef struct _chunk_ {
23 Uint size; /* size of chunk */
24 struct _chunk_ *next; /* next chunk */
25 } chunk;
26
27 # ifdef DEBUG
28 typedef struct _header_ {
29 Uint size; /* size of chunk */
30 struct _header_ *prev; /* previous in list */
31 struct _header_ *next; /* next in list */
32 int line; /* line it was allocated from */
33 char *file; /* file it was allocated from */
34 } header;
35 # endif
36
37
38 static allocinfo mstat; /* memory statistics */
39
40 /*
41 * NAME: newmem()
42 * DESCRIPTION: allocate new memory
43 */
44 static char *newmem(size, list)
45 size_t size;
46 char **list;
47 {
48 char *mem;
49
50 if (list != (char **) NULL) {
51 size += ALGN(sizeof(char *), STRUCT_AL);
52 }
53 mem = (char *) malloc(size);
54 if (mem == (char *) NULL) {
55 fatal("out of memory");
56 }
57 if (list != (char **) NULL) {
58 *((char **) mem) = *list;
59 *list = mem;
60 mem += ALGN(sizeof(char *), STRUCT_AL);
61 }
62 return mem;
63 }
64
65 /*
66 * static memory manager
67 */
68
69 # define INIT_MEM 15360 /* initial static memory chunk */
70 # define SLIMIT (STRINGSZ + MOFFSET)
71 # define SSMALL (MOFFSET + STRINGSZ / 8)
72 # define SCHUNKS (STRINGSZ / STRUCT_AL - 1)
73 # define LCHUNKS 32
74
75 typedef struct {
76 size_t size; /* size of chunks in list */
77 chunk *list; /* list of chunks (possibly empty) */
78 } clist;
79
80 static char *slist; /* list of static chunks */
81 static chunk *schunk; /* current chunk */
82 static size_t schunksz; /* size of current chunk */
83 static chunk *schunks[SCHUNKS]; /* lists of small free chunks */
84 static clist lchunks[LCHUNKS]; /* lists of large free chunks */
85 static unsigned int nlc; /* # elements in large chunk list */
86 static chunk *sflist; /* list of small unused chunks */
87 static int slevel; /* static level */
88
89 /*
90 * NAME: lchunk()
91 * DESCRIPTION: get the address of a list of large chunks
92 */
93 static chunk **lchunk(size, new)
94 register size_t size;
95 bool new;
96 {
97 register unsigned int h, l, m;
98
99 l = m = 0;
100 h = nlc;
101 while (l < h) {
102 m = (l + h) >> 1;
103 if (lchunks[m].size == size) {
104 return &lchunks[m].list; /* found */
105 } else if (lchunks[m].size > size) {
106 h = m; /* search in lower half */
107 } else {
108 l = ++m; /* search in upper half */
109 }
110 }
111
112 if (!new) {
113 return (chunk **) NULL; /* not found */
114 }
115 /* make a new list */
116 if (nlc == LCHUNKS) {
117 fatal("too many different large static chunks");
118 }
119 for (l = nlc++; l > m; --l) {
120 lchunks[l] = lchunks[l - 1];
121 }
122 lchunks[m].size = size;
123 lchunks[m].list = (chunk *) NULL;
124 return &lchunks[m].list;
125 }
126
127 /*
128 * NAME: salloc()
129 * DESCRIPTION: allocate static memory
130 */
131 static chunk *salloc(size)
132 register size_t size;
133 {
134 register chunk *c;
135
136 /* try lists of free chunks */
137 if (size >= SLIMIT) {
138 register chunk **lc;
139
140 lc = lchunk(size, FALSE);
141 if (lc != (chunk **) NULL && *lc != (chunk *) NULL) {
142 /* large chunk */
143 c = *lc;
144 *lc = c->next;
145 return c;
146 }
147 } else if ((c=schunks[(size - MOFFSET) / STRUCT_AL - 1]) != (chunk *) NULL)
148 {
149 /* small chunk */
150 schunks[(size - MOFFSET) / STRUCT_AL - 1] = c->next;
151 return c;
152 }
153
154 /* try unused chunk list */
155 if (sflist != (chunk *) NULL && sflist->size >= size) {
156 if (sflist->size - size <= MOFFSET) {
157 /* remainder is too small to put in free list */
158 c = sflist;
159 sflist = c->next;
160 } else {
161 register chunk *n;
162
163 /* split the chunk in two */
164 c = sflist;
165 n = (chunk *) ((char *) sflist + size);
166 n->size = c->size - size;
167 if (n->size <= SSMALL) {
168 /* small chunk */
169 n->next = schunks[(n->size - MOFFSET) / STRUCT_AL - 1];
170 schunks[(n->size - MOFFSET) / STRUCT_AL - 1] = n;
171 sflist = c->next;
172 } else {
173 /* large enough chunk */
174 n->next = c->next;
175 sflist = n;
176 }
177 c->size = size;
178 }
179 return c;
180 }
181
182 /* try current chunk */
183 if (schunk == (chunk *) NULL ||
184 (schunk->size < size && (schunksz != 0 || size <= INIT_MEM))) {
185 /*
186 * allocate default static memory block
187 */
188 if (schunk != (chunk *) NULL) {
189 schunk->next = sflist;
190 sflist = schunk;
191 }
192 schunk = (chunk *) newmem(INIT_MEM, &slist);
193 mstat.smemsize += schunk->size = INIT_MEM;
194 if (schunksz != 0) {
195 /* fragmentation matters */
196 P_message("*** Ran out of static memory (increase static_chunk)\012"); /* LF */
197 }
198 }
199 if (schunk->size >= size) {
200 if (schunk->size - size <= MOFFSET) {
201 /* remainder is too small */
202 c = schunk;
203 schunk = (chunk *) NULL;
204 } else {
205 c = schunk;
206 schunk = (chunk *) ((char *) schunk + size);
207 if ((schunk->size=c->size - size) <= SSMALL) {
208 /* small chunk */
209 schunk->next = schunks[(schunk->size - MOFFSET) / STRUCT_AL -1];
210 schunks[(schunk->size - MOFFSET) / STRUCT_AL - 1] = schunk;
211 schunk = (chunk *) NULL;
212 }
213 c->size = size;
214 }
215 return c;
216 }
217
218 /* allocate static memory directly */
219 c = (chunk *) newmem(size, &slist);
220 mstat.smemsize += c->size = size;
221 return c;
222 }
223
224 /*
225 * NAME: sfree()
226 * DESCRIPTION: free static memory
227 */
228 static void sfree(c)
229 register chunk *c;
230 {
231 if (c->size < SLIMIT) {
232 /* small chunk */
233 c->next = schunks[(c->size - MOFFSET) / STRUCT_AL - 1];
234 schunks[(c->size - MOFFSET) / STRUCT_AL - 1] = c;
235 } else {
236 register chunk **lc;
237
238 /* large chunk */
239 lc = lchunk(c->size, TRUE);
240 c->next = *lc;
241 *lc = c;
242 }
243 }
244
245 /*
246 * NAME: mstatic()
247 * DESCRIPTION: enter static mode
248 */
249 void m_static()
250 {
251 slevel++;
252 }
253
254 /*
255 * NAME: mdynamic()
256 * DESCRIPTION: reenter dynamic mode
257 */
258 void m_dynamic()
259 {
260 --slevel;
261 }
262
263
264 /*
265 * dynamic memory manager
266 */
267
268 typedef struct _spnode_ {
269 Uint size; /* size of chunk */
270 struct _spnode_ *parent; /* parent node */
271 struct _spnode_ *left; /* left child node */
272 struct _spnode_ *right; /* right child node */
273 } spnode;
274
275 static size_t dchunksz; /* dynamic chunk size */
276 static spnode *dtree; /* splay tree of large dynamic free chunks */
277
278 /*
279 * NAME: insert()
280 * DESCRIPTION: insert a chunk in the splay tree
281 */
282 static void insert(c)
283 chunk *c;
284 {
285 register spnode *n, *t;
286 register spnode *l, *r;
287 register Uint size;
288
289 n = dtree;
290 dtree = t = (spnode *) c;
291 t->parent = (spnode *) NULL;
292
293 if (n == (spnode *) NULL) {
294 /* first in splay tree */
295 t->left = (spnode *) NULL;
296 t->right = (spnode *) NULL;
297 } else {
298 size = t->size;
299 l = r = t;
300
301 for (;;) {
302 if (n->size < size) {
303 if ((t=n->right) == (spnode *) NULL) {
304 l->right = n; n->parent = l;
305 r->left = (spnode *) NULL;
306 break; /* finished */
307 }
308 if (t->size >= size) {
309 l->right = n; n->parent = l;
310 l = n;
311 n = t;
312 } else {
313 /* rotate */
314 if ((n->right=t->left) != (spnode *) NULL) {
315 t->left->parent = n;
316 }
317 t->left = n; n->parent = t;
318 l->right = t; t->parent = l;
319 if ((n=t->right) == (spnode *) NULL) {
320 r->left = (spnode *) NULL;
321 break; /* finished */
322 }
323 l = t;
324 }
325 } else {
326 if ((t=n->left) == (spnode *) NULL) {
327 r->left = n; n->parent = r;
328 l->right = (spnode *) NULL;
329 break; /* finished */
330 }
331 if (t->size < size) {
332 r->left = n; n->parent = r;
333 r = n;
334 n = t;
335 } else {
336 /* rotate */
337 if ((n->left=t->right) != (spnode *) NULL) {
338 t->right->parent = n;
339 }
340 t->right = n; n->parent = t;
341 r->left = t; t->parent = r;
342 if ((n=t->left) == (spnode *) NULL) {
343 l->right = (spnode *) NULL;
344 break; /* finished */
345 }
346 r = t;
347 }
348 }
349 }
350
351 /* exchange left and right subtree */
352 n = dtree;
353 t = n->left;
354 n->left = n->right;
355 n->right = t;
356 }
357 }
358
359 /*
360 * NAME: seek()
361 * DESCRIPTION: find a chunk of the proper size in the splay tree
362 */
363 static chunk *seek(size)
364 register Uint size;
365 {
366 spnode dummy;
367 register spnode *n, *t;
368 register spnode *l, *r;
369
370 if ((n=dtree) == (spnode *) NULL) {
371 /* empty splay tree */
372 return (chunk *) NULL;
373 } else {
374 l = r = &dummy;
375
376 for (;;) {
377 if (n->size < size) {
378 if ((t=n->right) == (spnode *) NULL) {
379 l->right = n; n->parent = l;
380 if (r == &dummy) {
381 /* all chunks are too small */
382 dtree = dummy.right;
383 dtree->parent = (spnode *) NULL;
384 return (chunk *) NULL;
385 }
386 if ((r->parent->left=r->right) != (spnode *) NULL) {
387 r->right->parent = r->parent;
388 }
389 n = r;
390 break; /* finished */
391 }
392 if (t->size >= size) {
393 l->right = n; n->parent = l;
394 l = n;
395 n = t;
396 } else {
397 /* rotate */
398 if ((n->right=t->left) != (spnode *) NULL) {
399 t->left->parent = n;
400 }
401 t->left = n; n->parent = t;
402 l->right = t; t->parent = l;
403 if ((n=t->right) == (spnode *) NULL) {
404 if (r == &dummy) {
405 /* all chunks are too small */
406 dtree = dummy.right;
407 dtree->parent = (spnode *) NULL;
408 return (chunk *) NULL;
409 }
410 if ((r->parent->left=r->right) != (spnode *) NULL) {
411 r->right->parent = r->parent;
412 }
413 n = r;
414 break; /* finished */
415 }
416 l = t;
417 }
418 } else {
419 if ((t=n->left) == (spnode *) NULL) {
420 if ((r->left=n->right) != (spnode *) NULL) {
421 n->right->parent = r;
422 }
423 l->right = (spnode *) NULL;
424 break; /* finished */
425 }
426 if (t->size < size) {
427 r->left = n; n->parent = r;
428 r = n;
429 n = t;
430 } else {
431 /* rotate */
432 if ((n->left=t->right) != (spnode *) NULL) {
433 t->right->parent = n;
434 }
435 if (t->left == (spnode *) NULL) {
436 r->left = n; n->parent = r;
437 l->right = (spnode *) NULL;
438 n = t;
439 break; /* finished */
440 }
441 t->right = n; n->parent = t;
442 r->left = t; t->parent = r;
443 r = t;
444 n = t->left;
445 }
446 }
447 }
448
449 n->parent = (spnode *) NULL;
450 if ((n->right=dummy.left) != (spnode *) NULL) {
451 dummy.left->parent = n;
452 }
453 if ((n->left=dummy.right) != (spnode *) NULL) {
454 dummy.right->parent = n;
455 }
456
457 return (chunk *) (dtree = n);
458 }
459 }
460
461 /*
462 * NAME: delete()
463 * DESCRIPTION: delete a chunk from the splay tree
464 */
465 static void delete(c)
466 chunk *c;
467 {
468 register spnode *t, *r;
469 register spnode *p, *n;
470
471 n = (spnode *) c;
472 p = n->parent;
473
474 if (n->left == (spnode *) NULL) {
475 /* there is no left subtree */
476 if (p == (spnode *) NULL) {
477 if ((dtree=n->right) != (spnode *) NULL) {
478 dtree->parent = (spnode *) NULL;
479 }
480 } else if (n == p->left) {
481 if ((p->left=n->right) != (spnode *) NULL) {
482 p->left->parent = p;
483 }
484 } else if ((p->right=n->right) != (spnode *) NULL) {
485 p->right->parent = p;
486 }
487 } else {
488 t = n->left;
489
490 /* walk to the right in the left subtree */
491 while ((r=t->right) != (spnode *) NULL) {
492 if ((t->right=r->left) != (spnode *) NULL) {
493 r->left->parent = t;
494 }
495 r->left = t; t->parent = r;
496 t = r;
497 }
498
499 if (p == (spnode *) NULL) {
500 dtree = t;
501 } else if (n == p->left) {
502 p->left = t;
503 } else {
504 p->right = t;
505 }
506 t->parent = p;
507 if ((t->right=n->right) != (spnode *) NULL) {
508 t->right->parent = t;
509 }
510 }
511 }
512
513 # define DSMALL 64
514 # define DLIMIT (DSMALL + MOFFSET)
515 # define DCHUNKS (DSMALL / STRUCT_AL - 1)
516 # define DCHUNKSZ 32768
517
518 static char *dlist; /* list of dynamic memory chunks */
519 static chunk *dchunks[DCHUNKS]; /* list of free small chunks */
520 static chunk *dchunk; /* chunk of small chunks */
521
522 /*
523 * NAME: dalloc()
524 * DESCRIPTION: allocate dynamic memory
525 */
526 static chunk *dalloc(size)
527 register size_t size;
528 {
529 register chunk *c;
530 register char *p;
531 register size_t sz;
532
533 if (dchunksz == 0) {
534 /*
535 * memory manager hasn't been initialized yet
536 */
537 c = (chunk *) newmem(size, (char **) NULL);
538 c->size = size;
539 return c;
540 }
541
542 if (size < DLIMIT) {
543 /*
544 * small chunk
545 */
546 if ((c=dchunks[(size - MOFFSET) / STRUCT_AL - 1]) != (chunk *) NULL) {
547 /* small chunk from free list */
548 dchunks[(size - MOFFSET) / STRUCT_AL - 1] = c->next;
549 return c;
550 }
551 if (dchunk == (chunk *) NULL) {
552 /* get new chunks chunk */
553 dchunk = dalloc(DCHUNKSZ); /* cannot use alloc() here */
554 p = (char *) dchunk + UINTSIZE;
555 ((chunk *) p)->size = dchunk->size - UINTSIZE - SIZETSIZE;
556 dchunk->size |= DM_MAGIC;
557 dchunk = (chunk *) p;
558 }
559 sz = dchunk->size - size;
560 c = dchunk;
561 c->size = size;
562 if (sz >= DLIMIT - STRUCT_AL) {
563 /* enough is left for another small chunk */
564 dchunk = (chunk *) ((char *) c + size);
565 dchunk->size = sz;
566 } else {
567 /* waste sz bytes of memory */
568 dchunk = (chunk *) NULL;
569 }
570 return c;
571 }
572
573 size += SIZETSIZE;
574 c = seek((Uint) size);
575 if (c != (chunk *) NULL) {
576 /*
577 * remove from free list
578 */
579 delete(c);
580 } else {
581 /*
582 * get new dynamic chunk
583 */
584 for (sz = dchunksz; sz < size + SIZETSIZE + UINTSIZE; sz += dchunksz) ;
585 p = newmem(sz, &dlist);
586 mstat.dmemsize += sz;
587
588 /* no previous chunk */
589 *(size_t *) p = 0;
590 c = (chunk *) (p + SIZETSIZE);
591 /* initialize chunk */
592 c->size = sz - SIZETSIZE - UINTSIZE;
593 p += c->size;
594 *(size_t *) p = c->size;
595 /* no following chunk */
596 p += SIZETSIZE;
597 ((chunk *) p)->size = 0;
598 }
599
600 if ((sz=c->size - size) >= DLIMIT + SIZETSIZE) {
601 /*
602 * split block, put second part in free list
603 */
604 c->size = size;
605 p = (char *) c + size - SIZETSIZE;
606 *(size_t *) p = size;
607 p += SIZETSIZE;
608 ((chunk *) p)->size = sz;
609 *((size_t *) (p + sz - SIZETSIZE)) = sz;
610 insert((chunk *) p); /* add to free list */
611 }
612 return c;
613 }
614
615 /*
616 * NAME: dfree()
617 * DESCRIPTION: free dynamic memory
618 */
619 static void dfree(c)
620 register chunk *c;
621 {
622 register char *p;
623
624 if (dchunksz == 0) {
625 /*
626 * memory manager not yet initialized
627 */
628 free((char *) c);
629 return;
630 }
631
632 if (c->size < DLIMIT) {
633 /* small chunk */
634 c->next = dchunks[(c->size - MOFFSET) / STRUCT_AL - 1];
635 dchunks[(c->size - MOFFSET) / STRUCT_AL - 1] = c;
636 return;
637 }
638
639 p = (char *) c - SIZETSIZE;
640 if (*(size_t *) p != 0) {
641 p -= *(size_t *) p - SIZETSIZE;
642 if ((((chunk *) p)->size & MAGIC_MASK) == 0) {
643 /*
644 * merge with previous block
645 */
646 delete((chunk *) p);
647 ((chunk *) p)->size += c->size;
648 c = (chunk *) p;
649 *((size_t *) (p + c->size - SIZETSIZE)) = c->size;
650 }
651 }
652 p = (char*) c + c->size;
653 if (((chunk *) p)->size != 0 && (((chunk *) p)->size & MAGIC_MASK) == 0) {
654 /*
655 * merge with next block
656 */
657 delete((chunk *) p);
658 c->size += ((chunk *) p)->size;
659 *((size_t *) ((char *) c + c->size - SIZETSIZE)) = c->size;
660 }
661
662 insert(c); /* add to free list */
663 }
664
665
666 /*
667 * NAME: mem->init()
668 * DESCRIPTION: initialize memory manager
669 */
670 void m_init(ssz, dsz)
671 size_t ssz, dsz;
672 {
673 schunksz = ALGN(ssz, STRUCT_AL);
674 dchunksz = ALGN(dsz, STRUCT_AL);
675 if (schunksz != 0) {
676 if (schunk != (chunk *) NULL) {
677 schunk->next = sflist;
678 sflist = schunk;
679 }
680 schunk = (chunk *) newmem(schunksz, &slist);
681 mstat.smemsize += schunk->size = schunksz;
682 }
683 }
684
685
686 # ifdef DEBUG
687 static header *hlist; /* list of all dynamic memory chunks */
688 # endif
689
690 /*
691 * NAME: mem->alloc()
692 * DESCRIPTION: allocate memory
693 */
694 # ifdef DEBUG
695 char *m_alloc(size, file, line)
696 register size_t size;
697 char *file;
698 int line;
699 # else
700 char *m_alloc(size)
701 register size_t size;
702 # endif
703 {
704 register chunk *c;
705
706 # ifdef DEBUG
707 if (size == 0) {
708 fatal("m_alloc(0)");
709 }
710 # endif
711 size = ALGN(size + MOFFSET, STRUCT_AL);
712 # ifndef DEBUG
713 if (size < ALGN(sizeof(chunk), STRUCT_AL)) {
714 size = ALGN(sizeof(chunk), STRUCT_AL);
715 }
716 # endif
717 if (slevel > 0) {
718 c = salloc(size);
719 mstat.smemused += c->size;
720 c->size |= SM_MAGIC;
721 } else {
722 c = dalloc(size);
723 mstat.dmemused += c->size;
724 c->size |= DM_MAGIC;
725 # ifdef DEBUG
726 ((header *) c)->prev = (header *) NULL;
727 ((header *) c)->next = hlist;
728 if (hlist != (header *) NULL) {
729 hlist->prev = (header *) c;
730 }
731 hlist = (header *) c;
732 # endif
733 }
734 # ifdef DEBUG
735 ((header *) c)->file = file;
736 ((header *) c)->line = line;
737 # endif
738 return (char *) c + MOFFSET;
739 }
740
741 /*
742 * NAME: mem->free()
743 * DESCRIPTION: free memory
744 */
745 void m_free(mem)
746 char *mem;
747 {
748 register chunk *c;
749
750 c = (chunk *) (mem - MOFFSET);
751 if ((c->size & MAGIC_MASK) == SM_MAGIC) {
752 c->size &= SIZE_MASK;
753 mstat.smemused -= c->size;
754 sfree(c);
755 } else if ((c->size & MAGIC_MASK) == DM_MAGIC) {
756 c->size &= SIZE_MASK;
757 mstat.dmemused -= c->size;
758 # ifdef DEBUG
759 if (((header *) c)->next != (header *) NULL) {
760 ((header *) c)->next->prev = ((header *) c)->prev;
761 }
762 if (((header *) c) == hlist) {
763 hlist = ((header *) c)->next;
764 } else {
765 ((header *) c)->prev->next = ((header *) c)->next;
766 }
767 # endif
768 dfree(c);
769 } else {
770 fatal("bad pointer in m_free");
771 }
772 }
773
774 /*
775 * NAME: mem->realloc()
776 * DESCRIPTION: reallocate memory
777 */
778 # ifdef DEBUG
779 char *m_realloc(mem, size1, size2, file, line)
780 char *mem, *file;
781 register size_t size1, size2;
782 int line;
783 # else
784 char *m_realloc(mem, size1, size2)
785 char *mem;
786 register size_t size1, size2;
787 # endif
788 {
789 register chunk *c1, *c2;
790
791 if (mem == (char *) NULL) {
792 if (size2 == 0) {
793 return (char *) NULL;
794 }
795 # ifdef DEBUG
796 return m_alloc(size2, file, line);
797 # else
798 return m_alloc(size2);
799 # endif
800 }
801 if (size2 == 0) {
802 m_free(mem);
803 return (char *) NULL;
804 }
805
806 size2 = ALGN(size2 + MOFFSET, STRUCT_AL);
807 # ifndef DEBUG
808 if (size2 < ALGN(sizeof(chunk), STRUCT_AL)) {
809 size2 = ALGN(sizeof(chunk), STRUCT_AL);
810 }
811 # endif
812 c1 = (chunk *) (mem - MOFFSET);
813 if ((c1->size & MAGIC_MASK) == SM_MAGIC) {
814 # ifdef DEBUG
815 if (size1 > (c1->size & SIZE_MASK)) {
816 fatal("bad size1 in m_realloc");
817 }
818 # endif
819 if ((c1->size & SIZE_MASK) < size2) {
820 c2 = salloc(size2);
821 if (size1 != 0) {
822 memcpy((char *) c2 + MOFFSET, mem, size1);
823 }
824 c1->size &= SIZE_MASK;
825 mstat.smemused += c2->size - c1->size;
826 c2->size |= SM_MAGIC;
827 sfree(c1);
828 c1 = c2;
829 }
830 } else if ((c1->size & MAGIC_MASK) == DM_MAGIC) {
831 # ifdef DEBUG
832 if (size1 > (c1->size & SIZE_MASK)) {
833 fatal("bad size1 in m_realloc");
834 }
835 # endif
836 if ((c1->size & SIZE_MASK) < ((size2 < DLIMIT) ?
837 size2 : size2 + SIZETSIZE)) {
838 c2 = dalloc(size2);
839 if (size1 != 0) {
840 memcpy((char *) c2 + MOFFSET, mem, size1);
841 }
842 c1->size &= SIZE_MASK;
843 mstat.dmemused += c2->size - c1->size;
844 c2->size |= DM_MAGIC;
845 # ifdef DEBUG
846 ((header *) c2)->next = ((header *) c1)->next;
847 if (((header *) c1)->next != (header *) NULL) {
848 ((header *) c2)->next->prev = (header *) c2;
849 }
850 ((header *) c2)->prev = ((header *) c1)->prev;
851 if (((header *) c1) == hlist) {
852 hlist = (header *) c2;
853 } else {
854 ((header *) c2)->prev->next = (header *) c2;
855 }
856 # endif
857 dfree(c1);
858 c1 = c2;
859 }
860 } else {
861 fatal("bad pointer in m_realloc");
862 }
863 # ifdef DEBUG
864 ((header *) c1)->file = file;
865 ((header *) c1)->line = line;
866 # endif
867 return (char *) c1 + MOFFSET;
868 }
869
870 /*
871 * NAME: mem->check()
872 * DESCRIPTION: return TRUE if there is enough static memory left, or FALSE
873 * otherwise
874 */
875 bool m_check()
876 {
877 if (schunk == (chunk *) NULL) {
878 return FALSE;
879 } else {
880 return (schunksz == 0 || schunk->size >= schunksz);
881 }
882 }
883
884 /*
885 * NAME: mem->purge()
886 * DESCRIPTION: purge dynamic memory
887 */
888 void m_purge()
889 {
890 register char *p;
891
892 # ifdef DEBUG
893 while (hlist != (header *) NULL) {
894 char buf[160];
895 register size_t n;
896
897 n = (hlist->size & SIZE_MASK) - MOFFSET;
898 if (n >= DLIMIT) {
899 n -= SIZETSIZE;
900 }
901 sprintf(buf, "FREE(%08lx/%u), %s line %u:\012", /* LF */
902 (unsigned long) (hlist + 1), n, hlist->file, hlist->line);
903 if (n > 26) {
904 n = 26;
905 }
906 for (p = (char *) (hlist + 1); n > 0; --n, p++) {
907 if (*p >= ' ') {
908 sprintf(buf + strlen(buf), " '%c", *p);
909 } else {
910 sprintf(buf + strlen(buf), " %02x", UCHAR(*p));
911 }
912 }
913 strcat(buf, "\012"); /* LF */
914 P_message(buf);
915 m_free((char *) (hlist + 1));
916 }
917 # endif
918
919 /* purge dynamic memory */
920 while (dlist != (char *) NULL) {
921 p = dlist;
922 dlist = *(char **) p;
923 free(p);
924 }
925 memset(dchunks, '\0', sizeof(dchunks));
926 dchunk = (chunk *) NULL;
927 dtree = (spnode *) NULL;
928 mstat.dmemsize = mstat.dmemused = 0;
929
930 if (schunksz != 0 &&
931 (schunk == (chunk *) NULL || schunk->size < schunksz ||
932 (mstat.smemsize - mstat.smemused) * 2 < schunksz * 3)) {
933 /* expand static memory */
934 if (schunk != (chunk *) NULL) {
935 schunk->next = sflist;
936 sflist = schunk;
937 }
938 schunk = (chunk *) newmem(schunksz, &slist);
939 mstat.smemsize += schunk->size = schunksz;
940 }
941 }
942
943 /*
944 * NAME: mem->info()
945 * DESCRIPTION: return informaton about memory usage
946 */
947 allocinfo *m_info()
948 {
949 return &mstat;
950 }
951
952
953 /*
954 * NAME: mem->finish()
955 * DESCRIPTION: finish up memory manager
956 */
957 void m_finish()
958 {
959 register char *p;
960
961 schunksz = 0;
962 dchunksz = 0;
963
964 /* purge dynamic memory */
965 # ifdef DEBUG
966 hlist = (header *) NULL;
967 # endif
968 m_purge();
969
970 /* purge static memory */
971 while (slist != (char *) NULL) {
972 p = slist;
973 slist = *(char **) p;
974 free(p);
975 }
976 memset(schunks, '\0', sizeof(schunks));
977 memset(lchunks, '\0', sizeof(lchunks));
978 nlc = 0;
979 schunk = (chunk *) NULL;
980 sflist = (chunk *) NULL;
981 slevel = 0;
982 mstat.smemsize = mstat.smemused = 0;
983 }
984
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.