-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmem.c
More file actions
316 lines (239 loc) · 6.76 KB
/
mem.c
File metadata and controls
316 lines (239 loc) · 6.76 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#include "mem.h"
#include <stdlib.h>
#include <stdio.h>
extern void *__heap_start;
typedef struct os_mem_blk_s os_mem_blk;
struct os_mem_blk_s
{
#if defined(OS_MEM_CHKSUM)
uint8_t chksum;
#endif /* OS_MEM_CHKSUM */
uint8_t task;
size_t size;
os_mem_blk *next;
};
#define OS_ERR(a, b)
#define os_tsk_curr 1
static os_mem_blk *os_mem_first;
static os_mem_blk *os_mem_final;
static int8_t os_free_blk(os_mem_blk *blk, os_mem_blk *prev);
/**
*
* Heap structure
* |os_mem_first|.........|blk|.....|blk| ......|os_mem_final|
*
* Every os_mem_blk sits at the end of the allocated block of memory.
* The first os_mem_blk has no associated memory.
*
**/
/* Get the start of the memory contained in a block */
#define BLK_START(blk) ((char *)(blk) + sizeof(os_mem_blk) - (blk)->size)
/* Get the final byte of a block */
#define BLK_END(blk) ((char *)(blk) + sizeof(os_mem_blk))
/*******************
* MEMORY CHECKING *
*******************/
/**
*
* Since we have no memory protection at all, if OS_MEM_CHKSUM is defined,
* then each memory block will have a simple checksum of the contents of the
* structure. If the heap itself is corrupted, then hopefully the checksums
* will be able to detect the problem for debugging.
*
**/
#if defined(OS_MEM_CHKSUM)
/* Define macros for memory checking */
/* BLK_CHK runs code if blk is not a valid mem_blk */
# define BLK_CHK(blk, code) if (os_mem_chk(blk)) {code;}
/* BLK_UPDATE updates the checksum of a block to match its contents */
# define BLK_UPDATE(blk) (blk)->chksum = os_mem_chksum(blk)
#else
/* If we're not going to use checksums, define them as blank */
# define BLK_CHK(blk, code)
# define BLK_UPDATE(blk)
#endif /* OS_MEM_CHKSUM */
#if defined(OS_MEM_CHKSUM)
/* Define memory checking functions */
/**
* Generte a checksum for a memory block
**/
static uint8_t os_mem_chksum(os_mem_blk *blk);
/**
* Check whether a memory block is valid. Returns 0 if valid, -1 if not.
**/
static int8_t os_mem_chk(os_mem_blk *blk);
static uint8_t os_mem_chksum(os_mem_blk *blk)
{
uint8_t sum, ind;
sum = 0xaa;
ind = sizeof(os_mem_blk);
/* Note that ind = 0 is not considered. This means that *
* we don't sum the old checksum as well. */
while (--ind) sum ^= ((char *)blk)[ind];
return sum;
}
static int8_t os_mem_chk(os_mem_blk *blk)
{
/* Check it's in thr right place */
if (blk < os_mem_first || blk > os_mem_final)
{
OS_ERR(inv_blk, "mem_chk: out of range");
return -1;
}
/* Check it has a valid checksum */
if (os_mem_chksum(blk) != blk->chksum)
{
OS_ERR(inv_blk, "mem_chk: inv sum");
return -1;
}
return 0;
}
#endif /* OS_MEM_CHKSUM */
/********
* INIT *
********/
void os_mem_init(void)
{
/* Initialize the first memory block */
os_mem_first = (void *)1000;
os_mem_first->task = -1;
os_mem_first->next = NULL;
os_mem_first->size = 0;
BLK_UPDATE(os_mem_first);
os_mem_final = os_mem_first;
}
/*********************
* ALLOCATING MEMORY *
*********************/
void *os_alloc(size_t bytes)
{
return os_alloc_task(bytes, os_tsk_curr);
}
void *os_alloc_task(size_t bytes, uint8_t tskn)
{
os_mem_blk *blk, *prev, *new;
size_t spare;
bytes += sizeof(os_mem_blk);
blk = os_mem_first;
for (;;)
{
prev = blk;
blk = blk->next;
if (blk == NULL) break;
BLK_CHK(blk, OS_ERR(inv_blk, "alloc: inv blk"); return NULL);
spare = BLK_START(blk) - BLK_END(prev);
if (spare >= bytes) break;
}
new = (os_mem_blk *)((char *)prev + bytes);
if (blk == NULL) os_mem_final = new;
new->size = bytes;
new->next = blk;
new->task = tskn;
BLK_UPDATE(new);
prev->next = new;
BLK_UPDATE(prev);
return BLK_START(new);
}
/******************
* FREEING MEMORY *
******************/
int8_t os_free_tsk(uint8_t tskn)
{
os_mem_blk *blk, *next;
blk = os_mem_first->next;
BLK_CHK(blk, OS_ERR(inv_blk, "free: inv blk"); return -1);
while (blk)
{
next = blk->next;
BLK_CHK(blk, OS_ERR(inv_blk, "free: inv blk"); return -1);
if (blk->task == tskn)
os_free(blk);
blk = next;
}
return 0;
}
int8_t os_free(void *mem)
{
os_mem_blk *prev, *blk;
prev = (os_mem_blk *)((char *)mem - sizeof(os_mem_blk));
BLK_CHK(prev, OS_ERR(inv_blk, "free: inv prev blk"); return -1);
blk = prev->next;
BLK_CHK(blk, OS_ERR(inv_blk, "free: inv blk"); return -1);
return os_free_blk(blk, prev);
}
static int8_t os_free_blk(os_mem_blk *blk, os_mem_blk *prev)
{
os_mem_blk *next;
next = blk->next;
if (next)
BLK_CHK(next, OS_ERR(inv_blk, "free: inv next blk"); return -1);
prev->next = next;
BLK_UPDATE(prev);
#if defined(OS_MEM_CHKSUM)
/* If we enabled checksums, reset the block to an invalid state */
blk->chksum = 0;
blk->task = 0;
blk->size = 0;
blk->next = 0;
#endif /* OS_MEM_CHKSUM */
return 0;
}
/*********
* DEBUG *
*********/
#if defined(OS_MEM_DBG)
int8_t os_mem_print(os_pipe *p)
{
os_mem_blk *blk, *prev;
char out[100];
size_t used, heap, heapmax;
heapmax = 0;
heap = BLK_END(os_mem_final) - BLK_START(os_mem_first);
used = 0;
/* Print our header */
if (os_write_str(p, "\r\n _________MEMORY DEBUG_________\r\n\n") != 0)
return -1;
/* Print a summary of the heap location */
snprintf(
out,
sizeof(out),
" Heap: 0x%04x-0x%04x\r\n Size: %6d\r\n Max: %6d\r\n\n",
(uintptr_t)BLK_START(os_mem_first),
(uintptr_t)BLK_END(os_mem_final),
heap, heapmax
);
/* Write the summary out */
if (os_write_str(p, out) != 0)
return -1;
/* Print column headers */
if (os_write_str(p, " _Blk__ _Memory______ Bytes Tsk\r\n") != 0)
return -1;
/* Iterate across all memory blocks */
for (prev = os_mem_first; prev->next; prev = prev->next)
{
blk = prev->next;
/* Check every block is valid */
BLK_CHK(
blk,
snprintf(out, sizeof(out), "INV BLK %p\r\n", (void *)blk);
os_write_str(p, out);
return -1;
);
/* Count up the memory in use */
used += blk->size;
/* Print details of the block */
snprintf(
out, sizeof(out), " 0x%04x 0x%04x - %04x %5d %3d\r\n",
(uintptr_t)blk,
(uintptr_t)BLK_START(blk),
(uintptr_t)BLK_END(blk),
blk->size - sizeof(os_mem_blk),
blk->task
);
if (os_write_str(p, out)) return -1;
}
snprintf(out, sizeof(out), " Total %4d\r\n", heap);
if (os_write_str(p, out)) return -1;
return 0;
}
#endif /* OS_MEM_DBG */