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