Large cummulative patch for pic16 port.
[fw/sdcc] / device / lib / pic16 / libc / stdlib / malloc.c
1 /*
2  * malloc.c - dynamic memory allocation
3  *
4  * written by Vangelis Rokas, 2004 (vrokas@otenet.gr)
5  *
6  */
7
8 #include "malloc.h"
9
10 extern unsigned char *_dynamicHeap;                     /* pointer to heap */
11
12 unsigned char *malloc(unsigned char len)
13 {
14   _malloc_rec *pHeap;                   /* pointer to block header */
15   _malloc_rec *temp;
16   unsigned char bLen;                   /* size of block  */
17   unsigned char eLen;
18
19         if(len > _MAX_HEAP_SIZE)
20                 return ((unsigned char *)0);
21
22         pHeap = (_malloc_rec *)&_dynamicHeap;
23
24
25         while(1) {
26                 bLen = pHeap->bits.count;
27                 
28                 /* if datum is zero, then last block, return NULL */
29                 if(pHeap->datum == 0)
30                         return ((unsigned char *)0);
31
32                 /* if current block is allocated then proceed to next */
33                 if(pHeap->bits.alloc) {
34                         pHeap += pHeap->bits.count;
35                         continue;
36                 }
37
38                 
39                 /* current block is not allocated, try to allocate */
40                         
41                 /* if current block is not enough for allocation, then proceed to next */
42                 if(bLen <= len) {
43
44                         /* current block is not enough see if we can merge some adjacent
45                          * memory blocks to make it fit */
46                         temp = pHeap + pHeap->bits.count;
47                         eLen = bLen;
48                         while((temp->datum) && (!temp->bits.alloc) && (eLen < len)) {
49                                 eLen += temp->bits.count;
50                                 temp += temp->bits.count;
51                         }
52
53                         if(eLen >= len) {
54                           int i;
55                                 /* yes, there are some free blocks that can be merged, merge them... */
56                                 
57                                 temp = pHeap;
58                             while(eLen > 0) {
59                                         if(eLen > MAX_BLOCK_SIZE)i = MAX_BLOCK_SIZE;
60                                         else i = eLen;
61
62                                         temp->bits.count = i;
63                                         temp->bits.alloc = 0;
64
65                                         temp += i;
66                                         eLen -= i;
67                                 }
68
69                                 bLen = pHeap->bits.count;
70                         } else {
71                                 /* otherwise proceed with next block */
72                                 pHeap += pHeap->bits.count;
73                                 continue;
74                         }
75                 }
76
77
78                 /* current block is enough to hold the new block */
79
80                 /* allocate by filling the fields */
81                 pHeap->bits.count = len+1;
82                 pHeap->bits.alloc = 1;
83
84                 if(bLen > len+1) {
85                         /* if current block size is greater than the requested one,
86                          * create a new empty block at the end of the newly allocated */
87                         temp = pHeap + len+1;
88                         temp->bits.count = bLen - len - 1;
89                         temp->bits.alloc = 0;
90                 }
91
92                 return ((unsigned char *)pHeap + 1);
93         }
94 }