]> git.sur5r.net Git - cc65/blob - libsrc/common/_hadd.c
This commit was generated by cvs2svn to compensate for changes in r2,
[cc65] / libsrc / common / _hadd.c
1 /*
2  * _hadd.c
3  *
4  * Ullrich von Bassewitz, 19.06.1998
5  */
6
7
8
9 #include <stddef.h>
10 #include "_heap.h"
11
12
13
14 void _hadd (void* mem, size_t size)
15 /* Add an arbitrary memory block to the heap. This function is used by
16  * free(), but it does also allow usage of otherwise unused memory
17  * blocks as heap space. The given block is entered in the free list
18  * without any checks, so beware!
19  */
20 {
21     struct freeblock* f;
22     struct freeblock* left;
23     struct freeblock* right;
24
25     if (size >= sizeof (struct freeblock)) {
26
27         /* Set the admin data */
28         f = (struct freeblock*) mem;
29         f->size = size;
30
31         /* Check if the freelist is empty */
32         if (_hfirst == 0) {
33
34             /* The freelist is empty until now, insert the block */
35             f->prev = 0;
36             f->next = 0;
37             _hfirst = f;
38             _hlast  = f;
39
40         } else {
41
42             /* We have to search the free list. As we are doing so, we check
43              * if it is possible to combine this block with another already
44              * existing block. Beware: The block may be the "missing link"
45              * between *two* other blocks.
46              */
47             left = 0;
48             right = _hfirst;
49             while (right && f > right) {
50                 left = right;
51                 right = right->next;
52             }
53
54
55             /* Ok, the current block must be inserted between left and right (but
56              * beware: one of the two may be zero!). Also check for the condition
57              * that we have to merge two or three blocks.
58              */
59             if (right) {
60                 /* Check if we must merge the block with the right one */
61                 if (((int) f) + size == (int) right) {
62                     /* Merge with the right block */
63                     f->size += right->size;
64                     if (f->next = right->next) {
65                         f->next->prev = f;
66                     } else {
67                         /* This is now the last block */
68                         _hlast = f;
69                     }
70                 } else {
71                     /* No merge, just set the link */
72                     f->next = right;
73                     right->prev = f;
74                 }
75             } else {
76                 f->next = 0;
77                 /* Special case: This is the new freelist end */
78                 _hlast = f;
79             }
80             if (left) {
81                 /* Check if we must merge the block with the left one */
82                 if ((int) f == ((int) left) + left->size) {
83                     /* Merge with the left block */
84                     left->size += f->size;
85                     if (left->next = f->next) {
86                         left->next->prev = left;
87                     } else {
88                         /* This is now the last block */
89                         _hlast = left;
90                     }
91                 } else {
92                     /* No merge, just set the link */
93                     left->next = f;
94                     f->prev = left;
95                 }
96             } else {
97                 f->prev = 0;
98                 /* Special case: This is the new freelist start */
99                 _hfirst = f;
100             }
101         }
102     }
103 }
104
105
106