-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathmemory_allocator.c
127 lines (105 loc) · 2.5 KB
/
memory_allocator.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
#include <exec/types.h>
#include <proto/exec.h>
#include "a314.h"
#include "device.h"
#include "debug.h"
#define SysBase (*(struct ExecBase **)4)
#define MEM_SIZE 65536
#define MEM_START (512 + 8)
struct MyMemChunk
{
struct MyMemChunk *next;
USHORT address;
USHORT length;
};
void init_memory_allocator(struct A314Device *dev)
{
struct MyMemChunk *mc = (struct MyMemChunk *)AllocMem(sizeof(struct MyMemChunk), 0);
mc->next = NULL;
mc->address = MEM_START;
mc->length = MEM_SIZE - MEM_START;
dev->first_chunk = mc;
}
ULONG a314base_translate_address(__reg("a6") struct A314Device *dev, __reg("a0") void *address)
{
dbg_trace("Enter: a314base_translate_address");
// It is an error if the application calls this routine.
return INVALID_A314_ADDRESS;
}
ULONG a314base_alloc_mem(__reg("a6") struct A314Device *dev, __reg("d0") ULONG length)
{
dbg_trace("Enter: a314base_alloc_mem, length=$l", length);
length = (length + 3) & ~3;
Forbid();
ULONG address = INVALID_A314_ADDRESS;
struct MyMemChunk *prev = NULL;
struct MyMemChunk *mc = dev->first_chunk;
while (mc)
{
if (mc->length >= length)
{
address = mc->address;
if (mc->length == length)
{
if (prev)
prev->next = mc->next;
else
dev->first_chunk = mc->next;
FreeMem(mc, sizeof(struct MyMemChunk));
}
else
{
mc->address += length;
mc->length -= length;
}
break;
}
prev = mc;
mc = mc->next;
}
Permit();
dbg_trace("Leave: a314base_alloc_mem, address=$l", address);
return address;
}
void a314base_free_mem(__reg("a6") struct A314Device *dev, __reg("d0") ULONG address, __reg("d1") ULONG length)
{
dbg_trace("Enter: a314base_free_mem, address=$l, length=$l", address, length);
length = (length + 3) & ~3;
Forbid();
struct MyMemChunk *prev = NULL;
struct MyMemChunk *succ = dev->first_chunk;
while (succ)
{
if (succ->address > address)
break;
prev = succ;
succ = succ->next;
}
if (prev && prev->address + prev->length == address)
{
prev->length += length;
if (succ && prev->address + prev->length == succ->address)
{
prev->length += succ->length;
prev->next = succ->next;
FreeMem(succ, sizeof(struct MyMemChunk));
}
}
else if (succ && address + length == succ->address)
{
succ->address = address;
succ->length += length;
}
else
{
struct MyMemChunk *mc = (struct MyMemChunk *)AllocMem(sizeof(struct MyMemChunk), 0);
mc->next = succ;
mc->address = address;
mc->length = length;
if (prev)
prev->next = mc;
else
dev->first_chunk = mc;
}
Permit();
}