/[osn-commons]/trunk/plibc/lib/malloc.c
ViewVC logotype

Contents of /trunk/plibc/lib/malloc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 51 - (show annotations)
Fri Aug 16 18:34:43 2024 UTC (7 months, 2 weeks ago) by rakinar2
File MIME type: text/x-c
File size: 6457 byte(s)
feat: add basic utilities and more system calls

1 #include "malloc.h"
2 #include "stddef.h"
3 #include "stdio.h"
4 #include "unistd.h"
5 #include "utils.h"
6 #include <stdbool.h>
7
8 struct malloc_chunk
9 {
10 size_t size;
11 void *ptr;
12 struct malloc_chunk *next;
13 struct malloc_chunk *prev;
14 bool free;
15 };
16
17 static struct malloc_chunk *head = NULL;
18 static struct malloc_chunk *tail = NULL;
19
20 static struct malloc_chunk *free_chunk_head = NULL;
21 static struct malloc_chunk *free_chunk_tail = NULL;
22 static size_t free_chunk_count = 0;
23
24 static void *init_mbrk = NULL;
25
26 static void
27 malloc_init ()
28 {
29 init_mbrk = brk ();
30 }
31
32 static void *
33 unfree (struct malloc_chunk *chunk)
34 {
35 if (chunk->prev != NULL)
36 chunk->prev->next = chunk->next;
37
38 if (chunk->next != NULL)
39 chunk->next->prev = chunk->prev;
40
41 if (chunk == head)
42 head = chunk->next;
43
44 if (chunk == tail)
45 tail = chunk->prev;
46
47 if (free_chunk_head == chunk)
48 free_chunk_head = chunk->next;
49
50 if (free_chunk_tail == chunk)
51 free_chunk_tail = chunk->prev;
52
53 if (chunk->free)
54 free_chunk_count--;
55
56 chunk->free = false;
57 return chunk->ptr;
58 }
59
60 static void
61 reduce_brk ()
62 {
63 if (free_chunk_count <= 3)
64 return;
65
66 struct malloc_chunk *chunk = free_chunk_tail;
67 intptr_t lowest_brk = 0;
68 void *b = brk ();
69
70 while (chunk != NULL)
71 {
72 if (tail >= chunk || !chunk->free
73 || (lowest_brk != 0 && lowest_brk < (intptr_t) chunk)
74 || (intptr_t) b < (intptr_t) chunk)
75 {
76 chunk = chunk->prev;
77 continue;
78 }
79
80 if (chunk->prev != NULL)
81 chunk->prev->next = chunk->next;
82
83 if (chunk->next != NULL)
84 chunk->next->prev = chunk->prev;
85
86 if (chunk == free_chunk_head)
87 free_chunk_head = chunk->next;
88
89 if (chunk == free_chunk_tail)
90 free_chunk_tail = chunk->prev;
91
92 struct malloc_chunk *prev = chunk->prev;
93 lowest_brk = (intptr_t) chunk;
94 chunk = prev;
95 }
96
97 if (lowest_brk == 0)
98 return;
99
100 if (sbrk ((intptr_t) lowest_brk) == (void *) -1)
101 {
102 printf ("reduce_brk(): sbrk failed\n");
103 abort ();
104 }
105 }
106
107 void *
108 malloc (size_t size)
109 {
110 reduce_brk ();
111
112 if (size == 0)
113 return NULL;
114
115 if (free_chunk_head != NULL && free_chunk_head->free
116 && free_chunk_head->size >= size)
117 return unfree (free_chunk_head);
118
119 if (free_chunk_tail != NULL && free_chunk_tail->free
120 && free_chunk_tail->size >= size)
121 return unfree (free_chunk_tail);
122
123 struct malloc_chunk *chunk = free_chunk_tail;
124
125 while (chunk != NULL)
126 {
127 if (chunk->free && chunk->size >= size)
128 return unfree (chunk);
129
130 chunk = chunk->prev;
131 }
132
133 if (init_mbrk == NULL)
134 malloc_init ();
135
136 size_t mc_size = sizeof (struct malloc_chunk);
137 void *b = brk ();
138 intptr_t new_ptr = (intptr_t) (((unsigned char *) b) + size + mc_size);
139
140 if (sbrk (new_ptr) == (void *) -1)
141 return NULL;
142
143 chunk = (struct malloc_chunk *) b;
144 chunk->size = size;
145 chunk->ptr = (void *) (((unsigned char *) b) + mc_size);
146 chunk->next = NULL;
147 chunk->prev = tail;
148 chunk->free = false;
149
150 tail = chunk;
151
152 if (head == NULL)
153 head = chunk;
154
155 return chunk->ptr;
156 }
157
158 static void __noreturn
159 invalid_ptr (const char *func)
160 {
161 printf ("%s(): invalid pointer\n", func);
162 abort ();
163 }
164
165 static void __noreturn
166 double_free (void *ptr, size_t size)
167 {
168 printf ("free(): double free detected: %p (block size %zu)\n", ptr, size);
169 abort ();
170 }
171
172 void
173 free (void *ptr)
174 {
175 reduce_brk ();
176
177 size_t mc_size = sizeof (struct malloc_chunk);
178 struct malloc_chunk *chunk
179 = (struct malloc_chunk *) (((unsigned char *) ptr) - mc_size);
180
181 if (chunk == NULL)
182 invalid_ptr (__func__);
183
184 if (chunk->ptr != ptr)
185 invalid_ptr (__func__);
186
187 if (chunk->free)
188 double_free (chunk->ptr, chunk->size);
189
190 free_chunk_count++;
191 chunk->free = true;
192
193 if (chunk->prev != NULL)
194 chunk->prev->next = chunk->next;
195
196 if (chunk->next != NULL)
197 chunk->next->prev = chunk->prev;
198
199 if (chunk == head)
200 head = chunk->next;
201
202 if (chunk == tail)
203 tail = chunk->prev;
204
205 if (free_chunk_head == NULL)
206 {
207 free_chunk_head = chunk;
208 free_chunk_tail = chunk;
209 chunk->next = NULL;
210 chunk->prev = NULL;
211 }
212 else
213 {
214 free_chunk_tail->next = chunk;
215 chunk->prev = free_chunk_tail;
216 chunk->next = NULL;
217 free_chunk_tail = chunk;
218 }
219 }
220
221 void
222 bzero (void *ptr, size_t size)
223 {
224 for (size_t i = 0; i < size; i++)
225 ((unsigned char *) ptr)[i] = 0;
226 }
227
228 void *
229 calloc (size_t nmemb, size_t size)
230 {
231 size_t total_size = nmemb * size;
232 void *ptr = malloc (total_size);
233
234 if (ptr == NULL)
235 return NULL;
236
237 bzero (ptr, total_size);
238 return ptr;
239 }
240
241 void *
242 realloc (void *ptr, size_t size)
243 {
244 if (ptr == NULL)
245 return malloc (size);
246
247 size_t mc_size = sizeof (struct malloc_chunk);
248 struct malloc_chunk *chunk
249 = (struct malloc_chunk *) (((unsigned char *) ptr) - mc_size);
250
251 if (chunk == NULL)
252 invalid_ptr (__func__);
253
254 if (chunk->ptr != ptr)
255 invalid_ptr (__func__);
256
257 if (chunk->size >= size)
258 return ptr;
259
260 if (tail == chunk)
261 {
262 reduce_brk ();
263
264 size_t new_size = size - chunk->size;
265 void *b = brk ();
266 intptr_t new_ptr = (intptr_t) (((unsigned char *) b) + new_size);
267
268 if (sbrk (new_ptr) == (void *) -1)
269 return NULL;
270
271 chunk->size = size;
272 return ptr;
273 }
274
275 void *new_ptr = malloc (size);
276
277 if (new_ptr == NULL)
278 return NULL;
279
280 for (size_t i = 0; i < chunk->size; i++)
281 ((unsigned char *) new_ptr)[i] = ((unsigned char *) ptr)[i];
282
283 free (ptr);
284 return new_ptr;
285 }
286
287 void
288 __plibc_heap_reset (void)
289 {
290 if (init_mbrk == NULL)
291 return;
292
293 if (sbrk ((intptr_t) init_mbrk) == (void *) -1)
294 {
295 printf ("__plibc_heap_reset(): sbrk failed\n");
296 abort ();
297 }
298
299 head = NULL;
300 tail = NULL;
301 free_chunk_head = NULL;
302 free_chunk_tail = NULL;
303 free_chunk_count = 0;
304 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26