1 #include "ucl.h"
2 
3 /**
4  * Memory Management Module
5  *
6  * UCC uses a heap-based memory management strategy. The memory is
7  * allocated from a heap. When freeing a heap, the memory in the heap
8  * will be recycled into a free block list.
9  *
10  * A heap is made of a list of memory blocks. Each memory block
11  * is a chunk of memory.
12  */
13 
14 // free block list
15 static struct mblock *FreeBlocks;
16 
17 /**
18  * Initialize a memory heap.
19  */
InitHeap(Heap hp)20 void InitHeap(Heap hp)
21 {
22 	hp->head.next = NULL;
23 	hp->head.begin = hp->head.end = hp->head.avail = NULL;
24 	hp->last = &hp->head;
25 }
26 
27 /**
28  * This function allocates size bytes from a heap and returns
29  * a pointer to the allocated memory.
30  */
HeapAllocate(Heap hp,int size)31 void* HeapAllocate(Heap hp, int size)
32 {
33 	struct mblock *blk = NULL;
34 
35 	// the returned pointer must be suitably aligned to hold values of any type
36 	size = ALIGN(size, sizeof(union align));
37 
38 	blk = hp->last;
39 
40 	/// if the last memory block can't satisfy the request, find a big enough memory
41 	/// block from the free block list, if there is no such memory block, allocate
42 	/// a new memory block
43 	while (size > blk->end - blk->avail)
44 	{
45 		if ((blk->next = FreeBlocks) != NULL)
46 		{
47 			FreeBlocks = FreeBlocks->next;
48 			blk = blk->next;
49 		}
50 		else
51 		{
52 			int m = size + MBLOCK_SIZE + sizeof(struct mblock);
53 
54 			blk->next = (struct mblock *)malloc(m);
55 			blk = blk->next;
56 			if (blk == NULL)
57 			{
58 				Fatal("Memory exhausted");
59 			}
60 			blk->end = (char *)blk + m;
61 		}
62 
63 		blk->avail = blk->begin = (char *)(blk + 1);
64 		blk->next = NULL;
65 		hp->last = blk;
66 	}
67 
68 	blk->avail += size;
69 
70 	return blk->avail - size;
71 }
72 
73 /**
74  * Recycle a heap's all memory blocks into free block list
75  */
FreeHeap(Heap hp)76 void FreeHeap(Heap hp)
77 {
78 	hp->last->next = FreeBlocks;
79 	FreeBlocks = hp->head.next;
80 	InitHeap(hp);
81 }
82 
83