]>
Commit | Line | Data |
---|---|---|
c074abee DHW |
1 | |
2 | /* gmalloc.c - THIS FILE IS AUTOMAGICALLY GENERATED SO DON'T EDIT IT. */ | |
3 | ||
4 | /* Single-file skeleton for GNU malloc. | |
5 | Copyright 1989 Free Software Foundation | |
6 | Written May 1989 by Mike Haertel. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 1, or (at your option) | |
11 | any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | ||
22 | The author may be reached (Email) at the address [email protected], | |
23 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
24 | ||
25 | #define __ONEFILE | |
26 | ||
27 | /* DO NOT DELETE THIS LINE -- ansidecl.h INSERTED HERE. */ | |
28 | /* Copyright (C) 1989 Free Software Foundation, Inc. | |
29 | This file is part of the GNU C Library. | |
30 | ||
31 | The GNU C Library is free software; you can redistribute it and/or modify | |
32 | it under the terms of the GNU General Public License as published by | |
33 | the Free Software Foundation; either version 1, or (at your option) | |
34 | any later version. | |
35 | ||
36 | The GNU C Library is distributed in the hope that it will be useful, | |
37 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
38 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39 | GNU General Public License for more details. | |
40 | ||
41 | You should have received a copy of the GNU General Public License | |
42 | along with the GNU C Library; see the file COPYING. If not, write to | |
43 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
44 | ||
45 | /* ANSI and traditional C compatibility macros | |
46 | ||
47 | ANSI C is assumed if __STDC__ is #defined. | |
48 | ||
49 | Macros | |
50 | PTR - Generic pointer type | |
51 | LONG_DOUBLE - `long double' type | |
52 | CONST - `const' keyword | |
53 | VOLATILE - `volatile' keyword | |
54 | SIGNED - `signed' keyword | |
55 | PTRCONST - Generic const pointer (void *const) | |
56 | ||
57 | EXFUN(name, prototype) - declare external function NAME | |
58 | with prototype PROTOTYPE | |
59 | DEFUN(name, arglist, args) - define function NAME with | |
60 | args ARGLIST of types in ARGS | |
61 | DEFUN_VOID(name) - define function NAME with no args | |
62 | AND - argument separator for ARGS | |
63 | NOARGS - null arglist | |
64 | DOTS - `...' in args | |
65 | ||
66 | For example: | |
67 | extern int EXFUN(printf, (CONST char *format DOTS)); | |
68 | int DEFUN(fprintf, (stream, format), | |
69 | FILE *stream AND CONST char *format DOTS) { ... } | |
70 | void DEFUN_VOID(abort) { ... } | |
71 | */ | |
72 | ||
73 | #ifndef _ANSIDECL_H | |
74 | ||
75 | #define _ANSIDECL_H 1 | |
76 | ||
77 | ||
78 | /* Every source file includes this file, | |
79 | so they will all get the switch for lint. */ | |
80 | /* LINTLIBRARY */ | |
81 | ||
82 | ||
83 | #ifdef __STDC__ | |
84 | ||
85 | #define PTR void * | |
86 | #define PTRCONST void *CONST | |
87 | #define LONG_DOUBLE long double | |
88 | ||
89 | #define AND , | |
90 | #define NOARGS void | |
91 | #define CONST const | |
92 | #define VOLATILE volatile | |
93 | #define SIGNED signed | |
94 | #define DOTS , ... | |
95 | ||
96 | #define EXFUN(name, proto) name proto | |
97 | #define DEFUN(name, arglist, args) name(args) | |
98 | #define DEFUN_VOID(name) name(NOARGS) | |
99 | ||
100 | #else /* Not ANSI C. */ | |
101 | ||
102 | #define PTR char * | |
103 | #define PTRCONST PTR | |
104 | #define LONG_DOUBLE double | |
105 | ||
106 | #define AND ; | |
107 | #define NOARGS | |
108 | #define CONST | |
109 | #define VOLATILE | |
110 | #define SIGNED | |
111 | #define DOTS | |
112 | ||
113 | #define EXFUN(name, proto) name() | |
114 | #define DEFUN(name, arglist, args) name arglist args; | |
115 | #define DEFUN_VOID(name) name() | |
116 | ||
117 | #endif /* ANSI C. */ | |
118 | ||
119 | ||
120 | #endif /* ansidecl.h */ | |
121 | ||
122 | #ifdef __STDC__ | |
123 | #include <limits.h> | |
124 | #else | |
125 | /* DO NOT DELETE THIS LINE -- limits.h INSERTED HERE. */ | |
126 | /* Number of bits in a `char'. */ | |
127 | #define CHAR_BIT 8 | |
128 | ||
129 | /* No multibyte characters supported yet. */ | |
130 | #define MB_LEN_MAX 1 | |
131 | ||
132 | /* Minimum and maximum values a `signed char' can hold. */ | |
133 | #define SCHAR_MIN -128 | |
134 | #define SCHAR_MAX 127 | |
135 | ||
136 | /* Maximum value an `unsigned char' can hold. (Minimum is 0). */ | |
137 | #define UCHAR_MAX 255U | |
138 | ||
139 | /* Minimum and maximum values a `char' can hold. */ | |
140 | #ifdef __CHAR_UNSIGNED__ | |
141 | #define CHAR_MIN 0 | |
142 | #define CHAR_MAX 255U | |
143 | #else | |
144 | #define CHAR_MIN -128 | |
145 | #define CHAR_MAX 127 | |
146 | #endif | |
147 | ||
148 | /* Minimum and maximum values a `signed short int' can hold. */ | |
149 | #define SHRT_MIN -32768 | |
150 | #define SHRT_MAX 32767 | |
151 | ||
152 | /* Maximum value an `unsigned short int' can hold. (Minimum is 0). */ | |
153 | #define USHRT_MAX 65535U | |
154 | ||
155 | /* Minimum and maximum values a `signed int' can hold. */ | |
156 | #define INT_MIN -2147483648 | |
157 | #define INT_MAX 2147483647 | |
158 | ||
159 | /* Maximum value an `unsigned int' can hold. (Minimum is 0). */ | |
160 | #define UINT_MAX 4294967295U | |
161 | ||
162 | /* Minimum and maximum values a `signed long int' can hold. | |
163 | (Same as `int'). */ | |
164 | #define LONG_MIN (-LONG_MAX-1) | |
165 | #define LONG_MAX 2147483647 | |
166 | ||
167 | /* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ | |
168 | #define ULONG_MAX 4294967295U | |
169 | #endif | |
170 | ||
171 | #ifdef __STDC__ | |
172 | #include <stddef.h> | |
173 | #else | |
174 | /* DO NOT DELETE THIS LINE -- stddef.h INSERTED HERE. */ | |
175 | #ifndef _STDDEF_H | |
176 | #define _STDDEF_H | |
177 | ||
178 | /* Signed type of difference of two pointers. */ | |
179 | ||
180 | typedef long ptrdiff_t; | |
181 | ||
182 | /* Unsigned type of `sizeof' something. */ | |
183 | ||
184 | #ifndef _SIZE_T /* in case <sys/types.h> has defined it. */ | |
185 | #define _SIZE_T | |
186 | typedef unsigned long size_t; | |
187 | #endif /* _SIZE_T */ | |
188 | ||
189 | /* A null pointer constant. */ | |
190 | ||
191 | #undef NULL /* in case <stdio.h> has defined it. */ | |
192 | #define NULL 0 | |
193 | ||
194 | /* Offset of member MEMBER in a struct of type TYPE. */ | |
195 | ||
196 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | |
197 | ||
198 | #endif /* _STDDEF_H */ | |
199 | #endif | |
200 | ||
201 | /* DO NOT DELETE THIS LINE -- stdlib.h INSERTED HERE. */ | |
202 | /* Fake stdlib.h supplying the stuff needed by malloc. */ | |
203 | ||
204 | #ifndef __ONEFILE | |
205 | #include <stddef.h> | |
206 | #endif | |
207 | ||
208 | extern void EXFUN(abort, (void)); | |
209 | extern void EXFUN(free, (PTR)); | |
210 | extern PTR EXFUN(malloc, (size_t)); | |
211 | extern PTR EXFUN(realloc, (PTR, size_t)); | |
212 | ||
213 | /* DO NOT DELETE THIS LINE -- string.h INSERTED HERE. */ | |
214 | /* Fake string.h supplying stuff used by malloc. */ | |
215 | #ifndef __ONEFILE | |
216 | #include <stddef.h> | |
217 | #endif | |
218 | ||
219 | extern PTR EXFUN(memcpy, (PTR, PTR, size_t)); | |
220 | extern PTR EXFUN(memset, (PTR, int, size_t)); | |
221 | #define memmove memcpy | |
222 | ||
223 | #define _MALLOC_INTERNAL | |
224 | /* DO NOT DELETE THIS LINE -- malloc.h INSERTED HERE. */ | |
225 | /* Declarations for `malloc' and friends. | |
226 | Copyright 1990 Free Software Foundation | |
227 | Written May 1989 by Mike Haertel. | |
228 | ||
229 | This program is free software; you can redistribute it and/or modify | |
230 | it under the terms of the GNU General Public License as published by | |
231 | the Free Software Foundation; either version 1, or (at your option) | |
232 | any later version. | |
233 | ||
234 | This program is distributed in the hope that it will be useful, | |
235 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
236 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
237 | GNU General Public License for more details. | |
238 | ||
239 | You should have received a copy of the GNU General Public License | |
240 | along with this program; if not, write to the Free Software | |
241 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
242 | ||
243 | The author may be reached (Email) at the address mike@@ai.mit.edu, | |
244 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
245 | ||
246 | #ifndef _MALLOC_H | |
247 | ||
248 | #define _MALLOC_H 1 | |
249 | ||
250 | #ifndef __ONEFILE | |
251 | #define __need_NULL | |
252 | #define __need_size_t | |
253 | #define __need_ptrdiff_t | |
254 | #include <stddef.h> | |
255 | #endif | |
256 | ||
257 | #ifdef _MALLOC_INTERNAL | |
258 | ||
259 | #ifndef __ONEFILE | |
260 | #include <limits.h> | |
261 | #endif | |
262 | ||
263 | /* The allocator divides the heap into blocks of fixed size; large | |
264 | requests receive one or more whole blocks, and small requests | |
265 | receive a fragment of a block. Fragment sizes are powers of two, | |
266 | and all fragments of a block are the same size. When all the | |
267 | fragments in a block have been freed, the block itself is freed. */ | |
268 | #define INT_BIT (CHAR_BIT * sizeof(int)) | |
269 | #define BLOCKLOG (INT_BIT > 16 ? 12 : 9) | |
270 | #define BLOCKSIZE (1 << BLOCKLOG) | |
271 | #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) | |
272 | ||
273 | /* Determine the amount of memory spanned by the initial heap table | |
274 | (not an absolute limit). */ | |
275 | #define HEAP (INT_BIT > 16 ? 4194304 : 65536) | |
276 | ||
277 | /* Number of contiguous free blocks allowed to build up at the end of | |
278 | memory before they will be returned to the system. */ | |
279 | #define FINAL_FREE_BLOCKS 8 | |
280 | ||
281 | /* Where to start searching the free list when looking for new memory. | |
282 | The two possible values are 0 and _heapindex. Starting at 0 seems | |
283 | to reduce total memory usage, while starting at _heapindex seems to | |
284 | run faster. */ | |
285 | #define MALLOC_SEARCH_START _heapindex | |
286 | ||
287 | /* Data structure giving per-block information. */ | |
288 | typedef union | |
289 | { | |
290 | /* Heap information for a busy block. */ | |
291 | struct | |
292 | { | |
293 | /* Zero for a large block, or positive giving the | |
294 | logarithm to the base two of the fragment size. */ | |
295 | int type; | |
296 | union | |
297 | { | |
298 | struct | |
299 | { | |
300 | size_t nfree; /* Free fragments in a fragmented block. */ | |
301 | size_t first; /* First free fragment of the block. */ | |
302 | } frag; | |
303 | /* Size (in blocks) of a large cluster. */ | |
304 | size_t size; | |
305 | } info; | |
306 | } busy; | |
307 | /* Heap information for a free block (that may be the first of | |
308 | a free cluster). */ | |
309 | struct | |
310 | { | |
311 | size_t size; /* Size (in blocks) of a free cluster. */ | |
312 | size_t next; /* Index of next free cluster. */ | |
313 | size_t prev; /* Index of previous free cluster. */ | |
314 | } free; | |
315 | } malloc_info; | |
316 | ||
317 | /* Pointer to first block of the heap. */ | |
318 | extern char *_heapbase; | |
319 | ||
320 | /* Table indexed by block number giving per-block information. */ | |
321 | extern malloc_info *_heapinfo; | |
322 | ||
323 | /* Address to block number and vice versa. */ | |
324 | #define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) | |
325 | #define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase)) | |
326 | ||
327 | /* Current search index for the heap table. */ | |
328 | extern size_t _heapindex; | |
329 | ||
330 | /* Limit of valid info table indices. */ | |
331 | extern size_t _heaplimit; | |
332 | ||
333 | /* Doubly linked lists of free fragments. */ | |
334 | struct list | |
335 | { | |
336 | struct list *next; | |
337 | struct list *prev; | |
338 | }; | |
339 | ||
340 | /* Free list headers for each fragment size. */ | |
341 | extern struct list _fraghead[]; | |
342 | ||
343 | /* Instrumentation. */ | |
344 | extern size_t _chunks_used; | |
345 | extern size_t _bytes_used; | |
346 | extern size_t _chunks_free; | |
347 | extern size_t _bytes_free; | |
348 | ||
349 | /* Internal version of free() used in morecore(). */ | |
350 | extern void EXFUN(__free, (PTR __ptr)); | |
351 | ||
352 | #endif /* _MALLOC_INTERNAL. */ | |
353 | ||
354 | /* Underlying allocation function; successive calls should | |
355 | return contiguous pieces of memory. */ | |
356 | extern PTR EXFUN((*__morecore), (ptrdiff_t __size)); | |
357 | ||
358 | /* Default value of previous. */ | |
359 | extern PTR EXFUN(__default_morecore, (ptrdiff_t __size)); | |
360 | ||
361 | /* Flag whether malloc has been called. */ | |
362 | extern int __malloc_initialized; | |
363 | ||
364 | /* Hooks for debugging versions. */ | |
365 | extern void EXFUN((*__free_hook), (PTR __ptr)); | |
366 | extern PTR EXFUN((*__malloc_hook), (size_t __size)); | |
367 | extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size)); | |
368 | ||
369 | /* Activate a standard collection of debugging hooks. */ | |
370 | extern void EXFUN(mcheck, (void EXFUN((*func), (void)))); | |
371 | ||
372 | /* Statistics available to the user. */ | |
373 | struct mstats | |
374 | { | |
375 | size_t bytes_total; /* Total size of the heap. */ | |
376 | size_t chunks_used; /* Chunks allocated by the user. */ | |
377 | size_t bytes_used; /* Byte total of user-allocated chunks. */ | |
378 | size_t chunks_free; /* Chunks in the free list. */ | |
379 | size_t bytes_free; /* Byte total of chunks in the free list. */ | |
380 | }; | |
381 | ||
382 | /* Pick up the current statistics. */ | |
383 | extern struct mstats EXFUN(mstats, (NOARGS)); | |
384 | ||
385 | #endif /* malloc.h */ | |
386 | ||
387 | /* DO NOT DELETE THIS LINE -- free.c INSERTED HERE. */ | |
388 | /* Free a block of memory allocated by `malloc'. | |
389 | Copyright 1990 Free Software Foundation | |
390 | Written May 1989 by Mike Haertel. | |
391 | ||
392 | This program is free software; you can redistribute it and/or modify | |
393 | it under the terms of the GNU General Public License as published by | |
394 | the Free Software Foundation; either version 1, or (at your option) | |
395 | any later version. | |
396 | ||
397 | This program is distributed in the hope that it will be useful, | |
398 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
399 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
400 | GNU General Public License for more details. | |
401 | ||
402 | You should have received a copy of the GNU General Public License | |
403 | along with this program; if not, write to the Free Software | |
404 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
405 | ||
406 | The author may be reached (Email) at the address [email protected], | |
407 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
408 | ||
409 | #ifndef __ONEFILE | |
410 | #include "ansidecl.h" | |
411 | #include <stddef.h> | |
412 | #include <stdlib.h> | |
413 | ||
414 | #define _MALLOC_INTERNAL | |
415 | #include "malloc.h" | |
416 | #endif /* __ONEFILE */ | |
417 | ||
418 | /* Debugging hook for free. */ | |
419 | void EXFUN((*__free_hook), (PTR __ptr)); | |
420 | ||
421 | /* Return memory to the heap. Like free() but don't call a __free_hook | |
422 | if there is one. */ | |
423 | void | |
424 | DEFUN(__free, (ptr), PTR ptr) | |
425 | { | |
426 | int type; | |
427 | size_t block, blocks; | |
428 | register size_t i; | |
429 | struct list *prev, *next; | |
430 | ||
431 | block = BLOCK(ptr); | |
432 | ||
433 | type = _heapinfo[block].busy.type; | |
434 | switch (type) | |
435 | { | |
436 | case 0: | |
437 | /* Get as many statistics as early as we can. */ | |
438 | --_chunks_used; | |
439 | _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; | |
440 | _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; | |
441 | ||
442 | /* Find the free cluster previous to this one in the free list. | |
443 | Start searching at the last block referenced; this may benefit | |
444 | programs with locality of allocation. */ | |
445 | i = _heapindex; | |
446 | if (i > block) | |
447 | while (i > block) | |
448 | i = _heapinfo[i].free.prev; | |
449 | else | |
450 | { | |
451 | do | |
452 | i = _heapinfo[i].free.next; | |
453 | while (i > 0 && i < block); | |
454 | i = _heapinfo[i].free.prev; | |
455 | } | |
456 | ||
457 | /* Determine how to link this block into the free list. */ | |
458 | if (block == i + _heapinfo[i].free.size) | |
459 | { | |
460 | /* Coalesce this block with its predecessor. */ | |
461 | _heapinfo[i].free.size += _heapinfo[block].busy.info.size; | |
462 | block = i; | |
463 | } | |
464 | else | |
465 | { | |
466 | /* Really link this block back into the free list. */ | |
467 | _heapinfo[block].free.size = _heapinfo[block].busy.info.size; | |
468 | _heapinfo[block].free.next = _heapinfo[i].free.next; | |
469 | _heapinfo[block].free.prev = i; | |
470 | _heapinfo[i].free.next = block; | |
471 | _heapinfo[_heapinfo[block].free.next].free.prev = block; | |
472 | ++_chunks_free; | |
473 | } | |
474 | ||
475 | /* Now that the block is linked in, see if we can coalesce it | |
476 | with its successor (by deleting its successor from the list | |
477 | and adding in its size). */ | |
478 | if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) | |
479 | { | |
480 | _heapinfo[block].free.size | |
481 | += _heapinfo[_heapinfo[block].free.next].free.size; | |
482 | _heapinfo[block].free.next | |
483 | = _heapinfo[_heapinfo[block].free.next].free.next; | |
484 | _heapinfo[_heapinfo[block].free.next].free.prev = block; | |
485 | --_chunks_free; | |
486 | } | |
487 | ||
488 | /* Now see if we can return stuff to the system. */ | |
489 | blocks = _heapinfo[block].free.size; | |
490 | if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit | |
491 | && (*__morecore)(0) == ADDRESS(block + blocks)) | |
492 | { | |
493 | register size_t bytes = blocks * BLOCKSIZE; | |
494 | _heaplimit -= blocks; | |
495 | (*__morecore)(- bytes); | |
496 | _heapinfo[_heapinfo[block].free.prev].free.next | |
497 | = _heapinfo[block].free.next; | |
498 | _heapinfo[_heapinfo[block].free.next].free.prev | |
499 | = _heapinfo[block].free.prev; | |
500 | block = _heapinfo[block].free.prev; | |
501 | --_chunks_free; | |
502 | _bytes_free -= bytes; | |
503 | } | |
504 | ||
505 | /* Set the next search to begin at this block. */ | |
506 | _heapindex = block; | |
507 | break; | |
508 | ||
509 | default: | |
510 | /* Do some of the statistics. */ | |
511 | --_chunks_used; | |
512 | _bytes_used -= 1 << type; | |
513 | ++_chunks_free; | |
514 | _bytes_free += 1 << type; | |
515 | ||
516 | /* Get the address of the first free fragment in this block. */ | |
517 | prev = (struct list *) ((char *) ADDRESS(block) + | |
518 | (_heapinfo[block].busy.info.frag.first << type)); | |
519 | ||
520 | if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) | |
521 | { | |
522 | /* If all fragments of this block are free, remove them | |
523 | from the fragment list and free the whole block. */ | |
524 | next = prev; | |
525 | for (i = 1; i < BLOCKSIZE >> type; ++i) | |
526 | next = next->next; | |
527 | prev->prev->next = next; | |
528 | if (next != NULL) | |
529 | next->prev = prev->prev; | |
530 | _heapinfo[block].busy.type = 0; | |
531 | _heapinfo[block].busy.info.size = 1; | |
532 | ||
533 | /* Keep the statistics accurate. */ | |
534 | ++_chunks_used; | |
535 | _bytes_used += BLOCKSIZE; | |
536 | _chunks_free -= BLOCKSIZE >> type; | |
537 | _bytes_free -= BLOCKSIZE; | |
538 | ||
539 | free(ADDRESS(block)); | |
540 | } | |
541 | else if (_heapinfo[block].busy.info.frag.nfree != 0) | |
542 | { | |
543 | /* If some fragments of this block are free, link this | |
544 | fragment into the fragment list after the first free | |
545 | fragment of this block. */ | |
546 | next = (struct list *) ptr; | |
547 | next->next = prev->next; | |
548 | next->prev = prev; | |
549 | prev->next = next; | |
550 | if (next->next != NULL) | |
551 | next->next->prev = next; | |
552 | ++_heapinfo[block].busy.info.frag.nfree; | |
553 | } | |
554 | else | |
555 | { | |
556 | /* No fragments of this block are free, so link this | |
557 | fragment into the fragment list and announce that | |
558 | it is the first free fragment of this block. */ | |
559 | prev = (struct list *) ptr; | |
560 | _heapinfo[block].busy.info.frag.nfree = 1; | |
561 | _heapinfo[block].busy.info.frag.first = (unsigned int) | |
562 | (((char *) ptr - (char *) NULL) % BLOCKSIZE >> type); | |
563 | prev->next = _fraghead[type].next; | |
564 | prev->prev = &_fraghead[type]; | |
565 | prev->prev->next = prev; | |
566 | if (prev->next != NULL) | |
567 | prev->next->prev = prev; | |
568 | } | |
569 | break; | |
570 | } | |
571 | } | |
572 | ||
573 | /* Return memory to the heap. */ | |
574 | void | |
575 | DEFUN(free, (ptr), PTR ptr) | |
576 | { | |
577 | if (ptr == NULL) | |
578 | return; | |
579 | ||
580 | if (__free_hook != NULL) | |
581 | (*__free_hook)(ptr); | |
582 | else | |
583 | __free (ptr); | |
584 | } | |
585 | ||
586 | /* DO NOT DELETE THIS LINE -- malloc.c INSERTED HERE. */ | |
587 | /* Memory allocator `malloc'. | |
588 | Copyright 1990 Free Software Foundation | |
589 | Written May 1989 by Mike Haertel. | |
590 | ||
591 | This program is free software; you can redistribute it and/or modify | |
592 | it under the terms of the GNU General Public License as published by | |
593 | the Free Software Foundation; either version 1, or (at your option) | |
594 | any later version. | |
595 | ||
596 | This program is distributed in the hope that it will be useful, | |
597 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
598 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
599 | GNU General Public License for more details. | |
600 | ||
601 | You should have received a copy of the GNU General Public License | |
602 | along with this program; if not, write to the Free Software | |
603 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
604 | ||
605 | The author may be reached (Email) at the address [email protected], | |
606 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
607 | ||
608 | #ifndef __ONEFILE | |
609 | #include "ansidecl.h" | |
610 | #include <stddef.h> | |
611 | #include <stdlib.h> | |
612 | #include <string.h> | |
613 | ||
614 | #define _MALLOC_INTERNAL | |
615 | #include "malloc.h" | |
616 | #endif /* __ONEFILE */ | |
617 | ||
618 | /* How to really get more memory. */ | |
619 | PTR EXFUN((*__morecore), (ptrdiff_t __size)) = __default_morecore; | |
620 | ||
621 | /* Debugging hook for `malloc'. */ | |
622 | PTR EXFUN((*__malloc_hook), (size_t __size)); | |
623 | ||
624 | /* Pointer to the base of the first block. */ | |
625 | char *_heapbase; | |
626 | ||
627 | /* Block information table. Allocated with align/__free (not malloc/free). */ | |
628 | malloc_info *_heapinfo; | |
629 | ||
630 | /* Number of info entries. */ | |
631 | static size_t heapsize; | |
632 | ||
633 | /* Search index in the info table. */ | |
634 | size_t _heapindex; | |
635 | ||
636 | /* Limit of valid info table indices. */ | |
637 | size_t _heaplimit; | |
638 | ||
639 | /* Free lists for each fragment size. */ | |
640 | struct list _fraghead[BLOCKLOG]; | |
641 | ||
642 | /* Instrumentation. */ | |
643 | size_t _chunks_used; | |
644 | size_t _bytes_used; | |
645 | size_t _chunks_free; | |
646 | size_t _bytes_free; | |
647 | ||
648 | /* Are you experienced? */ | |
649 | int __malloc_initialized; | |
650 | ||
651 | /* Aligned allocation. */ | |
652 | static PTR | |
653 | DEFUN(align, (size), size_t size) | |
654 | { | |
655 | PTR result; | |
656 | unsigned int adj; | |
657 | ||
658 | result = (*__morecore)(size); | |
659 | adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE; | |
660 | if (adj != 0) | |
661 | { | |
662 | adj = BLOCKSIZE - adj; | |
663 | (void) (*__morecore)(adj); | |
664 | result = (char *) result + adj; | |
665 | } | |
666 | return result; | |
667 | } | |
668 | ||
669 | /* Set everything up and remember that we have. */ | |
670 | static int | |
671 | DEFUN_VOID(initialize) | |
672 | { | |
673 | heapsize = HEAP / BLOCKSIZE; | |
674 | _heapinfo = (malloc_info *) align(heapsize * sizeof(malloc_info)); | |
675 | if (_heapinfo == NULL) | |
676 | return 0; | |
677 | memset(_heapinfo, 0, heapsize * sizeof(malloc_info)); | |
678 | _heapinfo[0].free.size = 0; | |
679 | _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; | |
680 | _heapindex = 0; | |
681 | _heapbase = (char *) _heapinfo; | |
682 | __malloc_initialized = 1; | |
683 | return 1; | |
684 | } | |
685 | ||
686 | /* Get neatly aligned memory, initializing or | |
687 | growing the heap info table as necessary. */ | |
688 | static PTR | |
689 | DEFUN(morecore, (size), size_t size) | |
690 | { | |
691 | PTR result; | |
692 | malloc_info *newinfo, *oldinfo; | |
693 | size_t newsize; | |
694 | ||
695 | result = align(size); | |
696 | if (result == NULL) | |
697 | return NULL; | |
698 | ||
699 | /* Check if we need to grow the info table. */ | |
700 | if (BLOCK((char *) result + size) > heapsize) | |
701 | { | |
702 | newsize = heapsize; | |
703 | while (BLOCK((char *) result + size) > newsize) | |
704 | newsize *= 2; | |
705 | newinfo = (malloc_info *) align(newsize * sizeof(malloc_info)); | |
706 | if (newinfo == NULL) | |
707 | { | |
708 | (*__morecore)(- size); | |
709 | return NULL; | |
710 | } | |
711 | memset(newinfo, 0, newsize * sizeof(malloc_info)); | |
712 | memcpy(newinfo, _heapinfo, heapsize * sizeof(malloc_info)); | |
713 | oldinfo = _heapinfo; | |
714 | newinfo[BLOCK(oldinfo)].busy.type = 0; | |
715 | newinfo[BLOCK(oldinfo)].busy.info.size | |
716 | = BLOCKIFY(heapsize * sizeof(malloc_info)); | |
717 | _heapinfo = newinfo; | |
718 | __free(oldinfo); | |
719 | heapsize = newsize; | |
720 | } | |
721 | ||
722 | _heaplimit = BLOCK((char *) result + size); | |
723 | return result; | |
724 | } | |
725 | ||
726 | /* Allocate memory from the heap. */ | |
727 | PTR | |
728 | DEFUN(malloc, (size), size_t size) | |
729 | { | |
730 | PTR result; | |
731 | size_t block, blocks, lastblocks, start; | |
732 | register size_t i; | |
733 | struct list *next; | |
734 | ||
735 | if (size == 0) | |
736 | return NULL; | |
737 | ||
738 | if (__malloc_hook != NULL) | |
739 | return (*__malloc_hook)(size); | |
740 | ||
741 | if (!__malloc_initialized) | |
742 | if (!initialize()) | |
743 | return NULL; | |
744 | ||
745 | if (size < sizeof(struct list)) | |
746 | size = sizeof(struct list); | |
747 | ||
748 | /* Determine the allocation policy based on the request size. */ | |
749 | if (size <= BLOCKSIZE / 2) | |
750 | { | |
751 | /* Small allocation to receive a fragment of a block. | |
752 | Determine the logarithm to base two of the fragment size. */ | |
753 | register size_t log = 1; | |
754 | --size; | |
755 | while ((size /= 2) != 0) | |
756 | ++log; | |
757 | ||
758 | /* Look in the fragment lists for a | |
759 | free fragment of the desired size. */ | |
760 | next = _fraghead[log].next; | |
761 | if (next != NULL) | |
762 | { | |
763 | /* There are free fragments of this size. | |
764 | Pop a fragment out of the fragment list and return it. | |
765 | Update the block's nfree and first counters. */ | |
766 | result = (PTR) next; | |
767 | next->prev->next = next->next; | |
768 | if (next->next != NULL) | |
769 | next->next->prev = next->prev; | |
770 | block = BLOCK(result); | |
771 | if (--_heapinfo[block].busy.info.frag.nfree != 0) | |
772 | _heapinfo[block].busy.info.frag.first = (unsigned int) | |
773 | (((char *) next->next - (char *) NULL) % BLOCKSIZE) >> log; | |
774 | ||
775 | /* Update the statistics. */ | |
776 | ++_chunks_used; | |
777 | _bytes_used += 1 << log; | |
778 | --_chunks_free; | |
779 | _bytes_free -= 1 << log; | |
780 | } | |
781 | else | |
782 | { | |
783 | /* No free fragments of the desired size, so get a new block | |
784 | and break it into fragments, returning the first. */ | |
785 | result = malloc(BLOCKSIZE); | |
786 | if (result == NULL) | |
787 | return NULL; | |
788 | ||
789 | /* Link all fragments but the first into the free list. */ | |
790 | for (i = 1; i < BLOCKSIZE >> log; ++i) | |
791 | { | |
792 | next = (struct list *) ((char *) result + (i << log)); | |
793 | next->next = _fraghead[log].next; | |
794 | next->prev = &_fraghead[log]; | |
795 | next->prev->next = next; | |
796 | if (next->next != NULL) | |
797 | next->next->prev = next; | |
798 | } | |
799 | ||
800 | /* Initialize the nfree and first counters for this block. */ | |
801 | block = BLOCK(result); | |
802 | _heapinfo[block].busy.type = log; | |
803 | _heapinfo[block].busy.info.frag.nfree = i - 1; | |
804 | _heapinfo[block].busy.info.frag.first = i - 1; | |
805 | ||
806 | _chunks_free += (BLOCKSIZE >> log) - 1; | |
807 | _bytes_free += BLOCKSIZE - (1 << log); | |
808 | } | |
809 | } | |
810 | else | |
811 | { | |
812 | /* Large allocation to receive one or more blocks. | |
813 | Search the free list in a circle starting at the last place visited. | |
814 | If we loop completely around without finding a large enough | |
815 | space we will have to get more memory from the system. */ | |
816 | blocks = BLOCKIFY(size); | |
817 | start = block = MALLOC_SEARCH_START; | |
818 | while (_heapinfo[block].free.size < blocks) | |
819 | { | |
820 | block = _heapinfo[block].free.next; | |
821 | if (block == start) | |
822 | { | |
823 | /* Need to get more from the system. Check to see if | |
824 | the new core will be contiguous with the final free | |
825 | block; if so we don't need to get as much. */ | |
826 | block = _heapinfo[0].free.prev; | |
827 | lastblocks = _heapinfo[block].free.size; | |
828 | if (_heaplimit != 0 && block + lastblocks == _heaplimit && | |
829 | (*__morecore)(0) == ADDRESS(block + lastblocks) && | |
830 | (morecore((blocks - lastblocks) * BLOCKSIZE)) != NULL) | |
831 | { | |
832 | _heapinfo[block].free.size = blocks; | |
833 | _bytes_free += (blocks - lastblocks) * BLOCKSIZE; | |
834 | continue; | |
835 | } | |
836 | result = morecore(blocks * BLOCKSIZE); | |
837 | if (result == NULL) | |
838 | return NULL; | |
839 | block = BLOCK(result); | |
840 | _heapinfo[block].busy.type = 0; | |
841 | _heapinfo[block].busy.info.size = blocks; | |
842 | ++_chunks_used; | |
843 | _bytes_used += blocks * BLOCKSIZE; | |
844 | return result; | |
845 | } | |
846 | } | |
847 | ||
848 | /* At this point we have found a suitable free list entry. | |
849 | Figure out how to remove what we need from the list. */ | |
850 | result = ADDRESS(block); | |
851 | if (_heapinfo[block].free.size > blocks) | |
852 | { | |
853 | /* The block we found has a bit left over, | |
854 | so relink the tail end back into the free list. */ | |
855 | _heapinfo[block + blocks].free.size | |
856 | = _heapinfo[block].free.size - blocks; | |
857 | _heapinfo[block + blocks].free.next | |
858 | = _heapinfo[block].free.next; | |
859 | _heapinfo[block + blocks].free.prev | |
860 | = _heapinfo[block].free.prev; | |
861 | _heapinfo[_heapinfo[block].free.prev].free.next | |
862 | = _heapinfo[_heapinfo[block].free.next].free.prev | |
863 | = _heapindex = block + blocks; | |
864 | } | |
865 | else | |
866 | { | |
867 | /* The block exactly matches our requirements, | |
868 | so just remove it from the list. */ | |
869 | _heapinfo[_heapinfo[block].free.next].free.prev | |
870 | = _heapinfo[block].free.prev; | |
871 | _heapinfo[_heapinfo[block].free.prev].free.next | |
872 | = _heapindex = _heapinfo[block].free.next; | |
873 | --_chunks_free; | |
874 | } | |
875 | ||
876 | _heapinfo[block].busy.type = 0; | |
877 | _heapinfo[block].busy.info.size = blocks; | |
878 | ++_chunks_used; | |
879 | _bytes_used += blocks * BLOCKSIZE; | |
880 | _bytes_free -= blocks * BLOCKSIZE; | |
881 | } | |
882 | ||
883 | return result; | |
884 | } | |
885 | ||
886 | /* DO NOT DELETE THIS LINE -- realloc.c INSERTED HERE. */ | |
887 | /* Change the size of a block allocated by `malloc'. | |
888 | Copyright 1990 Free Software Foundation | |
889 | Written May 1989 by Mike Haertel. | |
890 | ||
891 | This program is free software; you can redistribute it and/or modify | |
892 | it under the terms of the GNU General Public License as published by | |
893 | the Free Software Foundation; either version 1, or (at your option) | |
894 | any later version. | |
895 | ||
896 | This program is distributed in the hope that it will be useful, | |
897 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
898 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
899 | GNU General Public License for more details. | |
900 | ||
901 | You should have received a copy of the GNU General Public License | |
902 | along with this program; if not, write to the Free Software | |
903 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
904 | ||
905 | The author may be reached (Email) at the address [email protected], | |
906 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
907 | ||
908 | #ifndef __ONEFILE | |
909 | #include "ansidecl.h" | |
910 | #include <stdlib.h> | |
911 | #include <string.h> | |
912 | ||
913 | #define _MALLOC_INTERNAL | |
914 | #include "malloc.h" | |
915 | #endif /* __ONEFILE */ | |
916 | ||
917 | #define MIN(A, B) ((A) < (B) ? (A) : (B)) | |
918 | ||
919 | /* Debugging hook for realloc. */ | |
920 | PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size)); | |
921 | ||
922 | /* Resize the given region to the new size, returning a pointer | |
923 | to the (possibly moved) region. This is optimized for speed; | |
924 | some benchmarks seem to indicate that greater compactness is | |
925 | achieved by unconditionally allocating and copying to a | |
926 | new region. This module has incestuous knowledge of the | |
927 | internals of both free and malloc. */ | |
928 | PTR | |
929 | DEFUN(realloc, (ptr, size), PTR ptr AND size_t size) | |
930 | { | |
931 | PTR result; | |
932 | int type; | |
933 | size_t block, blocks, oldlimit; | |
934 | ||
935 | if (size == 0) | |
936 | { | |
937 | free(ptr); | |
938 | return NULL; | |
939 | } | |
940 | else if (ptr == NULL) | |
941 | return malloc(size); | |
942 | ||
943 | if (__realloc_hook != NULL) | |
944 | return (*__realloc_hook)(ptr, size); | |
945 | ||
946 | block = BLOCK(ptr); | |
947 | ||
948 | type = _heapinfo[block].busy.type; | |
949 | switch (type) | |
950 | { | |
951 | case 0: | |
952 | /* Maybe reallocate a large block to a small fragment. */ | |
953 | if (size <= BLOCKSIZE / 2) | |
954 | { | |
955 | result = malloc(size); | |
956 | if (result != NULL) | |
957 | { | |
958 | memcpy(result, ptr, size); | |
959 | free(ptr); | |
960 | return result; | |
961 | } | |
962 | } | |
963 | ||
964 | /* The new size is a large allocation as well; | |
965 | see if we can hold it in place. */ | |
966 | blocks = BLOCKIFY(size); | |
967 | if (blocks < _heapinfo[block].busy.info.size) | |
968 | { | |
969 | /* The new size is smaller; return | |
970 | excess memory to the free list. */ | |
971 | _heapinfo[block + blocks].busy.type = 0; | |
972 | _heapinfo[block + blocks].busy.info.size | |
973 | = _heapinfo[block].busy.info.size - blocks; | |
974 | _heapinfo[block].busy.info.size = blocks; | |
975 | free(ADDRESS(block + blocks)); | |
976 | result = ptr; | |
977 | } | |
978 | else if (blocks == _heapinfo[block].busy.info.size) | |
979 | /* No size change necessary. */ | |
980 | result = ptr; | |
981 | else | |
982 | { | |
983 | /* Won't fit, so allocate a new region that will. | |
984 | Free the old region first in case there is sufficient | |
985 | adjacent free space to grow without moving. */ | |
986 | blocks = _heapinfo[block].busy.info.size; | |
987 | /* Prevent free from actually returning memory to the system. */ | |
988 | oldlimit = _heaplimit; | |
989 | _heaplimit = 0; | |
990 | free(ptr); | |
991 | _heaplimit = oldlimit; | |
992 | result = malloc(size); | |
993 | if (result == NULL) | |
994 | { | |
995 | (void) malloc(blocks * BLOCKSIZE); | |
996 | return NULL; | |
997 | } | |
998 | if (ptr != result) | |
999 | memmove(result, ptr, blocks * BLOCKSIZE); | |
1000 | } | |
1001 | break; | |
1002 | ||
1003 | default: | |
1004 | /* Old size is a fragment; type is logarithm | |
1005 | to base two of the fragment size. */ | |
1006 | if (size > 1 << (type - 1) && size <= 1 << type) | |
1007 | /* The new size is the same kind of fragment. */ | |
1008 | result = ptr; | |
1009 | else | |
1010 | { | |
1011 | /* The new size is different; allocate a new space, | |
1012 | and copy the lesser of the new size and the old. */ | |
1013 | result = malloc(size); | |
1014 | if (result == NULL) | |
1015 | return NULL; | |
1016 | memcpy(result, ptr, MIN(size, 1 << type)); | |
1017 | free(ptr); | |
1018 | } | |
1019 | break; | |
1020 | } | |
1021 | ||
1022 | return result; | |
1023 | } | |
1024 | ||
1025 | /* DO NOT DELETE THIS LINE -- unix.c INSERTED HERE. */ | |
1026 | /* unix.c - get more memory with a UNIX system call. | |
1027 | Copyright 1990 Free Software Foundation | |
1028 | Written May 1989 by Mike Haertel. | |
1029 | ||
1030 | This program is free software; you can redistribute it and/or modify | |
1031 | it under the terms of the GNU General Public License as published by | |
1032 | the Free Software Foundation; either version 1, or (at your option) | |
1033 | any later version. | |
1034 | ||
1035 | This program is distributed in the hope that it will be useful, | |
1036 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1037 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1038 | GNU General Public License for more details. | |
1039 | ||
1040 | You should have received a copy of the GNU General Public License | |
1041 | along with this program; if not, write to the Free Software | |
1042 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
1043 | ||
1044 | The author may be reached (Email) at the address [email protected], | |
1045 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
1046 | ||
1047 | #ifndef __ONEFILE | |
1048 | #include "ansidecl.h" | |
1049 | #include <stddef.h> | |
1050 | ||
1051 | #define _MALLOC_INTERNAL | |
1052 | #include "malloc.h" | |
1053 | #endif /* __ONEFILE */ | |
1054 | ||
1055 | extern PTR EXFUN(sbrk, (ptrdiff_t size)); | |
1056 | ||
1057 | PTR | |
1058 | DEFUN(__default_morecore, (size), ptrdiff_t size) | |
1059 | { | |
1060 | PTR result; | |
1061 | ||
1062 | result = sbrk(size); | |
1063 | if (result == (PTR) -1) | |
1064 | return NULL; | |
1065 | return result; | |
1066 | } | |
1067 | ||
1068 | #define __getpagesize getpagesize | |
1069 | /* DO NOT DELETE THIS LINE -- valloc.c INSERTED HERE. */ | |
1070 | /* Allocate memory on a page boundary. | |
1071 | Copyright 1990 Free Software Foundation | |
1072 | Written May 1989 by Mike Haertel. | |
1073 | ||
1074 | This program is free software; you can redistribute it and/or modify | |
1075 | it under the terms of the GNU General Public License as published by | |
1076 | the Free Software Foundation; either version 1, or (at your option) | |
1077 | any later version. | |
1078 | ||
1079 | This program is distributed in the hope that it will be useful, | |
1080 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1081 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1082 | GNU General Public License for more details. | |
1083 | ||
1084 | You should have received a copy of the GNU General Public License | |
1085 | along with this program; if not, write to the Free Software | |
1086 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
1087 | ||
1088 | The author may be reached (Email) at the address [email protected], | |
1089 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | |
1090 | ||
1091 | #ifndef __ONEFILE | |
1092 | #include "ansidecl.h" | |
1093 | #include <stdlib.h> | |
1094 | #endif /* __ONEFILE */ | |
1095 | ||
1096 | extern size_t EXFUN(__getpagesize, (NOARGS)); | |
1097 | ||
1098 | static size_t pagesize; | |
1099 | ||
1100 | PTR | |
1101 | DEFUN(valloc, (size), size_t size) | |
1102 | { | |
1103 | PTR result; | |
1104 | unsigned int adj; | |
1105 | ||
1106 | if (pagesize == 0) | |
1107 | pagesize = __getpagesize(); | |
1108 | ||
1109 | result = malloc(size + pagesize); | |
1110 | if (result == NULL) | |
1111 | return NULL; | |
1112 | adj = (unsigned int) ((char *) result - (char *) NULL) % pagesize; | |
1113 | if (adj != 0) | |
1114 | result = (char *) result + pagesize - adj; | |
1115 | return result; | |
1116 | } |