annotate tmalloc.c @ 34:5d51fff843eb default tip

A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 08 Mar 2020 19:18:48 +0200
parents 33594243ce31
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
1 /*
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
2 * Tiny malloc
33
33594243ce31 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 0
diff changeset
3 *
0
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
4 * Copyright (c) 2014 Fabrice Bellard
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
5 *
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
7 * of this software and associated documentation files (the "Software"), to deal
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
8 * in the Software without restriction, including without limitation the rights
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
10 * copies of the Software, and to permit persons to whom the Software is
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
11 * furnished to do so, subject to the following conditions:
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
12 *
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
13 * The above copyright notice and this permission notice shall be included in
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
14 * all copies or substantial portions of the Software.
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
15 *
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
22 * THE SOFTWARE.
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
23 */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
24 #include <stddef.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
25 #include <stdlib.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
26 #include <stdio.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
27 #include <inttypes.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
28 #include <string.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
29 #include <limits.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
30 #ifndef MALLOC_TEST
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
31 #define NDEBUG
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
32 #endif
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
33 #include <assert.h>
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
34
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
35 /*
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
36 * Note: only works for 32 bit pointers
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
37 */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
38 #define MALLOC_ALIGN 8
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
39 #define MALLOC_BLOCK_SIZE 32
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
40
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
41 #define STATE_FREE 0xaa
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
42 #define STATE_ALLOCATED 0x55
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
43
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
44 struct list_head {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
45 struct list_head *prev, *next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
46 };
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
47
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
48 #define list_entry(el, type, member) \
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
49 ((type *)((uint8_t *)(el) - offsetof(type, member)))
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
50
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
51 /* Note: the 'state' byte is stored just before the MemBlock header,
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
52 so at most 23 bytes can be allocated in a single block. */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
53 typedef struct MemBlock {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
54 struct list_head link;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
55 union {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
56 uint8_t data[0] __attribute((aligned(MALLOC_ALIGN)));
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
57 struct list_head free_link;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
58 } u;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
59 } MemBlock;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
60
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
61 void *sbrk(intptr_t increment);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
62
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
63 /* Invariants: the last block is always a free block. The last free
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
64 block is always the last block. */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
65 static struct list_head free_list;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
66 static struct list_head block_list;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
67 static uint8_t *mem_top;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
68
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
69 /* insert 'el' after prev */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
70 static void list_add(struct list_head *el, struct list_head *prev)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
71 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
72 struct list_head *next = prev->next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
73 prev->next = el;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
74 el->prev = prev;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
75 el->next = next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
76 next->prev = el;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
77 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
78
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
79 static void list_del(struct list_head *el)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
80 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
81 struct list_head *prev, *next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
82 prev = el->prev;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
83 next = el->next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
84 prev->next = next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
85 next->prev = prev;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
86 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
87
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
88 static size_t get_alloc_size(size_t size)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
89 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
90 size = offsetof(MemBlock, u.data) + size;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
91 /* one more byte for the state byte from the next block */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
92 size = (size + MALLOC_BLOCK_SIZE) & ~(MALLOC_BLOCK_SIZE - 1);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
93 return size;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
94 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
95
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
96 /* Note: this size includes the 'state' byte from the next block */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
97 static size_t get_block_size(MemBlock *p)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
98 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
99 uint8_t *end;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
100 struct list_head *el;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
101 el = p->link.next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
102 if (el == &block_list)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
103 end = mem_top;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
104 else
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
105 end = (uint8_t *)list_entry(el, MemBlock, link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
106 return end - (uint8_t *)p;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
107 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
108
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
109 static inline void set_block_state(MemBlock *p, int state)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
110 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
111 ((uint8_t *)p)[-1] = state;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
112 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
113
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
114 static inline int get_block_state(const MemBlock *p)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
115 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
116 return ((const uint8_t *)p)[-1];
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
117 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
118
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
119 void *malloc(size_t size)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
120 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
121 MemBlock *p, *p1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
122 struct list_head *el;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
123 size_t block_size;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
124
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
125 if (size == 0 || size > (INT_MAX - 2 * MALLOC_BLOCK_SIZE))
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
126 return NULL;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
127 if (free_list.next == NULL) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
128 /* init */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
129 p = sbrk(MALLOC_BLOCK_SIZE * 2);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
130 if (p == (void *)-1)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
131 return NULL;
33
33594243ce31 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 0
diff changeset
132
0
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
133 mem_top = sbrk(0);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
134 free_list.prev = free_list.next = &free_list;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
135 block_list.prev = block_list.next = &block_list;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
136 p++;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
137 set_block_state(p, STATE_FREE);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
138 list_add(&p->link, &block_list);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
139 list_add(&p->u.free_link, &free_list);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
140 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
141
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
142 size = get_alloc_size(size);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
143 el = free_list.next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
144 for(;;) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
145 p = list_entry(el, MemBlock, u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
146 assert(get_block_state(p) == STATE_FREE);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
147 block_size = get_block_size(p);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
148 if (size < block_size) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
149 goto done1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
150 } else if (el == free_list.prev) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
151 /* last free block: increase its size */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
152 if (sbrk(size + MALLOC_BLOCK_SIZE - block_size) == (void *)-1)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
153 return NULL;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
154 mem_top = sbrk(0);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
155 done1:
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
156 p1 = (MemBlock *)((uint8_t *)p + size);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
157 list_add(&p1->link, &p->link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
158 list_add(&p1->u.free_link, &p->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
159 set_block_state(p1, STATE_FREE);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
160 list_del(&p->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
161 done:
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
162 set_block_state(p, STATE_ALLOCATED);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
163 return p->u.data;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
164 } else if (size == block_size) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
165 list_del(&p->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
166 goto done;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
167 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
168 el = el->next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
169 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
170 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
171
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
172 void free(void *ptr)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
173 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
174 MemBlock *p, *p1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
175 struct list_head *el;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
176
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
177 if (!ptr)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
178 return;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
179 p = (MemBlock *)((uint8_t *)ptr - offsetof(MemBlock, u.data));
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
180 assert(get_block_state(p) == STATE_ALLOCATED);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
181
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
182 /* mark as free */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
183 list_add(&p->u.free_link, &free_list);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
184 set_block_state(p, STATE_FREE);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
185
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
186 /* merge with previous free block if possible */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
187 el = p->link.prev;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
188 if (el != &block_list) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
189 p1 = list_entry(el, MemBlock, link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
190 if (get_block_state(p1) == STATE_FREE) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
191 list_del(&p->link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
192 list_del(&p->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
193 p = p1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
194 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
195 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
196 /* merge with next block if possible */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
197 el = p->link.next;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
198 if (el != &block_list) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
199 p1 = list_entry(el, MemBlock, link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
200 if (get_block_state(p1) == STATE_FREE) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
201 list_del(&p1->link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
202 /* keep p in the same position in free_list as p1 */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
203 list_del(&p->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
204 list_add(&p->u.free_link, &p1->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
205 list_del(&p1->u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
206 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
207 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
208 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
209
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
210 void *realloc(void *ptr, size_t size)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
211 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
212 MemBlock *p;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
213 void *ptr1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
214 size_t size1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
215
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
216 if (ptr == NULL) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
217 return malloc(size);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
218 } else if (size == 0) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
219 free(ptr);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
220 return NULL;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
221 } else {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
222 p = (MemBlock *)((uint8_t *)ptr - offsetof(MemBlock, u.data));
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
223 assert(get_block_state(p) == STATE_ALLOCATED);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
224 ptr1 = malloc(size);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
225 if (!ptr1)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
226 return NULL;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
227 /* Note: never the last block so it is valid */
33
33594243ce31 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 0
diff changeset
228 size1 = (uint8_t *)list_entry(p->link.next, MemBlock, link) -
0
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
229 p->u.data - 1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
230 if (size < size1)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
231 size1 = size;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
232 memcpy(ptr1, ptr, size1);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
233 free(ptr);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
234 return ptr1;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
235 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
236 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
237
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
238 #ifdef MALLOC_TEST
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
239 static void malloc_check(void)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
240 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
241 MemBlock *p;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
242 struct list_head *el;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
243 int state;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
244
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
245 for(el = block_list.next; el != &block_list; el = el->next) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
246 p = list_entry(el, MemBlock, link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
247 state = get_block_state(p);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
248 assert(state == STATE_FREE || state == STATE_ALLOCATED);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
249 if (el->next != &block_list)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
250 assert(el->next > el);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
251 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
252 for(el = free_list.next; el != &free_list; el = el->next) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
253 p = list_entry(el, MemBlock, u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
254 assert(get_block_state(p) == STATE_FREE);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
255 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
256
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
257 /* check invariant */
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
258 el = free_list.prev;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
259 if (el != &free_list) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
260 p = list_entry(el, MemBlock, u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
261 assert(&p->link == block_list.prev);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
262 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
263 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
264
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
265 static void malloc_dump(void)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
266 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
267 MemBlock *p;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
268 struct list_head *el;
33
33594243ce31 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 0
diff changeset
269
0
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
270 printf("blocks:\n");
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
271 for(el = block_list.next; el != &block_list; el = el->next) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
272 p = list_entry(el, MemBlock, link);
33
33594243ce31 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 0
diff changeset
273 printf("block: %p next=%p free=%d size=%u\n", p, p->link.next,
0
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
274 get_block_state(p) == STATE_FREE,
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
275 (unsigned int)get_block_size(p));
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
276 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
277 printf("free list:\n");
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
278 for(el = free_list.next; el != &free_list; el = el->next) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
279 p = list_entry(el, MemBlock, u.free_link);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
280 printf("block: %p size=%u\n", p, (unsigned int)get_block_size(p));
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
281 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
282 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
283
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
284 int main(int argc, char **argv)
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
285 {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
286 int i, n, j, size;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
287 void **tab;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
288
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
289 n = 100;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
290 tab = malloc(sizeof(void *) * n);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
291 memset(tab, 0, n * sizeof(void *));
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
292
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
293 for(i = 0; i < n * 1000; i++) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
294 j = random() % n;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
295
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
296 free(tab[j]);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
297
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
298 malloc_check();
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
299
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
300 size = random() % 500;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
301 tab[j] = malloc(size);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
302 memset(tab[j], 0x11, size);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
303
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
304 malloc_check();
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
305 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
306
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
307 malloc_dump();
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
308
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
309 for(i = 0; i < n; i++) {
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
310 free(tab[i]);
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
311 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
312 return 0;
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
313 }
772086c29cc7 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
314 #endif