OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [libmem/] [malloc/] [malloc.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*****************************************************************************
2
Simple malloc
3
Chris Giese <geezer@execpc.com> http://www.execpc.com/~geezer
4
Release date: Oct 30, 2002
5
This code is public domain (no copyright).
6
You can do whatever you want with it.
7
 
8
Features:
9
- First-fit
10
- free() coalesces adjacent free blocks
11
- Uses variable-sized heap, enlarged with kbrk()/sbrk() function
12
- Does not use mmap()
13
- Can be easily modified to use fixed-size heap
14
- Works with 16- or 32-bit compilers
15
 
16
Build this program with either of the two main() functions, then run it.
17
Messages that indicate a software error will contain three asterisks (***).
18
*****************************************************************************/
19
#include <string.h> /* memcpy(), memset() */
20
#include <stdio.h> /* printf() */
21
#include <l4/macros.h>
22
#define _32BIT  1
23
 
24
/* use small (32K) heap for 16-bit compilers,
25
large (500K) heap for 32-bit compilers */
26
#if defined(_32BIT)
27
#define HEAP_SIZE       500000uL
28
#else
29
#define HEAP_SIZE       32768u
30
#endif
31
 
32
#define MALLOC_MAGIC    0x6D92  /* must be < 0x8000 */
33
 
34
typedef struct _malloc          /* Turbo C      DJGPP */
35
{
36
        size_t size;            /* 2 bytes       4 bytes */
37
        struct _malloc *next;   /* 2 bytes       4 bytes */
38
        unsigned magic : 15;    /* 2 bytes total 4 bytes total */
39
        unsigned used : 1;
40
} malloc_t;             /* total   6 bytes      12 bytes */
41
 
42
static char *g_heap_bot, *g_kbrk, *g_heap_top;
43
/*****************************************************************************
44
*****************************************************************************/
45
void dump_heap(void)
46
{
47
        unsigned blks_used = 0, blks_free = 0;
48
        size_t bytes_used = 0, bytes_free = 0;
49
        malloc_t *m;
50
        int total;
51
 
52
        printf("===============================================\n");
53
        for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)
54
        {
55
                printf("blk %5p: %6u bytes %s\n", m,
56
                        m->size, m->used ? "used" : "free");
57
                if(m->used)
58
                {
59
                        blks_used++;
60
                        bytes_used += m->size;
61
                }
62
                else
63
                {
64
                        blks_free++;
65
                        bytes_free += m->size;
66
                }
67
        }
68
        printf("blks:  %6u used, %6u free, %6u total\n", blks_used,
69
                blks_free, blks_used + blks_free);
70
        printf("bytes: %6u used, %6u free, %6u total\n", bytes_used,
71
                bytes_free, bytes_used + bytes_free);
72
        printf("g_heap_bot=0x%p, g_kbrk=0x%p, g_heap_top=0x%p\n",
73
                g_heap_bot, g_kbrk, g_heap_top);
74
        total = (bytes_used + bytes_free) +
75
                        (blks_used + blks_free) * sizeof(malloc_t);
76
        if(total != g_kbrk - g_heap_bot)
77
                printf("*** some heap memory is not accounted for\n");
78
        printf("===============================================\n");
79
}
80
/*****************************************************************************
81
POSIX sbrk() looks like this
82
        void *sbrk(int incr);
83
Mine is a bit different so I can signal the calling function
84
if more memory than desired was allocated (e.g. in a system with paging)
85
If your kbrk()/sbrk() always allocates the amount of memory you ask for,
86
this code can be easily changed.
87
 
88
                        int brk(        void *sbrk(             void *kbrk(
89
function                 void *adr);     int delta);             int *delta);
90
----------------------  ------------    ------------            -------------
91
POSIX?                  yes             yes                     NO
92
return value if error   -1              -1                      NULL
93
get break value         .               sbrk(0)                 int x=0; kbrk(&x);
94
set break value to X    brk(X)          sbrk(X - sbrk(0))       int x=X, y=0; kbrk(&x) - kbrk(&y);
95
enlarge heap by N bytes .               sbrk(+N)                int x=N; kbrk(&x);
96
shrink heap by N bytes  .               sbrk(-N)                int x=-N; kbrk(&x);
97
can you tell if you're
98
  given more memory
99
  than you wanted?      no              no                      yes
100
*****************************************************************************/
101
static void *kbrk(int *delta)
102
{
103
        static char heap[HEAP_SIZE];
104
/**/
105
        char *new_brk, *old_brk;
106
 
107
/* heap doesn't exist yet */
108
        if(g_heap_bot == NULL)
109
        {
110
                g_heap_bot = g_kbrk = heap;
111
                g_heap_top = g_heap_bot + HEAP_SIZE;
112
        }
113
        new_brk = g_kbrk + (*delta);
114
/* too low: return NULL */
115
        if(new_brk < g_heap_bot)
116
                return NULL;
117
/* too high: return NULL */
118
        if(new_brk >= g_heap_top)
119
                return NULL;
120
/* success: adjust brk value... */
121
        old_brk = g_kbrk;
122
        g_kbrk = new_brk;
123
/* ...return actual delta... (for this sbrk(), they are the same)
124
        (*delta) = (*delta); */
125
/* ...return old brk value */
126
        return old_brk;
127
}
128
/*****************************************************************************
129
kmalloc() and kfree() use g_heap_bot, but not g_kbrk nor g_heap_top
130
*****************************************************************************/
131
void *kmalloc(size_t size)
132
{
133
        unsigned total_size;
134
        malloc_t *m, *n;
135
        int delta;
136
 
137
        if(size == 0)
138
                return NULL;
139
        total_size = size + sizeof(malloc_t);
140
/* search heap for free block (FIRST FIT) */
141
        m = (malloc_t *)g_heap_bot;
142
/* g_heap_bot == 0 == NULL if heap does not yet exist */
143
        if(m != NULL)
144
        {
145
                if(m->magic != MALLOC_MAGIC)
146
//                      panic("kernel heap is corrupt in kmalloc()");
147
                {
148
                        printf("*** kernel heap is corrupt in kmalloc()\n");
149
                        return NULL;
150
                }
151
                for(; m->next != NULL; m = m->next)
152
                {
153
                        if(m->used)
154
                                continue;
155
/* size == m->size is a perfect fit */
156
                        if(size == m->size)
157
                                m->used = 1;
158
                        else
159
                        {
160
/* otherwise, we need an extra sizeof(malloc_t) bytes for the header
161
of a second, free block */
162
                                if(total_size > m->size)
163
                                        continue;
164
/* create a new, smaller free block after this one */
165
                                n = (malloc_t *)((char *)m + total_size);
166
                                n->size = m->size - total_size;
167
                                n->next = m->next;
168
                                n->magic = MALLOC_MAGIC;
169
                                n->used = 0;
170
/* reduce the size of this block and mark it used */
171
                                m->size = size;
172
                                m->next = n;
173
                                m->used = 1;
174
                        }
175
                        return (char *)m + sizeof(malloc_t);
176
                }
177
        }
178
/* use kbrk() to enlarge (or create!) heap */
179
        delta = total_size;
180
        n = kbrk(&delta);
181
/* uh-oh */
182
        if(n == NULL)
183
                return NULL;
184
        if(m != NULL)
185
                m->next = n;
186
        n->size = size;
187
        n->magic = MALLOC_MAGIC;
188
        n->used = 1;
189
/* did kbrk() return the exact amount of memory we wanted?
190
cast to make "gcc -Wall -W ..." shut the hell up */
191
        if((int)total_size == delta)
192
                n->next = NULL;
193
        else
194
        {
195
/* it returned more than we wanted (it will never return less):
196
create a new, free block */
197
                m = (malloc_t *)((char *)n + total_size);
198
                m->size = delta - total_size - sizeof(malloc_t);
199
                m->next = NULL;
200
                m->magic = MALLOC_MAGIC;
201
                m->used = 0;
202
 
203
                n->next = m;
204
        }
205
        return (char *)n + sizeof(malloc_t);
206
}
207
 
208
/*****************************************************************************
209
*****************************************************************************/
210
void kfree(void *blk)
211
{
212
        malloc_t *m, *n;
213
 
214
/* get address of header */
215
        m = (malloc_t *)((char *)blk - sizeof(malloc_t));
216
        if(m->magic != MALLOC_MAGIC)
217
//              panic("attempt to kfree() block at 0x%p "
218
//                      "with bad magic value", blk);
219
        {
220
                printf("*** attempt to kfree() block at 0x%p "
221
                        "with bad magic value\n", blk);
222
                BUG();
223
                return;
224
        }
225
/* find this block in the heap */
226
        n = (malloc_t *)g_heap_bot;
227
        if(n->magic != MALLOC_MAGIC)
228
//              panic("kernel heap is corrupt in kfree()");
229
        {
230
                printf("*** kernel heap is corrupt in kfree()\n");
231
                return;
232
        }
233
        for(; n != NULL; n = n->next)
234
        {
235
                if(n == m)
236
                        break;
237
        }
238
/* not found? bad pointer or no heap or something else? */
239
        if(n == NULL)
240
//              panic("attempt to kfree() block at 0x%p "
241
//                      "that is not in the heap", blk);
242
        {
243
                printf("*** attempt to kfree() block at 0x%p "
244
                        "that is not in the heap\n", blk);
245
                return;
246
        }
247
/* free the block */
248
        m->used = 0;
249
/* BB: Addition: put 0xFF to block memory so we know if we use freed memory */
250
        memset(blk, 0xFF, m->size);
251
 
252
/* coalesce adjacent free blocks
253
Hard to spell, hard to do */
254
        for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)
255
        {
256
                while(!m->used && m->next != NULL && !m->next->used)
257
                {
258
/* resize this block */
259
                        m->size += sizeof(malloc_t) + m->next->size;
260
/* merge with next block */
261
                        m->next = m->next->next;
262
                }
263
        }
264
}
265
/*****************************************************************************
266
*****************************************************************************/
267
void *krealloc(void *blk, size_t size)
268
{
269
        void *new_blk;
270
        malloc_t *m;
271
 
272
/* size == 0: free block */
273
        if(size == 0)
274
        {
275
                if(blk != NULL)
276
                        kfree(blk);
277
                new_blk = NULL;
278
        }
279
        else
280
        {
281
/* allocate new block */
282
                new_blk = kmalloc(size);
283
/* if allocation OK, and if old block exists, copy old block to new */
284
                if(new_blk != NULL && blk != NULL)
285
                {
286
                        m = (malloc_t *)((char *)blk - sizeof(malloc_t));
287
                        if(m->magic != MALLOC_MAGIC)
288
//                              panic("attempt to krealloc() block at "
289
//                                      "0x%p with bad magic value", blk);
290
                        {
291
                                printf("*** attempt to krealloc() block at "
292
                                        "0x%p with bad magic value\n", blk);
293
                                return NULL;
294
                        }
295
/* copy minimum of old and new block sizes */
296
                        if(size > m->size)
297
                                size = m->size;
298
                        memcpy(new_blk, blk, size);
299
/* free the old block */
300
                        kfree(blk);
301
                }
302
        }
303
        return new_blk;
304
}
305
/*****************************************************************************
306
*****************************************************************************/
307
 
308
#if 0
309
 
310
#include <stdlib.h> /* rand() */
311
 
312
 
313
#define SLOTS   17
314
 
315
int main(void)
316
{
317
        unsigned lifetime[SLOTS];
318
        void *blk[SLOTS];
319
        int i, j, k;
320
 
321
        dump_heap();
322
        memset(lifetime, 0, sizeof(lifetime));
323
        memset(blk, 0, sizeof(blk));
324
        for(i = 0; i < 1000; i++)
325
        {
326
                printf("Pass %6u\n", i);
327
                for(j = 0; j < SLOTS; j++)
328
                {
329
/* age the block */
330
                        if(lifetime[j] != 0)
331
                        {
332
                                (lifetime[j])--;
333
                                continue;
334
                        }
335
/* too old; free it */
336
                        if(blk[j] != NULL)
337
                        {
338
                                kfree(blk[j]);
339
                                blk[j] = NULL;
340
                        }
341
/* alloc new block of random size
342
Note that size_t==unsigned, but kmalloc() uses integer math,
343
so block size must be positive integer */
344
#if defined(_32BIT)
345
                        k = rand() % 40960 + 1;
346
#else
347
                        k = rand() % 4096 + 1;
348
#endif
349
                        blk[j] = kmalloc(k);
350
                        if(blk[j] == NULL)
351
                                printf("failed to alloc %u bytes\n", k);
352
                        else
353
/* give it a random lifetime 0-20 */
354
                                lifetime[j] = rand() % 21;
355
                }
356
        }
357
/* let's see what we've wrought */
358
        printf("\n\n");
359
        dump_heap();
360
/* free everything */
361
        for(j = 0; j < SLOTS; j++)
362
        {
363
                if(blk[j] != NULL)
364
                {
365
                        kfree(blk[j]);
366
                        blk[j] = NULL;
367
                }
368
                (lifetime[j]) = 0;
369
        }
370
/* after all that, we should have a single, unused block */
371
        dump_heap();
372
        return 0;
373
}
374
/*****************************************************************************
375
*****************************************************************************/
376
 
377
int main(void)
378
{
379
        void *b1, *b2, *b3;
380
 
381
        dump_heap();
382
 
383
        b1 = kmalloc(42);
384
        dump_heap();
385
 
386
        b2 = kmalloc(23);
387
        dump_heap();
388
 
389
        b3 = kmalloc(7);
390
        dump_heap();
391
 
392
        b2 = krealloc(b2, 24);
393
        dump_heap();
394
 
395
        kfree(b1);
396
        dump_heap();
397
 
398
        b1 = kmalloc(5);
399
        dump_heap();
400
 
401
        kfree(b2);
402
        dump_heap();
403
 
404
        kfree(b3);
405
        dump_heap();
406
 
407
        kfree(b1);
408
        dump_heap();
409
 
410
        return 0;
411
}
412
#endif
413
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.