1 | #include <stdint.h>
|
2 | #include <stdlib.h>
|
3 | #include <stdbool.h>
|
4 | #include <avr/io.h>
|
5 | #include <avr/interrupt.h>
|
6 | #include <avr/pgmspace.h>
|
7 | #include <util/atomic.h>
|
8 | #include <util/delay.h>
|
9 |
|
10 |
|
11 | struct block{
|
12 | size_t size;
|
13 | bool free;
|
14 | struct block *next;
|
15 | };
|
16 |
|
17 |
|
18 | typedef struct
|
19 | {
|
20 | volatile uint8_t* memory_;
|
21 | uint16_t size_;
|
22 | struct block *freeList_;
|
23 | }MyHeap;
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | MyHeap myHeapInitialize(uint16_t heap_size);
|
29 | void myHeapSplit(struct block *fitting_slot,uint16_t size);
|
30 | void* myHeapMalloc(MyHeap *heap, uint16_t size);
|
31 | void myHeapMerge(MyHeap *heap);
|
32 | void myHeapFree(MyHeap *heap,void* ptr);
|
33 |
|
34 | uint16_t myHeapCountBlocks(MyHeap *heap);
|
35 | uint16_t myHeapCountFreeBlocks(MyHeap *heap);
|
36 |
|
37 | uint16_t myHeapCountBlockedBlocks(MyHeap *heap);
|
38 |
|
39 |
|
40 |
|
41 | MyHeap myHeapInitialize(uint16_t heap_size)
|
42 | {
|
43 |
|
44 | void* heap_buffer = (void *) calloc(heap_size,sizeof(uint8_t));
|
45 | MyHeap heap =
|
46 | {
|
47 | .memory_ = heap_buffer,
|
48 | .size_ = heap_size,
|
49 | .freeList_ = heap_buffer,
|
50 | };
|
51 | heap.freeList_->size=heap_size - sizeof(struct block);
|
52 | heap.freeList_->free=true;
|
53 | heap.freeList_->next=NULL;
|
54 | return heap;
|
55 | }
|
56 |
|
57 |
|
58 | void myHeapSplit(struct block *fitting_slot,uint16_t size)
|
59 | {
|
60 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
61 | {
|
62 | struct block *new=(void*)((void*)fitting_slot+size+sizeof(struct block));
|
63 | new->size=(fitting_slot->size)-size-sizeof(struct block);
|
64 | new->free=true;
|
65 | new->next=fitting_slot->next;
|
66 | fitting_slot->size=size;
|
67 | fitting_slot->free=false;
|
68 | fitting_slot->next=new;
|
69 | }
|
70 | }
|
71 |
|
72 |
|
73 | void* myHeapMalloc(MyHeap *heap, uint16_t size)
|
74 | {
|
75 | void *result;
|
76 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
77 | {
|
78 |
|
79 | struct block *curr;
|
80 | curr=heap->freeList_;
|
81 |
|
82 | while((((curr->size)<size)||((curr->free)==false))&&(curr->next!=NULL)){
|
83 | //prev=curr;
|
84 | curr=curr->next;
|
85 | //printf("One block checked\n");
|
86 | }
|
87 |
|
88 | if((curr->size)==size){
|
89 | curr->free=false;
|
90 | result=(void*)(++curr);
|
91 | //printf("Exact fitting block allocated\n");
|
92 | return result;
|
93 | }
|
94 | else if((curr->size)>(size+sizeof(struct block))){
|
95 | myHeapSplit(curr,size);
|
96 | result=(void*)(++curr);
|
97 | //printf("Fitting block allocated with a split\n");
|
98 | return result;
|
99 | }
|
100 | else{
|
101 | result=NULL;
|
102 | PORTA.OUTSET = PIN4_bm;
|
103 | //printf("Sorry. No sufficient memory to allocate\n");
|
104 | return result;
|
105 |
|
106 | }
|
107 | }
|
108 | return result;
|
109 | }
|
110 |
|
111 |
|
112 | void myHeapMerge(MyHeap *heap)
|
113 | {
|
114 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
115 | {
|
116 | struct block *curr;
|
117 | curr=heap->freeList_;
|
118 | while((curr->next)!=NULL){
|
119 | if((curr->free) && (curr->next->free))
|
120 | {
|
121 | curr->size+=(curr->next->size)+sizeof(struct block);
|
122 | curr->next=curr->next->next;
|
123 | }
|
124 | else
|
125 | {
|
126 | //prev=curr;
|
127 | curr=curr->next;
|
128 | }
|
129 | //curr=curr->next;
|
130 | }
|
131 | }
|
132 | }
|
133 |
|
134 | uint16_t myHeapCountBlocks(MyHeap *heap)
|
135 | {
|
136 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
137 | {
|
138 | uint16_t blocks = 0;
|
139 | struct block *curr;
|
140 | curr=heap->freeList_;
|
141 | do
|
142 | {
|
143 | blocks++;
|
144 | curr=curr->next;
|
145 | if (blocks > heap->size_)
|
146 | return blocks;
|
147 | }
|
148 | while((curr->next)!=NULL);
|
149 | return blocks;
|
150 | }
|
151 | return 0;
|
152 | }
|
153 |
|
154 | uint16_t myHeapCountFreeBlocks(MyHeap *heap)
|
155 | {
|
156 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
157 | {
|
158 | uint16_t blocks = 0;
|
159 | struct block *curr;
|
160 | curr=heap->freeList_;
|
161 | do{
|
162 | if (curr->free)
|
163 | blocks++;
|
164 | curr=curr->next;
|
165 | if (blocks > heap->size_)
|
166 | return blocks;
|
167 | }
|
168 | while((curr->next)!=NULL);
|
169 | return blocks;
|
170 | }
|
171 | return 0;
|
172 | }
|
173 |
|
174 | uint16_t myHeapCountBlockedBlocks(MyHeap *heap)
|
175 | {
|
176 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
177 | {
|
178 | uint16_t blocks = 0;
|
179 | struct block *curr;
|
180 | curr=heap->freeList_;
|
181 | do{
|
182 | if (!curr->free)
|
183 | blocks++;
|
184 | curr=curr->next;
|
185 | if (blocks > heap->size_)
|
186 | return blocks;
|
187 | }while((curr->next)!=NULL);
|
188 | return blocks;
|
189 | }
|
190 | return 0;
|
191 | }
|
192 |
|
193 | void myHeapFree(MyHeap *heap,void* ptr)
|
194 | {
|
195 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
196 | {
|
197 | if(((void*)heap->memory_<=ptr)&&(ptr<=(void*)(heap->memory_ + heap->size_))){
|
198 | struct block* curr=ptr;
|
199 | --curr;
|
200 | curr->free=true;
|
201 | myHeapMerge(heap);
|
202 | ptr = NULL;
|
203 | }
|
204 | else
|
205 | {
|
206 | PORTA.OUTSET = PIN3_bm;
|
207 | }
|
208 | }
|
209 | }
|