Mercurial > hg > xemacs-beta
comparison src/gmalloc.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 9ee227acff29 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Synched up with: Not synched up with FSF 19.28, even though I | |
2 thought I did so. */ | |
3 | |
4 /* Get the configuration files if we're being compiled for Emacs. */ | |
5 #ifdef emacs | |
6 # include <config.h> | |
7 # include "getpagesize.h" | |
8 # ifndef HAVE_CONFIG_H | |
9 # define HAVE_CONFIG_H | |
10 # endif | |
11 #endif | |
12 | |
13 #if defined (__STDC__) && !defined (STDC_HEADERS) | |
14 /* The ANSI standard says that defining __STDC__ to a non-zero value means | |
15 that the compiler conforms to that standard. The standard requires | |
16 certain header files and library functions to be present. Therefore, | |
17 if your compiler defines __STDC__ to non-0 but does not have ANSI headers | |
18 and the ANSI library routines, then your compiler is buggy. Conversely, | |
19 an ANSI-conforming environment (which has both the ANSI headers and | |
20 library routines, i.e., stdlib.h and `memmove') does not necessarily | |
21 define the STDC_HEADERS flag. Lucid Emacs requires an ANSI compiler. | |
22 Therefore, there is no need to consult the abominable STDC_HEADERS flag. | |
23 -- jwz | |
24 */ | |
25 # define STDC_HEADERS | |
26 #endif | |
27 | |
28 #define __const const | |
29 | |
30 | |
31 /* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */ | |
32 /* Bwaa-haa-haa! Not a chance that this is actually true! */ | |
33 | |
34 #define _MALLOC_INTERNAL | |
35 | |
36 /* The malloc headers and source files from the C library follow here. */ | |
37 | |
38 /* Declarations for `malloc' and friends. | |
39 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. | |
40 Written May 1989 by Mike Haertel. | |
41 | |
42 This library is free software; you can redistribute it and/or | |
43 modify it under the terms of the GNU Library General Public License as | |
44 published by the Free Software Foundation; either version 2 of the | |
45 License, or (at your option) any later version. | |
46 | |
47 This library is distributed in the hope that it will be useful, | |
48 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
49 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
50 Library General Public License for more details. | |
51 | |
52 You should have received a copy of the GNU General Public License | |
53 along with this library; see the file COPYING. If not, write to | |
54 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
55 Boston, MA 02111-1307, USA. | |
56 | |
57 The author may be reached (Email) at the address mike@ai.mit.edu, | |
58 or (US mail) as Mike Haertel c/o Free Software Foundation, Inc. */ | |
59 | |
60 #ifndef _MALLOC_H | |
61 | |
62 #define _MALLOC_H 1 | |
63 | |
64 #ifdef _MALLOC_INTERNAL | |
65 | |
66 #ifdef HAVE_CONFIG_H | |
67 #include <config.h> | |
68 #endif | |
69 | |
70 #if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG) | |
71 #include <string.h> | |
72 #else | |
73 #ifndef memset | |
74 #define memset(s, zero, n) bzero ((s), (n)) | |
75 #endif | |
76 #ifndef memcpy | |
77 #define memcpy(d, s, n) bcopy ((s), (d), (n)) | |
78 #endif | |
79 #endif | |
80 | |
81 #if defined(__GNU_LIBRARY__) || defined(__STDC__) | |
82 #include <limits.h> | |
83 #else | |
84 #define CHAR_BIT 8 | |
85 #endif | |
86 | |
87 #ifdef HAVE_UNISTD_H | |
88 #include <unistd.h> | |
89 #endif | |
90 | |
91 #endif /* _MALLOC_INTERNAL. */ | |
92 | |
93 | |
94 #ifdef __cplusplus | |
95 extern "C" | |
96 { | |
97 #endif | |
98 | |
99 /* #### XEmacs change for Solaris */ | |
100 #if defined (__cplusplus) || (defined (__STDC__) && __STDC__) || \ | |
101 (defined (__STDC__) && defined (SOLARIS2)) | |
102 #undef __P | |
103 #define __P(args) args | |
104 #undef __ptr_t | |
105 #define __ptr_t void * | |
106 #else /* Not C++ or ANSI C. */ | |
107 #undef __P | |
108 #define __P(args) () | |
109 #undef const | |
110 #define const | |
111 #undef __ptr_t | |
112 #define __ptr_t char * | |
113 #endif /* C++ or ANSI C. */ | |
114 | |
115 #ifdef __STDC__ | |
116 #include <stddef.h> | |
117 #define __malloc_size_t size_t | |
118 #else | |
119 #ifdef OSF1 /* from grunwald@foobar.cs.colorado.edu */ | |
120 #define __malloc_size_t unsigned long | |
121 #else | |
122 #define __malloc_size_t unsigned int | |
123 #endif | |
124 #endif | |
125 | |
126 #ifndef NULL | |
127 #define NULL 0 | |
128 #endif | |
129 | |
130 /* XEmacs: I thought this should be int under SunOS, but that | |
131 apparently fails. Curses on all this shit. */ | |
132 #define __free_ret_t void | |
133 | |
134 /* XEmacs: I tried commenting these out and including stdlib.h, | |
135 but that fails badly. Urk! This sucks. */ | |
136 /* Allocate SIZE bytes of memory. */ | |
137 extern __ptr_t malloc __P ((size_t __size)); | |
138 /* Re-allocate the previously allocated block | |
139 in __ptr_t, making the new block SIZE bytes long. */ | |
140 extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size)); | |
141 /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ | |
142 extern __ptr_t calloc __P ((size_t __nmemb, size_t __size)); | |
143 /* Free a block allocated by `malloc', `realloc' or `calloc'. */ | |
144 extern __free_ret_t free __P ((__ptr_t __ptr)); | |
145 | |
146 /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ | |
147 extern __ptr_t memalign __P ((size_t __alignment, size_t __size)); | |
148 | |
149 /* Allocate SIZE bytes on a page boundary. */ | |
150 extern __ptr_t valloc __P ((size_t __size)); | |
151 | |
152 | |
153 #ifdef _MALLOC_INTERNAL | |
154 | |
155 /* The allocator divides the heap into blocks of fixed size; large | |
156 requests receive one or more whole blocks, and small requests | |
157 receive a fragment of a block. Fragment sizes are powers of two, | |
158 and all fragments of a block are the same size. When all the | |
159 fragments in a block have been freed, the block itself is freed. */ | |
160 #define INT_BIT (CHAR_BIT * sizeof(int)) | |
161 #define BLOCKLOG (INT_BIT > 16 ? 12 : 9) | |
162 #define BLOCKSIZE (1 << BLOCKLOG) | |
163 #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) | |
164 | |
165 /* Determine the amount of memory spanned by the initial heap table | |
166 (not an absolute limit). */ | |
167 #define HEAP (INT_BIT > 16 ? 4194304 : 65536) | |
168 | |
169 /* Number of contiguous free blocks allowed to build up at the end of | |
170 memory before they will be returned to the system. */ | |
171 #define FINAL_FREE_BLOCKS 8 | |
172 | |
173 /* Data structure giving per-block information. */ | |
174 typedef union | |
175 { | |
176 /* Heap information for a busy block. */ | |
177 struct | |
178 { | |
179 /* Zero for a large block, or positive giving the | |
180 logarithm to the base two of the fragment size. */ | |
181 int type; | |
182 union | |
183 { | |
184 struct | |
185 { | |
186 __malloc_size_t nfree; /* Free frags in a fragmented block. */ | |
187 __malloc_size_t first; /* First free fragment of the block. */ | |
188 } frag; | |
189 /* Size (in blocks) of a large cluster. */ | |
190 __malloc_size_t size; | |
191 } info; | |
192 } busy; | |
193 /* Heap information for a free block | |
194 (that may be the first of a free cluster). */ | |
195 struct | |
196 { | |
197 __malloc_size_t size; /* Size (in blocks) of a free cluster. */ | |
198 __malloc_size_t next; /* Index of next free cluster. */ | |
199 __malloc_size_t prev; /* Index of previous free cluster. */ | |
200 } free; | |
201 } malloc_info; | |
202 | |
203 /* Pointer to first block of the heap. */ | |
204 extern char *_heapbase; | |
205 | |
206 /* Table indexed by block number giving per-block information. */ | |
207 extern malloc_info *_heapinfo; | |
208 | |
209 /* Address to block number and vice versa. */ | |
210 #define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) | |
211 #define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) | |
212 | |
213 /* Current search index for the heap table. */ | |
214 extern __malloc_size_t _heapindex; | |
215 | |
216 /* Limit of valid info table indices. */ | |
217 extern __malloc_size_t _heaplimit; | |
218 | |
219 /* Doubly linked lists of free fragments. */ | |
220 struct list | |
221 { | |
222 struct list *next; | |
223 struct list *prev; | |
224 }; | |
225 | |
226 /* Free list headers for each fragment size. */ | |
227 extern struct list _fraghead[]; | |
228 | |
229 /* List of blocks allocated with `memalign' (or `valloc'). */ | |
230 struct alignlist | |
231 { | |
232 struct alignlist *next; | |
233 __ptr_t aligned; /* The address that memaligned returned. */ | |
234 __ptr_t exact; /* The address that malloc returned. */ | |
235 }; | |
236 extern struct alignlist *_aligned_blocks; | |
237 | |
238 /* Instrumentation. */ | |
239 extern __malloc_size_t _chunks_used; | |
240 extern __malloc_size_t _bytes_used; | |
241 extern __malloc_size_t _chunks_free; | |
242 extern __malloc_size_t _bytes_free; | |
243 | |
244 /* Internal version of `free' used in `morecore' (malloc.c). */ | |
245 extern void _free_internal __P ((__ptr_t __ptr)); | |
246 | |
247 #endif /* _MALLOC_INTERNAL. */ | |
248 | |
249 /* Underlying allocation function; successive calls should | |
250 return contiguous pieces of memory. */ | |
251 extern __ptr_t (*__morecore) __P ((ptrdiff_t __size)); | |
252 | |
253 /* Default value of `__morecore'. */ | |
254 extern __ptr_t __default_morecore __P ((ptrdiff_t __size)); | |
255 | |
256 /* If not NULL, this function is called after each time | |
257 `__morecore' is called to increase the data size. */ | |
258 extern void (*__after_morecore_hook) __P ((void)); | |
259 | |
260 /* Nonzero if `malloc' has been called and done its initialization. */ | |
261 extern int __malloc_initialized; | |
262 | |
263 /* Hooks for debugging versions. */ | |
264 extern void (*__free_hook) __P ((__ptr_t __ptr)); | |
265 extern __ptr_t (*__malloc_hook) __P ((size_t __size)); | |
266 extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)); | |
267 | |
268 /* Return values for `mprobe': these are the kinds of inconsistencies that | |
269 `mcheck' enables detection of. */ | |
270 enum mcheck_status | |
271 { | |
272 MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ | |
273 MCHECK_OK, /* Block is fine. */ | |
274 MCHECK_FREE, /* Block freed twice. */ | |
275 MCHECK_HEAD, /* Memory before the block was clobbered. */ | |
276 MCHECK_TAIL /* Memory after the block was clobbered. */ | |
277 }; | |
278 | |
279 /* Activate a standard collection of debugging hooks. This must be called | |
280 before `malloc' is ever called. ABORTFUNC is called with an error code | |
281 (see enum above) when an inconsistency is detected. If ABORTFUNC is | |
282 null, the standard function prints on stderr and then calls `abort'. */ | |
283 extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status)))); | |
284 | |
285 /* Check for aberrations in a particular malloc'd block. You must have | |
286 called `mcheck' already. These are the same checks that `mcheck' does | |
287 when you free or reallocate a block. */ | |
288 extern enum mcheck_status mprobe __P ((__ptr_t __ptr)); | |
289 | |
290 /* Activate a standard collection of tracing hooks. */ | |
291 extern void mtrace __P ((void)); | |
292 extern void muntrace __P ((void)); | |
293 | |
294 /* Statistics available to the user. */ | |
295 struct mstats | |
296 { | |
297 __malloc_size_t bytes_total; /* Total size of the heap. */ | |
298 __malloc_size_t chunks_used; /* Chunks allocated by the user. */ | |
299 __malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */ | |
300 __malloc_size_t chunks_free; /* Chunks in the free list. */ | |
301 __malloc_size_t bytes_free; /* Byte total of chunks in the free list. */ | |
302 }; | |
303 | |
304 /* Pick up the current statistics. */ | |
305 extern struct mstats mstats __P ((void)); | |
306 | |
307 /* Call WARNFUN with a warning message when memory usage is high. */ | |
308 extern void memory_warnings __P ((__ptr_t __start, | |
309 void (*__warnfun) __P ((__const char *)))); | |
310 | |
311 | |
312 #if 0 /* unused in this file, and conflicting prototypes anyway */ | |
313 /* Relocating allocator. */ | |
314 | |
315 /* Allocate SIZE bytes, and store the address in *HANDLEPTR. */ | |
316 extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size)); | |
317 | |
318 /* Free the storage allocated in HANDLEPTR. */ | |
319 extern void r_alloc_free __P ((__ptr_t *__handleptr)); | |
320 | |
321 /* Adjust the block at HANDLEPTR to be SIZE bytes long. */ | |
322 extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size)); | |
323 #endif /* 0 */ | |
324 | |
325 #ifdef __cplusplus | |
326 } | |
327 #endif | |
328 | |
329 #endif /* malloc.h */ | |
330 /* Allocate memory on a page boundary. | |
331 Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. | |
332 | |
333 This library is free software; you can redistribute it and/or | |
334 modify it under the terms of the GNU Library General Public License as | |
335 published by the Free Software Foundation; either version 2 of the | |
336 License, or (at your option) any later version. | |
337 | |
338 This library is distributed in the hope that it will be useful, | |
339 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
340 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
341 Library General Public License for more details. | |
342 | |
343 You should have received a copy of the GNU General Public License | |
344 along with this library; see the file COPYING. If not, write to | |
345 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
346 Boston, MA 02111-1307, USA. | |
347 | |
348 The author may be reached (Email) at the address mike@ai.mit.edu, | |
349 or (US mail) as Mike Haertel c/o Free Software Foundation, Inc. */ | |
350 | |
351 #if defined (__GNU_LIBRARY__) || defined (_LIBC) | |
352 #include <stddef.h> | |
353 #include <sys/cdefs.h> | |
354 extern size_t __getpagesize __P ((void)); | |
355 #else | |
356 #include "getpagesize.h" | |
357 #define __getpagesize() getpagesize() | |
358 #endif | |
359 | |
360 #ifndef _MALLOC_INTERNAL | |
361 #define _MALLOC_INTERNAL | |
362 #include <malloc.h> | |
363 #endif | |
364 | |
365 static __malloc_size_t pagesize; | |
366 | |
367 __ptr_t | |
368 valloc (size) | |
369 __malloc_size_t size; | |
370 { | |
371 if (pagesize == 0) | |
372 pagesize = __getpagesize (); | |
373 | |
374 return memalign (pagesize, size); | |
375 } | |
376 /* Memory allocator `malloc'. | |
377 Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation | |
378 Written May 1989 by Mike Haertel. | |
379 | |
380 This library is free software; you can redistribute it and/or | |
381 modify it under the terms of the GNU Library General Public License as | |
382 published by the Free Software Foundation; either version 2 of the | |
383 License, or (at your option) any later version. | |
384 | |
385 This library is distributed in the hope that it will be useful, | |
386 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
387 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
388 Library General Public License for more details. | |
389 | |
390 You should have received a copy of the GNU General Public License | |
391 along with this library; see the file COPYING. If not, write to | |
392 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
393 Boston, MA 02111-1307, USA. | |
394 | |
395 The author may be reached (Email) at the address mike@ai.mit.edu, | |
396 or (US mail) as Mike Haertel c/o Free Software Foundation, Inc. */ | |
397 | |
398 #ifndef _MALLOC_INTERNAL | |
399 #define _MALLOC_INTERNAL | |
400 #include <malloc.h> | |
401 #endif | |
402 | |
403 /* How to really get more memory. */ | |
404 __ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore; | |
405 | |
406 /* Debugging hook for `malloc'. */ | |
407 __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); | |
408 | |
409 /* Pointer to the base of the first block. */ | |
410 char *_heapbase; | |
411 | |
412 /* Block information table. Allocated with align/__free (not malloc/free). */ | |
413 malloc_info *_heapinfo; | |
414 | |
415 /* Number of info entries. */ | |
416 static __malloc_size_t heapsize; | |
417 | |
418 /* Search index in the info table. */ | |
419 __malloc_size_t _heapindex; | |
420 | |
421 /* Limit of valid info table indices. */ | |
422 __malloc_size_t _heaplimit; | |
423 | |
424 /* Free lists for each fragment size. */ | |
425 struct list _fraghead[BLOCKLOG]; | |
426 | |
427 /* Instrumentation. */ | |
428 __malloc_size_t _chunks_used; | |
429 __malloc_size_t _bytes_used; | |
430 __malloc_size_t _chunks_free; | |
431 __malloc_size_t _bytes_free; | |
432 | |
433 /* Are you experienced? */ | |
434 int __malloc_initialized; | |
435 | |
436 void (*__after_morecore_hook) __P ((void)); | |
437 | |
438 /* Aligned allocation. */ | |
439 static __ptr_t align __P ((__malloc_size_t)); | |
440 static __ptr_t | |
441 align (size) | |
442 __malloc_size_t size; | |
443 { | |
444 __ptr_t result; | |
445 unsigned long int adj; | |
446 | |
447 result = (*__morecore) (size); | |
448 adj = (unsigned long int) ((unsigned long int) ((char *) result - | |
449 (char *) NULL)) % BLOCKSIZE; | |
450 if (adj != 0) | |
451 { | |
452 adj = BLOCKSIZE - adj; | |
453 (void) (*__morecore) (adj); | |
454 result = (char *) result + adj; | |
455 } | |
456 | |
457 if (__after_morecore_hook) | |
458 (*__after_morecore_hook) (); | |
459 | |
460 return result; | |
461 } | |
462 | |
463 /* Set everything up and remember that we have. */ | |
464 static int initialize __P ((void)); | |
465 static int | |
466 initialize () | |
467 { | |
468 heapsize = HEAP / BLOCKSIZE; | |
469 _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); | |
470 if (_heapinfo == NULL) | |
471 return 0; | |
472 memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); | |
473 _heapinfo[0].free.size = 0; | |
474 _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; | |
475 _heapindex = 0; | |
476 _heapbase = (char *) _heapinfo; | |
477 | |
478 /* Account for the _heapinfo block itself in the statistics. */ | |
479 _bytes_used = heapsize * sizeof (malloc_info); | |
480 _chunks_used = 1; | |
481 | |
482 __malloc_initialized = 1; | |
483 return 1; | |
484 } | |
485 | |
486 /* Get neatly aligned memory, initializing or | |
487 growing the heap info table as necessary. */ | |
488 static __ptr_t morecore __P ((__malloc_size_t)); | |
489 static __ptr_t | |
490 morecore (size) | |
491 __malloc_size_t size; | |
492 { | |
493 __ptr_t result; | |
494 malloc_info *newinfo, *oldinfo; | |
495 __malloc_size_t newsize; | |
496 | |
497 result = align (size); | |
498 if (result == NULL) | |
499 return NULL; | |
500 | |
501 /* Check if we need to grow the info table. */ | |
502 if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize) | |
503 { | |
504 newsize = heapsize; | |
505 while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize) | |
506 newsize *= 2; | |
507 newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); | |
508 if (newinfo == NULL) | |
509 { | |
510 (*__morecore) (-size); | |
511 return NULL; | |
512 } | |
513 memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); | |
514 memset (&newinfo[heapsize], 0, | |
515 (newsize - heapsize) * sizeof (malloc_info)); | |
516 oldinfo = _heapinfo; | |
517 newinfo[BLOCK (oldinfo)].busy.type = 0; | |
518 newinfo[BLOCK (oldinfo)].busy.info.size | |
519 = BLOCKIFY (heapsize * sizeof (malloc_info)); | |
520 _heapinfo = newinfo; | |
521 /* Account for the _heapinfo block itself in the statistics. */ | |
522 _bytes_used += newsize * sizeof (malloc_info); | |
523 ++_chunks_used; | |
524 _free_internal (oldinfo); | |
525 heapsize = newsize; | |
526 } | |
527 | |
528 _heaplimit = BLOCK ((char *) result + size); | |
529 return result; | |
530 } | |
531 | |
532 /* Allocate memory from the heap. */ | |
533 __ptr_t | |
534 malloc (size) | |
535 __malloc_size_t size; | |
536 { | |
537 __ptr_t result; | |
538 __malloc_size_t block, blocks, lastblocks, start; | |
539 __malloc_size_t i; | |
540 struct list *next; | |
541 | |
542 /* ANSI C allows `malloc (0)' to either return NULL, or to return a | |
543 valid address you can realloc and free (though not dereference). | |
544 | |
545 It turns out that some extant code (sunrpc, at least Ultrix's version) | |
546 expects `malloc (0)' to return non-NULL and breaks otherwise. | |
547 Be compatible. */ | |
548 | |
549 #ifdef HAVE_X_WINDOWS | |
550 /* there is at least one Xt bug where calloc(n,x) is blindly called | |
551 where n can be 0, and yet if 0 is returned, Xt barfs */ | |
552 if (size == 0) | |
553 size = sizeof (struct list); | |
554 #else | |
555 if (size == 0) | |
556 return NULL; | |
557 #endif | |
558 | |
559 if (__malloc_hook != NULL) | |
560 return (*__malloc_hook) (size); | |
561 | |
562 if (!__malloc_initialized) | |
563 if (!initialize ()) | |
564 return NULL; | |
565 | |
566 #ifdef SUNOS_LOCALTIME_BUG | |
567 /* Workaround for localtime() allocating 8 bytes and writing 9 bug... */ | |
568 if (size < 16) | |
569 size = 16; | |
570 #endif | |
571 | |
572 if (size < sizeof (struct list)) | |
573 size = sizeof (struct list); | |
574 | |
575 /* Determine the allocation policy based on the request size. */ | |
576 if (size <= BLOCKSIZE / 2) | |
577 { | |
578 /* Small allocation to receive a fragment of a block. | |
579 Determine the logarithm to base two of the fragment size. */ | |
580 __malloc_size_t log = 1; | |
581 --size; | |
582 while ((size /= 2) != 0) | |
583 ++log; | |
584 | |
585 /* Look in the fragment lists for a | |
586 free fragment of the desired size. */ | |
587 next = _fraghead[log].next; | |
588 if (next != NULL) | |
589 { | |
590 /* There are free fragments of this size. | |
591 Pop a fragment out of the fragment list and return it. | |
592 Update the block's nfree and first counters. */ | |
593 result = (__ptr_t) next; | |
594 next->prev->next = next->next; | |
595 if (next->next != NULL) | |
596 next->next->prev = next->prev; | |
597 block = BLOCK (result); | |
598 if (--_heapinfo[block].busy.info.frag.nfree != 0) | |
599 _heapinfo[block].busy.info.frag.first = (unsigned long int) | |
600 ((unsigned long int) ((char *) next->next - (char *) NULL) | |
601 % BLOCKSIZE) >> log; | |
602 | |
603 /* Update the statistics. */ | |
604 ++_chunks_used; | |
605 _bytes_used += 1 << log; | |
606 --_chunks_free; | |
607 _bytes_free -= 1 << log; | |
608 } | |
609 else | |
610 { | |
611 /* No free fragments of the desired size, so get a new block | |
612 and break it into fragments, returning the first. */ | |
613 result = malloc (BLOCKSIZE); | |
614 if (result == NULL) | |
615 return NULL; | |
616 | |
617 /* Link all fragments but the first into the free list. */ | |
618 for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> log); ++i) | |
619 { | |
620 next = (struct list *) ((char *) result + (i << log)); | |
621 next->next = _fraghead[log].next; | |
622 next->prev = &_fraghead[log]; | |
623 next->prev->next = next; | |
624 if (next->next != NULL) | |
625 next->next->prev = next; | |
626 } | |
627 | |
628 /* Initialize the nfree and first counters for this block. */ | |
629 block = BLOCK (result); | |
630 _heapinfo[block].busy.type = log; | |
631 _heapinfo[block].busy.info.frag.nfree = i - 1; | |
632 _heapinfo[block].busy.info.frag.first = i - 1; | |
633 | |
634 _chunks_free += (BLOCKSIZE >> log) - 1; | |
635 _bytes_free += BLOCKSIZE - (1 << log); | |
636 _bytes_used -= BLOCKSIZE - (1 << log); | |
637 } | |
638 } | |
639 else | |
640 { | |
641 /* Large allocation to receive one or more blocks. | |
642 Search the free list in a circle starting at the last place visited. | |
643 If we loop completely around without finding a large enough | |
644 space we will have to get more memory from the system. */ | |
645 blocks = BLOCKIFY (size); | |
646 start = block = _heapindex; | |
647 while (_heapinfo[block].free.size < blocks) | |
648 { | |
649 block = _heapinfo[block].free.next; | |
650 if (block == start) | |
651 { | |
652 /* Need to get more from the system. Check to see if | |
653 the new core will be contiguous with the final free | |
654 block; if so we don't need to get as much. */ | |
655 block = _heapinfo[0].free.prev; | |
656 lastblocks = _heapinfo[block].free.size; | |
657 if (_heaplimit != 0 && block + lastblocks == _heaplimit && | |
658 (*__morecore) (0) == ADDRESS (block + lastblocks) && | |
659 (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL) | |
660 { | |
661 /* Which block we are extending (the `final free | |
662 block' referred to above) might have changed, if | |
663 it got combined with a freed info table. */ | |
664 block = _heapinfo[0].free.prev; | |
665 _heapinfo[block].free.size += (blocks - lastblocks); | |
666 _bytes_free += (blocks - lastblocks) * BLOCKSIZE; | |
667 continue; | |
668 } | |
669 result = morecore (blocks * BLOCKSIZE); | |
670 if (result == NULL) | |
671 return NULL; | |
672 block = BLOCK (result); | |
673 _heapinfo[block].busy.type = 0; | |
674 _heapinfo[block].busy.info.size = blocks; | |
675 ++_chunks_used; | |
676 _bytes_used += blocks * BLOCKSIZE; | |
677 return result; | |
678 } | |
679 } | |
680 | |
681 /* At this point we have found a suitable free list entry. | |
682 Figure out how to remove what we need from the list. */ | |
683 result = ADDRESS (block); | |
684 if (_heapinfo[block].free.size > blocks) | |
685 { | |
686 /* The block we found has a bit left over, | |
687 so relink the tail end back into the free list. */ | |
688 _heapinfo[block + blocks].free.size | |
689 = _heapinfo[block].free.size - blocks; | |
690 _heapinfo[block + blocks].free.next | |
691 = _heapinfo[block].free.next; | |
692 _heapinfo[block + blocks].free.prev | |
693 = _heapinfo[block].free.prev; | |
694 _heapinfo[_heapinfo[block].free.prev].free.next | |
695 = _heapinfo[_heapinfo[block].free.next].free.prev | |
696 = _heapindex = block + blocks; | |
697 } | |
698 else | |
699 { | |
700 /* The block exactly matches our requirements, | |
701 so just remove it from the list. */ | |
702 _heapinfo[_heapinfo[block].free.next].free.prev | |
703 = _heapinfo[block].free.prev; | |
704 _heapinfo[_heapinfo[block].free.prev].free.next | |
705 = _heapindex = _heapinfo[block].free.next; | |
706 --_chunks_free; | |
707 } | |
708 | |
709 _heapinfo[block].busy.type = 0; | |
710 _heapinfo[block].busy.info.size = blocks; | |
711 ++_chunks_used; | |
712 _bytes_used += blocks * BLOCKSIZE; | |
713 _bytes_free -= blocks * BLOCKSIZE; | |
714 } | |
715 | |
716 return result; | |
717 } | |
718 | |
719 #ifndef _LIBC | |
720 | |
721 /* On some ANSI C systems, some libc functions call _malloc, _free | |
722 and _realloc. Make them use the GNU functions. */ | |
723 | |
724 __ptr_t _malloc (__malloc_size_t size); | |
725 __ptr_t | |
726 _malloc (__malloc_size_t size) | |
727 { | |
728 return malloc (size); | |
729 } | |
730 | |
731 void _free (__ptr_t ptr); | |
732 void | |
733 _free (__ptr_t ptr) | |
734 { | |
735 free (ptr); | |
736 } | |
737 | |
738 __ptr_t _realloc (__ptr_t ptr, __malloc_size_t size); | |
739 __ptr_t | |
740 _realloc (__ptr_t ptr, __malloc_size_t size) | |
741 { | |
742 return realloc (ptr, size); | |
743 } | |
744 | |
745 #endif | |
746 /* Free a block of memory allocated by `malloc'. | |
747 Copyright 1990, 1991, 1992, 1994 Free Software Foundation | |
748 Written May 1989 by Mike Haertel. | |
749 | |
750 This library is free software; you can redistribute it and/or | |
751 modify it under the terms of the GNU Library General Public License as | |
752 published by the Free Software Foundation; either version 2 of the | |
753 License, or (at your option) any later version. | |
754 | |
755 This library is distributed in the hope that it will be useful, | |
756 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
757 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
758 Library General Public License for more details. | |
759 | |
760 You should have received a copy of the GNU General Public License | |
761 along with this library; see the file COPYING. If not, write to | |
762 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
763 Boston, MA 02111-1307, USA. | |
764 | |
765 The author may be reached (Email) at the address mike@ai.mit.edu, | |
766 or (US mail) as Mike Haertel c/o Free Software Foundation, Inc. */ | |
767 | |
768 #ifndef _MALLOC_INTERNAL | |
769 #define _MALLOC_INTERNAL | |
770 #include <malloc.h> | |
771 #endif | |
772 | |
773 /* Debugging hook for free. */ | |
774 void (*__free_hook) __P ((__ptr_t __ptr)); | |
775 | |
776 /* List of blocks allocated by memalign. */ | |
777 struct alignlist *_aligned_blocks = NULL; | |
778 | |
779 /* Return memory to the heap. | |
780 Like `free' but don't call a __free_hook if there is one. */ | |
781 void | |
782 _free_internal (ptr) | |
783 __ptr_t ptr; | |
784 { | |
785 int type; | |
786 __malloc_size_t block, blocks; | |
787 __malloc_size_t i; | |
788 struct list *prev, *next; | |
789 | |
790 block = BLOCK (ptr); | |
791 | |
792 type = _heapinfo[block].busy.type; | |
793 switch (type) | |
794 { | |
795 case 0: | |
796 /* Get as many statistics as early as we can. */ | |
797 --_chunks_used; | |
798 _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; | |
799 _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; | |
800 | |
801 /* Find the free cluster previous to this one in the free list. | |
802 Start searching at the last block referenced; this may benefit | |
803 programs with locality of allocation. */ | |
804 i = _heapindex; | |
805 if (i > block) | |
806 while (i > block) | |
807 i = _heapinfo[i].free.prev; | |
808 else | |
809 { | |
810 do | |
811 i = _heapinfo[i].free.next; | |
812 while (i > 0 && i < block); | |
813 i = _heapinfo[i].free.prev; | |
814 } | |
815 | |
816 /* Determine how to link this block into the free list. */ | |
817 if (block == i + _heapinfo[i].free.size) | |
818 { | |
819 /* Coalesce this block with its predecessor. */ | |
820 _heapinfo[i].free.size += _heapinfo[block].busy.info.size; | |
821 block = i; | |
822 } | |
823 else | |
824 { | |
825 /* Really link this block back into the free list. */ | |
826 _heapinfo[block].free.size = _heapinfo[block].busy.info.size; | |
827 _heapinfo[block].free.next = _heapinfo[i].free.next; | |
828 _heapinfo[block].free.prev = i; | |
829 _heapinfo[i].free.next = block; | |
830 _heapinfo[_heapinfo[block].free.next].free.prev = block; | |
831 ++_chunks_free; | |
832 } | |
833 | |
834 /* Now that the block is linked in, see if we can coalesce it | |
835 with its successor (by deleting its successor from the list | |
836 and adding in its size). */ | |
837 if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) | |
838 { | |
839 _heapinfo[block].free.size | |
840 += _heapinfo[_heapinfo[block].free.next].free.size; | |
841 _heapinfo[block].free.next | |
842 = _heapinfo[_heapinfo[block].free.next].free.next; | |
843 _heapinfo[_heapinfo[block].free.next].free.prev = block; | |
844 --_chunks_free; | |
845 } | |
846 | |
847 /* Now see if we can return stuff to the system. */ | |
848 blocks = _heapinfo[block].free.size; | |
849 if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit | |
850 && (*__morecore) (0) == ADDRESS (block + blocks)) | |
851 { | |
852 __malloc_size_t bytes = blocks * BLOCKSIZE; | |
853 _heaplimit -= blocks; | |
854 (*__morecore) (-bytes); | |
855 _heapinfo[_heapinfo[block].free.prev].free.next | |
856 = _heapinfo[block].free.next; | |
857 _heapinfo[_heapinfo[block].free.next].free.prev | |
858 = _heapinfo[block].free.prev; | |
859 block = _heapinfo[block].free.prev; | |
860 --_chunks_free; | |
861 _bytes_free -= bytes; | |
862 } | |
863 | |
864 /* Set the next search to begin at this block. */ | |
865 _heapindex = block; | |
866 break; | |
867 | |
868 default: | |
869 /* Do some of the statistics. */ | |
870 --_chunks_used; | |
871 _bytes_used -= 1 << type; | |
872 ++_chunks_free; | |
873 _bytes_free += 1 << type; | |
874 | |
875 /* Get the address of the first free fragment in this block. */ | |
876 prev = (struct list *) ((char *) ADDRESS (block) + | |
877 (_heapinfo[block].busy.info.frag.first << type)); | |
878 | |
879 if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) | |
880 { | |
881 /* If all fragments of this block are free, remove them | |
882 from the fragment list and free the whole block. */ | |
883 next = prev; | |
884 for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i) | |
885 next = next->next; | |
886 prev->prev->next = next; | |
887 if (next != NULL) | |
888 next->prev = prev->prev; | |
889 _heapinfo[block].busy.type = 0; | |
890 _heapinfo[block].busy.info.size = 1; | |
891 | |
892 /* Keep the statistics accurate. */ | |
893 ++_chunks_used; | |
894 _bytes_used += BLOCKSIZE; | |
895 _chunks_free -= BLOCKSIZE >> type; | |
896 _bytes_free -= BLOCKSIZE; | |
897 | |
898 free (ADDRESS (block)); | |
899 } | |
900 else if (_heapinfo[block].busy.info.frag.nfree != 0) | |
901 { | |
902 /* If some fragments of this block are free, link this | |
903 fragment into the fragment list after the first free | |
904 fragment of this block. */ | |
905 next = (struct list *) ptr; | |
906 next->next = prev->next; | |
907 next->prev = prev; | |
908 prev->next = next; | |
909 if (next->next != NULL) | |
910 next->next->prev = next; | |
911 ++_heapinfo[block].busy.info.frag.nfree; | |
912 } | |
913 else | |
914 { | |
915 /* No fragments of this block are free, so link this | |
916 fragment into the fragment list and announce that | |
917 it is the first free fragment of this block. */ | |
918 prev = (struct list *) ptr; | |
919 _heapinfo[block].busy.info.frag.nfree = 1; | |
920 _heapinfo[block].busy.info.frag.first = (unsigned long int) | |
921 ((unsigned long int) ((char *) ptr - (char *) NULL) | |
922 % BLOCKSIZE >> type); | |
923 prev->next = _fraghead[type].next; | |
924 prev->prev = &_fraghead[type]; | |
925 prev->prev->next = prev; | |
926 if (prev->next != NULL) | |
927 prev->next->prev = prev; | |
928 } | |
929 break; | |
930 } | |
931 } | |
932 | |
933 /* Return memory to the heap. */ | |
934 __free_ret_t | |
935 free (ptr) | |
936 __ptr_t ptr; | |
937 { | |
938 struct alignlist *l; | |
939 | |
940 if (ptr == NULL) | |
941 return; | |
942 | |
943 for (l = _aligned_blocks; l != NULL; l = l->next) | |
944 if (l->aligned == ptr) | |
945 { | |
946 l->aligned = NULL; /* Mark the slot in the list as free. */ | |
947 ptr = l->exact; | |
948 break; | |
949 } | |
950 | |
951 if (__free_hook != NULL) | |
952 (*__free_hook) (ptr); | |
953 else | |
954 _free_internal (ptr); | |
955 } | |
956 /* Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. | |
957 This file is part of the GNU C Library. | |
958 | |
959 The GNU C Library is free software; you can redistribute it and/or | |
960 modify it under the terms of the GNU Library General Public License as | |
961 published by the Free Software Foundation; either version 2 of the | |
962 License, or (at your option) any later version. | |
963 | |
964 The GNU C Library is distributed in the hope that it will be useful, | |
965 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
966 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
967 Library General Public License for more details. | |
968 | |
969 You should have received a copy of the GNU General Public License | |
970 along with this library; see the file COPYING. If not, write to | |
971 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
972 Boston, MA 02111-1307, USA. */ | |
973 | |
974 #ifndef _MALLOC_INTERNAL | |
975 #define _MALLOC_INTERNAL | |
976 #include <malloc.h> | |
977 #endif | |
978 | |
979 #ifdef _LIBC | |
980 | |
981 #include <ansidecl.h> | |
982 #include <gnu-stabs.h> | |
983 | |
984 #undef cfree | |
985 | |
986 function_alias(cfree, free, void, (ptr), | |
987 DEFUN(cfree, (ptr), PTR ptr)) | |
988 | |
989 #else | |
990 | |
991 void cfree (__ptr_t ptr); | |
992 void | |
993 cfree (__ptr_t ptr) | |
994 { | |
995 free (ptr); | |
996 } | |
997 | |
998 #endif | |
999 /* Change the size of a block allocated by `malloc'. | |
1000 Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. | |
1001 Written May 1989 by Mike Haertel. | |
1002 | |
1003 This library is free software; you can redistribute it and/or | |
1004 modify it under the terms of the GNU Library General Public License as | |
1005 published by the Free Software Foundation; either version 2 of the | |
1006 License, or (at your option) any later version. | |
1007 | |
1008 This library is distributed in the hope that it will be useful, | |
1009 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1011 Library General Public License for more details. | |
1012 | |
1013 You should have received a copy of the GNU General Public License | |
1014 along with this library; see the file COPYING. If not, write to | |
1015 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
1016 Boston, MA 02111-1307, USA. | |
1017 | |
1018 The author may be reached (Email) at the address mike@ai.mit.edu, | |
1019 or (US mail) as Mike Haertel c/o Free Software Foundation, Inc. */ | |
1020 | |
1021 #ifndef _MALLOC_INTERNAL | |
1022 #define _MALLOC_INTERNAL | |
1023 #include <malloc.h> | |
1024 #endif | |
1025 | |
1026 #if 0 /* FSFmacs */ | |
1027 /* XEmacs requires an ANSI compiler, and memmove() is part of the ANSI- | |
1028 mandated functions. For losing systems like SunOS 4, we provide | |
1029 our own memmove(). */ | |
1030 | |
1031 #if (defined (MEMMOVE_MISSING) || \ | |
1032 !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) | |
1033 | |
1034 /* Snarfed directly from Emacs src/dispnew.c: | |
1035 XXX Should use system bcopy if it handles overlap. */ | |
1036 #ifndef emacs | |
1037 | |
1038 /* Like bcopy except never gets confused by overlap. */ | |
1039 | |
1040 static void | |
1041 safe_bcopy (from, to, size) | |
1042 char *from, *to; | |
1043 int size; | |
1044 { | |
1045 if (size <= 0 || from == to) | |
1046 return; | |
1047 | |
1048 /* If the source and destination don't overlap, then bcopy can | |
1049 handle it. If they do overlap, but the destination is lower in | |
1050 memory than the source, we'll assume bcopy can handle that. */ | |
1051 if (to < from || from + size <= to) | |
1052 bcopy (from, to, size); | |
1053 | |
1054 /* Otherwise, we'll copy from the end. */ | |
1055 else | |
1056 { | |
1057 char *endf = from + size; | |
1058 char *endt = to + size; | |
1059 | |
1060 /* If TO - FROM is large, then we should break the copy into | |
1061 nonoverlapping chunks of TO - FROM bytes each. However, if | |
1062 TO - FROM is small, then the bcopy function call overhead | |
1063 makes this not worth it. The crossover point could be about | |
1064 anywhere. Since I don't think the obvious copy loop is too | |
1065 bad, I'm trying to err in its favor. */ | |
1066 if (to - from < 64) | |
1067 { | |
1068 do | |
1069 *--endt = *--endf; | |
1070 while (endf != from); | |
1071 } | |
1072 else | |
1073 { | |
1074 for (;;) | |
1075 { | |
1076 endt -= (to - from); | |
1077 endf -= (to - from); | |
1078 | |
1079 if (endt < to) | |
1080 break; | |
1081 | |
1082 bcopy (endf, endt, to - from); | |
1083 } | |
1084 | |
1085 /* If SIZE wasn't a multiple of TO - FROM, there will be a | |
1086 little left over. The amount left over is | |
1087 (endt + (to - from)) - to, which is endt - from. */ | |
1088 bcopy (from, to, endt - from); | |
1089 } | |
1090 } | |
1091 } | |
1092 #endif /* Not emacs. */ | |
1093 | |
1094 #define memmove(to, from, size) safe_bcopy ((from), (to), (size)) | |
1095 | |
1096 #endif | |
1097 | |
1098 #endif /* FSFmacs */ | |
1099 | |
1100 | |
1101 #ifndef min | |
1102 #define min(A, B) ((A) < (B) ? (A) : (B)) | |
1103 #endif | |
1104 | |
1105 /* Debugging hook for realloc. */ | |
1106 __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); | |
1107 | |
1108 /* Resize the given region to the new size, returning a pointer | |
1109 to the (possibly moved) region. This is optimized for speed; | |
1110 some benchmarks seem to indicate that greater compactness is | |
1111 achieved by unconditionally allocating and copying to a | |
1112 new region. This module has incestuous knowledge of the | |
1113 internals of both free and malloc. */ | |
1114 __ptr_t | |
1115 realloc (ptr, size) | |
1116 __ptr_t ptr; | |
1117 __malloc_size_t size; | |
1118 { | |
1119 __ptr_t result; | |
1120 int type; | |
1121 __malloc_size_t block, blocks, oldlimit; | |
1122 | |
1123 if (size == 0) | |
1124 { | |
1125 free (ptr); | |
1126 return malloc (0); | |
1127 } | |
1128 else if (ptr == NULL) | |
1129 return malloc (size); | |
1130 | |
1131 if (__realloc_hook != NULL) | |
1132 return (*__realloc_hook) (ptr, size); | |
1133 | |
1134 block = BLOCK (ptr); | |
1135 | |
1136 type = _heapinfo[block].busy.type; | |
1137 switch (type) | |
1138 { | |
1139 case 0: | |
1140 /* Maybe reallocate a large block to a small fragment. */ | |
1141 if (size <= BLOCKSIZE / 2) | |
1142 { | |
1143 result = malloc (size); | |
1144 if (result != NULL) | |
1145 { | |
1146 memcpy (result, ptr, size); | |
1147 _free_internal (ptr); | |
1148 return result; | |
1149 } | |
1150 } | |
1151 | |
1152 /* The new size is a large allocation as well; | |
1153 see if we can hold it in place. */ | |
1154 blocks = BLOCKIFY (size); | |
1155 if (blocks < _heapinfo[block].busy.info.size) | |
1156 { | |
1157 /* The new size is smaller; return | |
1158 excess memory to the free list. */ | |
1159 _heapinfo[block + blocks].busy.type = 0; | |
1160 _heapinfo[block + blocks].busy.info.size | |
1161 = _heapinfo[block].busy.info.size - blocks; | |
1162 _heapinfo[block].busy.info.size = blocks; | |
1163 /* We have just created a new chunk by splitting a chunk in two. | |
1164 Now we will free this chunk; increment the statistics counter | |
1165 so it doesn't become wrong when _free_internal decrements it. */ | |
1166 ++_chunks_used; | |
1167 _free_internal (ADDRESS (block + blocks)); | |
1168 result = ptr; | |
1169 } | |
1170 else if (blocks == _heapinfo[block].busy.info.size) | |
1171 /* No size change necessary. */ | |
1172 result = ptr; | |
1173 else | |
1174 { | |
1175 /* Won't fit, so allocate a new region that will. | |
1176 Free the old region first in case there is sufficient | |
1177 adjacent free space to grow without moving. */ | |
1178 blocks = _heapinfo[block].busy.info.size; | |
1179 /* Prevent free from actually returning memory to the system. */ | |
1180 oldlimit = _heaplimit; | |
1181 _heaplimit = 0; | |
1182 free (ptr); | |
1183 _heaplimit = oldlimit; | |
1184 result = malloc (size); | |
1185 if (result == NULL) | |
1186 { | |
1187 /* Now we're really in trouble. We have to unfree | |
1188 the thing we just freed. Unfortunately it might | |
1189 have been coalesced with its neighbors. */ | |
1190 if (_heapindex == block) | |
1191 (void) malloc (blocks * BLOCKSIZE); | |
1192 else | |
1193 { | |
1194 __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE); | |
1195 (void) malloc (blocks * BLOCKSIZE); | |
1196 free (previous); | |
1197 } | |
1198 return NULL; | |
1199 } | |
1200 if (ptr != result) | |
1201 memmove (result, ptr, blocks * BLOCKSIZE); | |
1202 } | |
1203 break; | |
1204 | |
1205 default: | |
1206 /* Old size is a fragment; type is logarithm | |
1207 to base two of the fragment size. */ | |
1208 if (size > (__malloc_size_t) (1 << (type - 1)) && | |
1209 size <= (__malloc_size_t) (1 << type)) | |
1210 /* The new size is the same kind of fragment. */ | |
1211 result = ptr; | |
1212 else | |
1213 { | |
1214 /* The new size is different; allocate a new space, | |
1215 and copy the lesser of the new size and the old. */ | |
1216 result = malloc (size); | |
1217 if (result == NULL) | |
1218 return NULL; | |
1219 memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type)); | |
1220 free (ptr); | |
1221 } | |
1222 break; | |
1223 } | |
1224 | |
1225 return result; | |
1226 } | |
1227 /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. | |
1228 | |
1229 This library is free software; you can redistribute it and/or | |
1230 modify it under the terms of the GNU Library General Public License as | |
1231 published by the Free Software Foundation; either version 2 of the | |
1232 License, or (at your option) any later version. | |
1233 | |
1234 This library is distributed in the hope that it will be useful, | |
1235 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1236 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1237 Library General Public License for more details. | |
1238 | |
1239 You should have received a copy of the GNU General Public License | |
1240 along with this library; see the file COPYING. If not, write to | |
1241 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
1242 Boston, MA 02111-1307, USA. | |
1243 | |
1244 The author may be reached (Email) at the address mike@ai.mit.edu, | |
1245 or (US mail) as Mike Haertel c/o Free Software Foundation, Inc. */ | |
1246 | |
1247 #ifndef _MALLOC_INTERNAL | |
1248 #define _MALLOC_INTERNAL | |
1249 #include <malloc.h> | |
1250 #endif | |
1251 | |
1252 /* Allocate an array of NMEMB elements each SIZE bytes long. | |
1253 The entire array is initialized to zeros. */ | |
1254 __ptr_t | |
1255 calloc (nmemb, size) | |
1256 __malloc_size_t nmemb; | |
1257 __malloc_size_t size; | |
1258 { | |
1259 __ptr_t result = malloc (nmemb * size); | |
1260 | |
1261 if (result != NULL) | |
1262 (void) memset (result, 0, nmemb * size); | |
1263 | |
1264 return result; | |
1265 } | |
1266 /* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. | |
1267 This file is part of the GNU C Library. | |
1268 | |
1269 The GNU C Library is free software; you can redistribute it and/or modify | |
1270 it under the terms of the GNU General Public License as published by | |
1271 the Free Software Foundation; either version 2, or (at your option) | |
1272 any later version. | |
1273 | |
1274 The GNU C Library is distributed in the hope that it will be useful, | |
1275 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1276 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1277 GNU General Public License for more details. | |
1278 | |
1279 You should have received a copy of the GNU General Public License | |
1280 along with the GNU C Library; see the file COPYING. If not, write to | |
1281 the Free the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
1282 Boston, MA 02111-1307, USA. */ | |
1283 | |
1284 #ifndef _MALLOC_INTERNAL | |
1285 #define _MALLOC_INTERNAL | |
1286 #include <malloc.h> | |
1287 #endif | |
1288 | |
1289 #ifndef __GNU_LIBRARY__ | |
1290 #define __sbrk sbrk | |
1291 #endif | |
1292 | |
1293 #ifdef GMALLOC_NEEDS_SBRK_DECL | |
1294 /* some versions of OSF1 need this */ | |
1295 extern __ptr_t __sbrk __P ((ssize_t increment)); | |
1296 #else | |
1297 #ifdef __GNU_LIBRARY__ | |
1298 /* It is best not to declare this and cast its result on foreign operating | |
1299 systems with potentially hostile include files. */ | |
1300 extern __ptr_t __sbrk __P ((int increment)); | |
1301 #endif | |
1302 #endif | |
1303 | |
1304 #ifndef NULL | |
1305 #define NULL 0 | |
1306 #endif | |
1307 | |
1308 /* Allocate INCREMENT more bytes of data space, | |
1309 and return the start of data space, or NULL on errors. | |
1310 If INCREMENT is negative, shrink data space. */ | |
1311 __ptr_t | |
1312 __default_morecore (increment) | |
1313 #ifdef __STDC__ | |
1314 ptrdiff_t increment; | |
1315 #else | |
1316 #ifdef OSF1 | |
1317 long increment; | |
1318 #else | |
1319 int increment; | |
1320 #endif | |
1321 #endif | |
1322 { | |
1323 #ifdef OSF1 | |
1324 __ptr_t result = (__ptr_t) __sbrk ((ssize_t) increment); | |
1325 #else | |
1326 __ptr_t result = (__ptr_t) __sbrk ((int) increment); | |
1327 #endif | |
1328 if (result == (__ptr_t) -1) | |
1329 return NULL; | |
1330 return result; | |
1331 } | |
1332 /* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. | |
1333 | |
1334 This library is free software; you can redistribute it and/or | |
1335 modify it under the terms of the GNU Library General Public License as | |
1336 published by the Free Software Foundation; either version 2 of the | |
1337 License, or (at your option) any later version. | |
1338 | |
1339 This library is distributed in the hope that it will be useful, | |
1340 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1341 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1342 Library General Public License for more details. | |
1343 | |
1344 You should have received a copy of the GNU General Public License | |
1345 along with this library; see the file COPYING. If not, write to | |
1346 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
1347 Boston, MA 02111-1307, USA. */ | |
1348 | |
1349 #ifndef _MALLOC_INTERNAL | |
1350 #define _MALLOC_INTERNAL | |
1351 #include <malloc.h> | |
1352 #endif | |
1353 | |
1354 __ptr_t | |
1355 memalign (alignment, size) | |
1356 __malloc_size_t alignment; | |
1357 __malloc_size_t size; | |
1358 { | |
1359 __ptr_t result; | |
1360 unsigned long int adj; | |
1361 | |
1362 size = ((size + alignment - 1) / alignment) * alignment; | |
1363 | |
1364 result = malloc (size); | |
1365 if (result == NULL) | |
1366 return NULL; | |
1367 adj = (unsigned long int) ((unsigned long int) ((char *) result - | |
1368 (char *) NULL)) % alignment; | |
1369 if (adj != 0) | |
1370 { | |
1371 struct alignlist *l; | |
1372 for (l = _aligned_blocks; l != NULL; l = l->next) | |
1373 if (l->aligned == NULL) | |
1374 /* This slot is free. Use it. */ | |
1375 break; | |
1376 if (l == NULL) | |
1377 { | |
1378 l = (struct alignlist *) malloc (sizeof (struct alignlist)); | |
1379 if (l == NULL) | |
1380 { | |
1381 free (result); | |
1382 return NULL; | |
1383 } | |
1384 l->next = _aligned_blocks; | |
1385 _aligned_blocks = l; | |
1386 } | |
1387 l->exact = result; | |
1388 result = l->aligned = (char *) result + alignment - adj; | |
1389 } | |
1390 | |
1391 return result; | |
1392 } |