forked from rcatolino/galloc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
galloc.c
136 lines (132 loc) · 4.22 KB
/
galloc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include "block.h"
static void * blkalloc(int blocksize)
{
void* addr = NULL;
//TRACE("Old break address is %p\n",sbrk(0));
//addr = sbrk(blocksize);
TRACE("Mapping 0x%x bytes of memory\n",blocksize);
addr=mmap(
0, //Let the kernel decide which address to use for this mapping
blocksize, //Length of memory thus allocated
PROT_READ | PROT_WRITE, //Memory won't be executable
MAP_PRIVATE | MAP_ANONYMOUS, //Just rtfm...
-1,0);
TRACE("Got memory, at address %p\n",addr);
//TRACE("New break address is %p\n",sbrk(0));
return addr;
}
static struct block * getBlock(struct block * lastBlock)
{
struct block * newBlock=NULL;
TRACE("Allocating new 0x%zx bytes block.\n",BLOCKSIZE);
newBlock=blkalloc(BLOCKSIZE);
TRACE("New block address is %p.\n",newBlock);
newBlock->size=MMAP_THRESHOLD;
newBlock->next=NULL;
newBlock->prev=lastBlock;
TRACE("Is this the first block?. %p\n",lastBlock);
if (lastBlock)
{
if (lastBlock->next){
lastBlock->next->prev=newBlock;
newBlock->next=lastBlock->next;
}
TRACE("No, adding block in free linked list, %p\n",sbrk(0));
lastBlock->next=newBlock;
} else {
TRACE("Yes, %p\n",sbrk(0));
}
return newBlock;
}
static struct block * split(struct block * freeBlock, int newBlockSize)
{
struct block * usedBlock = NULL;
TRACE("Shrinking free block by 0x%zx bytes\n",newBlockSize+sizeof(struct block));
if (freeBlock->size<newBlockSize+sizeof(struct block))
{
TRACE("Free block %p is too small to shrink,\
move it to used linked list instead\n",freeBlock);
removeFromList(freeBlock);
TRACE("firstUsedBlock : %p\n",firstUsedBlock);
freeBlock->next=firstUsedBlock; //Add it in front of used block list
freeBlock->prev=NULL;
firstUsedBlock->prev=freeBlock;
firstUsedBlock=freeBlock;
return freeBlock;
}
freeBlock->size-=(newBlockSize+sizeof(struct block));
TRACE("Create new used block of size %d bytes with this spare space.\n",newBlockSize);
TRACE("Free block size is now 0x%x bytes.\n",freeBlock->size);
usedBlock=(void*)((long)freeBlock+sizeof (struct block)+freeBlock->size);
TRACE("New block address is %p.\n",usedBlock);
usedBlock->size=newBlockSize;
usedBlock->prev=NULL;
usedBlock->next=firstUsedBlock;
if (firstUsedBlock)
firstUsedBlock->prev=usedBlock;
firstUsedBlock=usedBlock;
return usedBlock;
}
static void * alloc(int requestSize)
{
struct block * i;
struct block * pb=firstFreeBlock;
struct block * bb=NULL;
int bestSize = BLOCKSIZE+1;
TRACE("Allocating 0x%x bytes of memory.\n",requestSize);
//Best Fit, Test wether we have enough memory for request :
for (i=firstFreeBlock; i!=NULL; i=i->next)
{
TRACE("i->next : %p\n",i->next);
if (i->size>=requestSize && i->size<bestSize) //This block is ok.
{
TRACE("Found good block with 0x%x bytes free.\n",i->size);
bb=i;
bestSize=i->size;
}
pb=i;
}
if (!bb)
{
TRACE("No suitable block found for 0x%x bytes.\n",requestSize);
//We need another block :
TRACE("Append block after end of list: %p\n",pb);
pb=getBlock(pb);
i=split(pb,requestSize);
} else {
i=split(bb,requestSize);
}
TRACE("Suitable block available at %p.\n",i);
return DATA(i);
}
void * gmalloc(int requestSize)
{
struct bblock * hugeBlock;
TRACE("0x%x bytes requested\n", requestSize);
TRACE("Header size is 0x%zx.\n",sizeof(struct block));
if (!initialized)
{
TRACE("First call, initializing, %p\n",sbrk(0));
firstFreeBlock=getBlock(NULL);
initialized=1;
}
if (requestSize>=MMAP_THRESHOLD-sizeof(struct block))
{
TRACE("Mapping 0x%x bytes of memory\n",requestSize+sizeof(struct block) );
hugeBlock=mmap(
0, //Let the kernel decide which address to use for this mapping
requestSize+sizeof(struct bblock), //Length of memory thus allocated
PROT_READ | PROT_WRITE, //Memory won't be executable
MAP_PRIVATE | MAP_ANONYMOUS, //Just rtfm...
-1,0);
TRACE("Got memory, at address %p\n",hugeBlock);
hugeBlock->next=firstBBlock;
hugeBlock->size=requestSize+sizeof(struct block);
firstBBlock=hugeBlock;
return DATA(hugeBlock);
}
return alloc(requestSize/*+requestSize%4*/); //to align mem blocks
}