Simplify and avoid signal-handling races.
[bpt/emacs.git] / src / ralloc.c
CommitLineData
177c0ea7 1/* Block-relocating memory allocator.
acaf905b 2 Copyright (C) 1993, 1995, 2000-2012 Free Software Foundation, Inc.
dcfdbac7
JB
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
dcfdbac7 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
dcfdbac7
JB
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
dcfdbac7
JB
18
19/* NOTES:
20
eb8c3be9 21 Only relocate the blocs necessary for SIZE in r_alloc_sbrk,
dcfdbac7 22 rather than all of them. This means allowing for a possible
abe9ff32 23 hole between the first bloc and the end of malloc storage. */
dcfdbac7 24
2c46d29f 25#ifdef emacs
aef4d570 26
18160b98 27#include <config.h>
0328b6de 28
956ace37 29#include "lisp.h" /* Needed for VALBITS. */
a4766fd5 30#include "blockinput.h"
0a58f946 31
642a1733 32#include <unistd.h>
a8c0e5ea 33
b0119c68 34#ifdef DOUG_LEA_MALLOC
177c0ea7 35#define M_TOP_PAD -2
971de7fb 36extern int mallopt (int, int);
0a58f946 37#else /* not DOUG_LEA_MALLOC */
a2c23c92 38#ifndef SYSTEM_MALLOC
b1685c5f 39extern size_t __malloc_extra_blocks;
a2c23c92 40#endif /* SYSTEM_MALLOC */
0a58f946 41#endif /* not DOUG_LEA_MALLOC */
49081834 42
d5179acc 43#else /* not emacs */
aef4d570 44
2c46d29f 45#include <stddef.h>
aef4d570 46
aef4d570
RM
47#include <unistd.h>
48#include <malloc.h>
aef4d570 49
d5179acc 50#endif /* not emacs */
2c46d29f 51
0a58f946 52
d5179acc 53#include "getpagesize.h"
dcfdbac7 54
261cb4bb
PE
55typedef size_t SIZE;
56typedef void *POINTER;
dcfdbac7
JB
57#define NIL ((POINTER) 0)
58
2c46d29f
RS
59/* A flag to indicate whether we have initialized ralloc yet. For
60 Emacs's sake, please do not make this local to malloc_init; on some
61 machines, the dumping procedure makes all static variables
62 read-only. On these machines, the word static is #defined to be
63 the empty string, meaning that r_alloc_initialized becomes an
0a58f946
GM
64 automatic variable, and loses its value each time Emacs is started
65 up. */
66
2c46d29f
RS
67static int r_alloc_initialized = 0;
68
971de7fb 69static void r_alloc_init (void);
0a58f946 70
dcfdbac7 71\f
956ace37
JB
72/* Declarations for working with the malloc, ralloc, and system breaks. */
73
abe9ff32 74/* Function to set the real break value. */
361358ea 75POINTER (*real_morecore) (long int);
dcfdbac7 76
abe9ff32 77/* The break value, as seen by malloc. */
dcfdbac7
JB
78static POINTER virtual_break_value;
79
abe9ff32
RS
80/* The address of the end of the last data in use by ralloc,
81 including relocatable blocs as well as malloc data. */
dcfdbac7
JB
82static POINTER break_value;
83
7516b7d5
RS
84/* This is the size of a page. We round memory requests to this boundary. */
85static int page_size;
86
177c0ea7 87/* Whenever we get memory from the system, get this many extra bytes. This
ad3bb3d2 88 must be a multiple of page_size. */
7516b7d5
RS
89static int extra_bytes;
90
dcfdbac7 91/* Macros for rounding. Note that rounding to any value is possible
abe9ff32 92 by changing the definition of PAGE. */
dcfdbac7 93#define PAGE (getpagesize ())
f7a009a5
RM
94#define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \
95 & ~(page_size - 1))
e429caa2 96
5e617bc2 97#define MEM_ALIGN sizeof (double)
e429caa2
KH
98#define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \
99 & ~(MEM_ALIGN - 1))
0a58f946 100
aeac019e
GM
101/* The hook `malloc' uses for the function which gets more space
102 from the system. */
103
104#ifndef SYSTEM_MALLOC
361358ea 105extern POINTER (*__morecore) (long int);
aeac019e
GM
106#endif
107
108
e429caa2 109\f
0a58f946
GM
110/***********************************************************************
111 Implementation using sbrk
112 ***********************************************************************/
113
abe9ff32
RS
114/* Data structures of heaps and blocs. */
115
116/* The relocatable objects, or blocs, and the malloc data
117 both reside within one or more heaps.
118 Each heap contains malloc data, running from `start' to `bloc_start',
119 and relocatable objects, running from `bloc_start' to `free'.
120
121 Relocatable objects may relocate within the same heap
122 or may move into another heap; the heaps themselves may grow
123 but they never move.
124
125 We try to make just one heap and make it larger as necessary.
8e6208c5 126 But sometimes we can't do that, because we can't get contiguous
abe9ff32 127 space to add onto the heap. When that happens, we start a new heap. */
177c0ea7 128
e429caa2
KH
129typedef struct heap
130{
131 struct heap *next;
132 struct heap *prev;
abe9ff32 133 /* Start of memory range of this heap. */
e429caa2 134 POINTER start;
abe9ff32 135 /* End of memory range of this heap. */
e429caa2 136 POINTER end;
abe9ff32
RS
137 /* Start of relocatable data in this heap. */
138 POINTER bloc_start;
139 /* Start of unused space in this heap. */
140 POINTER free;
47f13333
RS
141 /* First bloc in this heap. */
142 struct bp *first_bloc;
143 /* Last bloc in this heap. */
144 struct bp *last_bloc;
e429caa2
KH
145} *heap_ptr;
146
147#define NIL_HEAP ((heap_ptr) 0)
e429caa2 148
abe9ff32
RS
149/* This is the first heap object.
150 If we need additional heap objects, each one resides at the beginning of
151 the space it covers. */
152static struct heap heap_base;
153
154/* Head and tail of the list of heaps. */
e429caa2
KH
155static heap_ptr first_heap, last_heap;
156
157/* These structures are allocated in the malloc arena.
158 The linked list is kept in order of increasing '.data' members.
159 The data blocks abut each other; if b->next is non-nil, then
177c0ea7 160 b->data + b->size == b->next->data.
49f82b3d
RS
161
162 An element with variable==NIL denotes a freed block, which has not yet
f96f2c5b
JB
163 been collected. They may only appear while r_alloc_freeze_level > 0,
164 and will be freed when the arena is thawed. Currently, these blocs are
165 not reusable, while the arena is frozen. Very inefficient. */
49f82b3d 166
e429caa2
KH
167typedef struct bp
168{
169 struct bp *next;
170 struct bp *prev;
171 POINTER *variable;
172 POINTER data;
173 SIZE size;
8e6208c5 174 POINTER new_data; /* temporarily used for relocation */
49f82b3d 175 struct heap *heap; /* Heap this bloc is in. */
e429caa2
KH
176} *bloc_ptr;
177
178#define NIL_BLOC ((bloc_ptr) 0)
179#define BLOC_PTR_SIZE (sizeof (struct bp))
180
abe9ff32 181/* Head and tail of the list of relocatable blocs. */
e429caa2
KH
182static bloc_ptr first_bloc, last_bloc;
183
49f82b3d
RS
184static int use_relocatable_buffers;
185
186/* If >0, no relocation whatsoever takes place. */
187static int r_alloc_freeze_level;
188
dcfdbac7 189\f
956ace37
JB
190/* Functions to get and return memory from the system. */
191
abe9ff32
RS
192/* Find the heap that ADDRESS falls within. */
193
194static heap_ptr
971de7fb 195find_heap (POINTER address)
abe9ff32
RS
196{
197 heap_ptr heap;
198
199 for (heap = last_heap; heap; heap = heap->prev)
200 {
201 if (heap->start <= address && address <= heap->end)
202 return heap;
203 }
204
205 return NIL_HEAP;
206}
207
208/* Find SIZE bytes of space in a heap.
209 Try to get them at ADDRESS (which must fall within some heap's range)
210 if we can get that many within one heap.
211
e429caa2 212 If enough space is not presently available in our reserve, this means
8e6208c5
KH
213 getting more page-aligned space from the system. If the returned space
214 is not contiguous to the last heap, allocate a new heap, and append it
0d26e0b6 215 to the heap list.
abe9ff32 216
0d26e0b6
JB
217 obtain does not try to keep track of whether space is in use or not
218 in use. It just returns the address of SIZE bytes that fall within a
219 single heap. If you call obtain twice in a row with the same arguments,
220 you typically get the same value. It's the caller's responsibility to
221 keep track of what space is in use.
dcfdbac7 222
e429caa2
KH
223 Return the address of the space if all went well, or zero if we couldn't
224 allocate the memory. */
abe9ff32 225
e429caa2 226static POINTER
971de7fb 227obtain (POINTER address, SIZE size)
dcfdbac7 228{
e429caa2
KH
229 heap_ptr heap;
230 SIZE already_available;
dcfdbac7 231
abe9ff32 232 /* Find the heap that ADDRESS falls within. */
e429caa2 233 for (heap = last_heap; heap; heap = heap->prev)
dcfdbac7 234 {
e429caa2
KH
235 if (heap->start <= address && address <= heap->end)
236 break;
237 }
dcfdbac7 238
e429caa2 239 if (! heap)
1088b922 240 emacs_abort ();
dcfdbac7 241
abe9ff32
RS
242 /* If we can't fit SIZE bytes in that heap,
243 try successive later heaps. */
91a211b5 244 while (heap && (char *) address + size > (char *) heap->end)
e429caa2
KH
245 {
246 heap = heap->next;
247 if (heap == NIL_HEAP)
248 break;
249 address = heap->bloc_start;
dcfdbac7
JB
250 }
251
abe9ff32
RS
252 /* If we can't fit them within any existing heap,
253 get more space. */
e429caa2
KH
254 if (heap == NIL_HEAP)
255 {
256 POINTER new = (*real_morecore)(0);
257 SIZE get;
98b7fe02 258
e429caa2 259 already_available = (char *)last_heap->end - (char *)address;
dcfdbac7 260
e429caa2
KH
261 if (new != last_heap->end)
262 {
abe9ff32
RS
263 /* Someone else called sbrk. Make a new heap. */
264
265 heap_ptr new_heap = (heap_ptr) MEM_ROUNDUP (new);
266 POINTER bloc_start = (POINTER) MEM_ROUNDUP ((POINTER)(new_heap + 1));
e429caa2 267
91a211b5 268 if ((*real_morecore) ((char *) bloc_start - (char *) new) != new)
e429caa2
KH
269 return 0;
270
271 new_heap->start = new;
272 new_heap->end = bloc_start;
273 new_heap->bloc_start = bloc_start;
abe9ff32 274 new_heap->free = bloc_start;
e429caa2
KH
275 new_heap->next = NIL_HEAP;
276 new_heap->prev = last_heap;
47f13333
RS
277 new_heap->first_bloc = NIL_BLOC;
278 new_heap->last_bloc = NIL_BLOC;
e429caa2
KH
279 last_heap->next = new_heap;
280 last_heap = new_heap;
281
282 address = bloc_start;
283 already_available = 0;
284 }
dcfdbac7 285
abe9ff32
RS
286 /* Add space to the last heap (which we may have just created).
287 Get some extra, so we can come here less often. */
288
e429caa2 289 get = size + extra_bytes - already_available;
abe9ff32 290 get = (char *) ROUNDUP ((char *)last_heap->end + get)
e429caa2 291 - (char *) last_heap->end;
dcfdbac7 292
e429caa2
KH
293 if ((*real_morecore) (get) != last_heap->end)
294 return 0;
295
91a211b5 296 last_heap->end = (char *) last_heap->end + get;
e429caa2
KH
297 }
298
299 return address;
300}
dcfdbac7 301
abe9ff32
RS
302/* Return unused heap space to the system
303 if there is a lot of unused space now.
304 This can make the last heap smaller;
305 it can also eliminate the last heap entirely. */
306
dcfdbac7 307static void
971de7fb 308relinquish (void)
dcfdbac7 309{
e429caa2 310 register heap_ptr h;
8d31e373 311 long excess = 0;
e429caa2 312
abe9ff32
RS
313 /* Add the amount of space beyond break_value
314 in all heaps which have extend beyond break_value at all. */
315
e429caa2
KH
316 for (h = last_heap; h && break_value < h->end; h = h->prev)
317 {
318 excess += (char *) h->end - (char *) ((break_value < h->bloc_start)
319 ? h->bloc_start : break_value);
320 }
321
322 if (excess > extra_bytes * 2 && (*real_morecore) (0) == last_heap->end)
dcfdbac7 323 {
7516b7d5
RS
324 /* Keep extra_bytes worth of empty space.
325 And don't free anything unless we can free at least extra_bytes. */
e429caa2 326 excess -= extra_bytes;
dcfdbac7 327
e429caa2
KH
328 if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess)
329 {
47f13333
RS
330 /* This heap should have no blocs in it. */
331 if (last_heap->first_bloc != NIL_BLOC
332 || last_heap->last_bloc != NIL_BLOC)
1088b922 333 emacs_abort ();
47f13333 334
abe9ff32 335 /* Return the last heap, with its header, to the system. */
e429caa2
KH
336 excess = (char *)last_heap->end - (char *)last_heap->start;
337 last_heap = last_heap->prev;
338 last_heap->next = NIL_HEAP;
339 }
340 else
341 {
342 excess = (char *) last_heap->end
abe9ff32 343 - (char *) ROUNDUP ((char *)last_heap->end - excess);
91a211b5 344 last_heap->end = (char *) last_heap->end - excess;
e429caa2 345 }
dcfdbac7 346
e429caa2 347 if ((*real_morecore) (- excess) == 0)
21532667
KH
348 {
349 /* If the system didn't want that much memory back, adjust
350 the end of the last heap to reflect that. This can occur
351 if break_value is still within the original data segment. */
91a211b5 352 last_heap->end = (char *) last_heap->end + excess;
21532667
KH
353 /* Make sure that the result of the adjustment is accurate.
354 It should be, for the else clause above; the other case,
355 which returns the entire last heap to the system, seems
356 unlikely to trigger this mode of failure. */
357 if (last_heap->end != (*real_morecore) (0))
1088b922 358 emacs_abort ();
21532667 359 }
e429caa2 360 }
dcfdbac7
JB
361}
362\f
956ace37
JB
363/* The meat - allocating, freeing, and relocating blocs. */
364
956ace37 365/* Find the bloc referenced by the address in PTR. Returns a pointer
abe9ff32 366 to that block. */
dcfdbac7
JB
367
368static bloc_ptr
971de7fb 369find_bloc (POINTER *ptr)
dcfdbac7
JB
370{
371 register bloc_ptr p = first_bloc;
372
373 while (p != NIL_BLOC)
374 {
747d9d14 375 /* Consistency check. Don't return inconsistent blocs.
0d26e0b6 376 Don't abort here, as callers might be expecting this, but
747d9d14
JR
377 callers that always expect a bloc to be returned should abort
378 if one isn't to avoid a memory corruption bug that is
379 difficult to track down. */
dcfdbac7
JB
380 if (p->variable == ptr && p->data == *ptr)
381 return p;
382
383 p = p->next;
384 }
385
386 return p;
387}
388
389/* Allocate a bloc of SIZE bytes and append it to the chain of blocs.
98b7fe02
JB
390 Returns a pointer to the new bloc, or zero if we couldn't allocate
391 memory for the new block. */
dcfdbac7
JB
392
393static bloc_ptr
971de7fb 394get_bloc (SIZE size)
dcfdbac7 395{
98b7fe02 396 register bloc_ptr new_bloc;
abe9ff32 397 register heap_ptr heap;
98b7fe02 398
38182d90 399 if (! (new_bloc = malloc (BLOC_PTR_SIZE))
e429caa2 400 || ! (new_bloc->data = obtain (break_value, size)))
98b7fe02 401 {
c2cd06e6 402 free (new_bloc);
98b7fe02
JB
403
404 return 0;
405 }
dcfdbac7 406
91a211b5 407 break_value = (char *) new_bloc->data + size;
e429caa2 408
dcfdbac7
JB
409 new_bloc->size = size;
410 new_bloc->next = NIL_BLOC;
8c7f1e35 411 new_bloc->variable = (POINTER *) NIL;
e429caa2 412 new_bloc->new_data = 0;
dcfdbac7 413
abe9ff32
RS
414 /* Record in the heap that this space is in use. */
415 heap = find_heap (new_bloc->data);
416 heap->free = break_value;
417
47f13333
RS
418 /* Maintain the correspondence between heaps and blocs. */
419 new_bloc->heap = heap;
420 heap->last_bloc = new_bloc;
421 if (heap->first_bloc == NIL_BLOC)
422 heap->first_bloc = new_bloc;
423
abe9ff32 424 /* Put this bloc on the doubly-linked list of blocs. */
dcfdbac7
JB
425 if (first_bloc)
426 {
427 new_bloc->prev = last_bloc;
428 last_bloc->next = new_bloc;
429 last_bloc = new_bloc;
430 }
431 else
432 {
433 first_bloc = last_bloc = new_bloc;
434 new_bloc->prev = NIL_BLOC;
435 }
436
437 return new_bloc;
438}
47f13333 439\f
abe9ff32
RS
440/* Calculate new locations of blocs in the list beginning with BLOC,
441 relocating it to start at ADDRESS, in heap HEAP. If enough space is
442 not presently available in our reserve, call obtain for
177c0ea7
JB
443 more space.
444
abe9ff32
RS
445 Store the new location of each bloc in its new_data field.
446 Do not touch the contents of blocs or break_value. */
dcfdbac7 447
e429caa2 448static int
971de7fb 449relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address)
e429caa2
KH
450{
451 register bloc_ptr b = bloc;
ad3bb3d2 452
49f82b3d 453 /* No need to ever call this if arena is frozen, bug somewhere! */
177c0ea7 454 if (r_alloc_freeze_level)
1088b922 455 emacs_abort ();
49f82b3d 456
e429caa2
KH
457 while (b)
458 {
abe9ff32
RS
459 /* If bloc B won't fit within HEAP,
460 move to the next heap and try again. */
91a211b5 461 while (heap && (char *) address + b->size > (char *) heap->end)
e429caa2
KH
462 {
463 heap = heap->next;
464 if (heap == NIL_HEAP)
465 break;
466 address = heap->bloc_start;
467 }
dcfdbac7 468
abe9ff32
RS
469 /* If BLOC won't fit in any heap,
470 get enough new space to hold BLOC and all following blocs. */
e429caa2
KH
471 if (heap == NIL_HEAP)
472 {
473 register bloc_ptr tb = b;
474 register SIZE s = 0;
475
abe9ff32 476 /* Add up the size of all the following blocs. */
e429caa2
KH
477 while (tb != NIL_BLOC)
478 {
177c0ea7 479 if (tb->variable)
49f82b3d
RS
480 s += tb->size;
481
e429caa2
KH
482 tb = tb->next;
483 }
484
abe9ff32
RS
485 /* Get that space. */
486 address = obtain (address, s);
487 if (address == 0)
e429caa2
KH
488 return 0;
489
490 heap = last_heap;
491 }
492
abe9ff32
RS
493 /* Record the new address of this bloc
494 and update where the next bloc can start. */
e429caa2 495 b->new_data = address;
177c0ea7 496 if (b->variable)
91a211b5 497 address = (char *) address + b->size;
e429caa2
KH
498 b = b->next;
499 }
500
501 return 1;
502}
47f13333
RS
503\f
504/* Update the records of which heaps contain which blocs, starting
505 with heap HEAP and bloc BLOC. */
506
507static void
971de7fb 508update_heap_bloc_correspondence (bloc_ptr bloc, heap_ptr heap)
abe9ff32
RS
509{
510 register bloc_ptr b;
511
47f13333
RS
512 /* Initialize HEAP's status to reflect blocs before BLOC. */
513 if (bloc != NIL_BLOC && bloc->prev != NIL_BLOC && bloc->prev->heap == heap)
514 {
515 /* The previous bloc is in HEAP. */
516 heap->last_bloc = bloc->prev;
91a211b5 517 heap->free = (char *) bloc->prev->data + bloc->prev->size;
47f13333
RS
518 }
519 else
520 {
521 /* HEAP contains no blocs before BLOC. */
522 heap->first_bloc = NIL_BLOC;
523 heap->last_bloc = NIL_BLOC;
524 heap->free = heap->bloc_start;
525 }
526
abe9ff32
RS
527 /* Advance through blocs one by one. */
528 for (b = bloc; b != NIL_BLOC; b = b->next)
529 {
47f13333
RS
530 /* Advance through heaps, marking them empty,
531 till we get to the one that B is in. */
abe9ff32
RS
532 while (heap)
533 {
534 if (heap->bloc_start <= b->data && b->data <= heap->end)
535 break;
536 heap = heap->next;
47f13333
RS
537 /* We know HEAP is not null now,
538 because there has to be space for bloc B. */
539 heap->first_bloc = NIL_BLOC;
540 heap->last_bloc = NIL_BLOC;
abe9ff32
RS
541 heap->free = heap->bloc_start;
542 }
47f13333
RS
543
544 /* Update HEAP's status for bloc B. */
91a211b5 545 heap->free = (char *) b->data + b->size;
47f13333
RS
546 heap->last_bloc = b;
547 if (heap->first_bloc == NIL_BLOC)
548 heap->first_bloc = b;
549
550 /* Record that B is in HEAP. */
551 b->heap = heap;
abe9ff32
RS
552 }
553
554 /* If there are any remaining heaps and no blocs left,
47f13333 555 mark those heaps as empty. */
abe9ff32
RS
556 heap = heap->next;
557 while (heap)
558 {
47f13333
RS
559 heap->first_bloc = NIL_BLOC;
560 heap->last_bloc = NIL_BLOC;
abe9ff32
RS
561 heap->free = heap->bloc_start;
562 heap = heap->next;
563 }
564}
47f13333 565\f
abe9ff32
RS
566/* Resize BLOC to SIZE bytes. This relocates the blocs
567 that come after BLOC in memory. */
568
e429caa2 569static int
971de7fb 570resize_bloc (bloc_ptr bloc, SIZE size)
dcfdbac7 571{
e429caa2
KH
572 register bloc_ptr b;
573 heap_ptr heap;
574 POINTER address;
575 SIZE old_size;
576
49f82b3d 577 /* No need to ever call this if arena is frozen, bug somewhere! */
177c0ea7 578 if (r_alloc_freeze_level)
1088b922 579 emacs_abort ();
49f82b3d 580
e429caa2
KH
581 if (bloc == NIL_BLOC || size == bloc->size)
582 return 1;
583
584 for (heap = first_heap; heap != NIL_HEAP; heap = heap->next)
585 {
586 if (heap->bloc_start <= bloc->data && bloc->data <= heap->end)
587 break;
588 }
589
590 if (heap == NIL_HEAP)
1088b922 591 emacs_abort ();
e429caa2
KH
592
593 old_size = bloc->size;
594 bloc->size = size;
595
abe9ff32 596 /* Note that bloc could be moved into the previous heap. */
91a211b5
GM
597 address = (bloc->prev ? (char *) bloc->prev->data + bloc->prev->size
598 : (char *) first_heap->bloc_start);
e429caa2
KH
599 while (heap)
600 {
601 if (heap->bloc_start <= address && address <= heap->end)
602 break;
603 heap = heap->prev;
604 }
605
606 if (! relocate_blocs (bloc, heap, address))
607 {
608 bloc->size = old_size;
609 return 0;
610 }
611
612 if (size > old_size)
613 {
614 for (b = last_bloc; b != bloc; b = b->prev)
615 {
49f82b3d
RS
616 if (!b->variable)
617 {
618 b->size = 0;
619 b->data = b->new_data;
177c0ea7
JB
620 }
621 else
49f82b3d 622 {
78cef877
EZ
623 if (b->new_data != b->data)
624 memmove (b->new_data, b->data, b->size);
49f82b3d
RS
625 *b->variable = b->data = b->new_data;
626 }
627 }
628 if (!bloc->variable)
629 {
630 bloc->size = 0;
631 bloc->data = bloc->new_data;
632 }
633 else
634 {
78cef877
EZ
635 if (bloc->new_data != bloc->data)
636 memmove (bloc->new_data, bloc->data, old_size);
3ce2f8ac 637 memset ((char *) bloc->new_data + old_size, 0, size - old_size);
49f82b3d 638 *bloc->variable = bloc->data = bloc->new_data;
e429caa2 639 }
e429caa2
KH
640 }
641 else
dcfdbac7 642 {
ad3bb3d2
JB
643 for (b = bloc; b != NIL_BLOC; b = b->next)
644 {
49f82b3d
RS
645 if (!b->variable)
646 {
647 b->size = 0;
648 b->data = b->new_data;
177c0ea7
JB
649 }
650 else
49f82b3d 651 {
78cef877
EZ
652 if (b->new_data != b->data)
653 memmove (b->new_data, b->data, b->size);
49f82b3d
RS
654 *b->variable = b->data = b->new_data;
655 }
ad3bb3d2 656 }
ad3bb3d2 657 }
dcfdbac7 658
47f13333 659 update_heap_bloc_correspondence (bloc, heap);
abe9ff32 660
91a211b5
GM
661 break_value = (last_bloc ? (char *) last_bloc->data + last_bloc->size
662 : (char *) first_heap->bloc_start);
e429caa2
KH
663 return 1;
664}
47f13333 665\f
abe9ff32
RS
666/* Free BLOC from the chain of blocs, relocating any blocs above it.
667 This may return space to the system. */
dcfdbac7
JB
668
669static void
971de7fb 670free_bloc (bloc_ptr bloc)
dcfdbac7 671{
47f13333 672 heap_ptr heap = bloc->heap;
36c46f8e 673 heap_ptr h;
47f13333 674
49f82b3d
RS
675 if (r_alloc_freeze_level)
676 {
677 bloc->variable = (POINTER *) NIL;
678 return;
679 }
177c0ea7 680
e429caa2
KH
681 resize_bloc (bloc, 0);
682
dcfdbac7
JB
683 if (bloc == first_bloc && bloc == last_bloc)
684 {
685 first_bloc = last_bloc = NIL_BLOC;
686 }
687 else if (bloc == last_bloc)
688 {
689 last_bloc = bloc->prev;
690 last_bloc->next = NIL_BLOC;
691 }
692 else if (bloc == first_bloc)
693 {
694 first_bloc = bloc->next;
695 first_bloc->prev = NIL_BLOC;
dcfdbac7
JB
696 }
697 else
698 {
699 bloc->next->prev = bloc->prev;
700 bloc->prev->next = bloc->next;
dcfdbac7
JB
701 }
702
36c46f8e
EZ
703 /* Sometimes, 'heap' obtained from bloc->heap above is not really a
704 'heap' structure. It can even be beyond the current break point,
705 which will cause crashes when we dereference it below (see
706 bug#12242). Evidently, the reason is bloc allocations done while
707 use_relocatable_buffers was non-positive, because additional
708 memory we get then is not recorded in the heaps we manage. If
709 bloc->heap records such a "heap", we cannot (and don't need to)
710 update its records. So we validate the 'heap' value by making
711 sure it is one of the heaps we manage via the heaps linked list,
712 and don't touch a 'heap' that isn't found there. This avoids
713 accessing memory we know nothing about. */
714 for (h = first_heap; h != NIL_HEAP; h = h->next)
715 if (heap == h)
716 break;
717
718 if (h)
47f13333 719 {
36c46f8e
EZ
720 /* Update the records of which blocs are in HEAP. */
721 if (heap->first_bloc == bloc)
722 {
723 if (bloc->next != 0 && bloc->next->heap == heap)
724 heap->first_bloc = bloc->next;
725 else
726 heap->first_bloc = heap->last_bloc = NIL_BLOC;
727 }
728 if (heap->last_bloc == bloc)
729 {
730 if (bloc->prev != 0 && bloc->prev->heap == heap)
731 heap->last_bloc = bloc->prev;
732 else
733 heap->first_bloc = heap->last_bloc = NIL_BLOC;
734 }
47f13333
RS
735 }
736
e429caa2 737 relinquish ();
dcfdbac7
JB
738 free (bloc);
739}
740\f
956ace37
JB
741/* Interface routines. */
742
98b7fe02 743/* Obtain SIZE bytes of storage from the free pool, or the system, as
2c46d29f 744 necessary. If relocatable blocs are in use, this means relocating
98b7fe02
JB
745 them. This function gets plugged into the GNU malloc's __morecore
746 hook.
747
7516b7d5
RS
748 We provide hysteresis, never relocating by less than extra_bytes.
749
98b7fe02
JB
750 If we're out of memory, we should return zero, to imitate the other
751 __morecore hook values - in particular, __default_morecore in the
752 GNU malloc package. */
dcfdbac7 753
3539f31f 754static POINTER
971de7fb 755r_alloc_sbrk (long int size)
dcfdbac7 756{
e429caa2
KH
757 register bloc_ptr b;
758 POINTER address;
dcfdbac7 759
44d3dec0
RS
760 if (! r_alloc_initialized)
761 r_alloc_init ();
762
e8a02204 763 if (use_relocatable_buffers <= 0)
bbc60227 764 return (*real_morecore) (size);
dcfdbac7 765
e429caa2
KH
766 if (size == 0)
767 return virtual_break_value;
7516b7d5 768
e429caa2 769 if (size > 0)
dcfdbac7 770 {
abe9ff32
RS
771 /* Allocate a page-aligned space. GNU malloc would reclaim an
772 extra space if we passed an unaligned one. But we could
8e6208c5 773 not always find a space which is contiguous to the previous. */
e429caa2
KH
774 POINTER new_bloc_start;
775 heap_ptr h = first_heap;
abe9ff32 776 SIZE get = ROUNDUP (size);
7516b7d5 777
abe9ff32 778 address = (POINTER) ROUNDUP (virtual_break_value);
e429caa2 779
abe9ff32
RS
780 /* Search the list upward for a heap which is large enough. */
781 while ((char *) h->end < (char *) MEM_ROUNDUP ((char *)address + get))
e429caa2
KH
782 {
783 h = h->next;
784 if (h == NIL_HEAP)
785 break;
abe9ff32 786 address = (POINTER) ROUNDUP (h->start);
e429caa2
KH
787 }
788
abe9ff32 789 /* If not found, obtain more space. */
e429caa2
KH
790 if (h == NIL_HEAP)
791 {
792 get += extra_bytes + page_size;
793
49f82b3d 794 if (! obtain (address, get))
e429caa2 795 return 0;
98b7fe02 796
e429caa2 797 if (first_heap == last_heap)
abe9ff32 798 address = (POINTER) ROUNDUP (virtual_break_value);
e429caa2 799 else
abe9ff32 800 address = (POINTER) ROUNDUP (last_heap->start);
e429caa2
KH
801 h = last_heap;
802 }
803
abe9ff32 804 new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get);
e429caa2
KH
805
806 if (first_heap->bloc_start < new_bloc_start)
807 {
49f82b3d 808 /* This is no clean solution - no idea how to do it better. */
177c0ea7 809 if (r_alloc_freeze_level)
49f82b3d
RS
810 return NIL;
811
812 /* There is a bug here: if the above obtain call succeeded, but the
813 relocate_blocs call below does not succeed, we need to free
814 the memory that we got with obtain. */
815
abe9ff32 816 /* Move all blocs upward. */
49f82b3d 817 if (! relocate_blocs (first_bloc, h, new_bloc_start))
e429caa2
KH
818 return 0;
819
820 /* Note that (POINTER)(h+1) <= new_bloc_start since
821 get >= page_size, so the following does not destroy the heap
abe9ff32 822 header. */
e429caa2
KH
823 for (b = last_bloc; b != NIL_BLOC; b = b->prev)
824 {
78cef877
EZ
825 if (b->new_data != b->data)
826 memmove (b->new_data, b->data, b->size);
e429caa2
KH
827 *b->variable = b->data = b->new_data;
828 }
829
830 h->bloc_start = new_bloc_start;
abe9ff32 831
47f13333 832 update_heap_bloc_correspondence (first_bloc, h);
e429caa2 833 }
e429caa2
KH
834 if (h != first_heap)
835 {
836 /* Give up managing heaps below the one the new
abe9ff32 837 virtual_break_value points to. */
e429caa2
KH
838 first_heap->prev = NIL_HEAP;
839 first_heap->next = h->next;
840 first_heap->start = h->start;
841 first_heap->end = h->end;
abe9ff32 842 first_heap->free = h->free;
47f13333
RS
843 first_heap->first_bloc = h->first_bloc;
844 first_heap->last_bloc = h->last_bloc;
e429caa2
KH
845 first_heap->bloc_start = h->bloc_start;
846
847 if (first_heap->next)
848 first_heap->next->prev = first_heap;
849 else
850 last_heap = first_heap;
851 }
852
72af86bd 853 memset (address, 0, size);
dcfdbac7 854 }
e429caa2 855 else /* size < 0 */
dcfdbac7 856 {
e429caa2
KH
857 SIZE excess = (char *)first_heap->bloc_start
858 - ((char *)virtual_break_value + size);
859
860 address = virtual_break_value;
861
862 if (r_alloc_freeze_level == 0 && excess > 2 * extra_bytes)
863 {
864 excess -= extra_bytes;
865 first_heap->bloc_start
47f13333 866 = (POINTER) MEM_ROUNDUP ((char *)first_heap->bloc_start - excess);
e429caa2 867
abe9ff32 868 relocate_blocs (first_bloc, first_heap, first_heap->bloc_start);
7516b7d5 869
e429caa2
KH
870 for (b = first_bloc; b != NIL_BLOC; b = b->next)
871 {
78cef877
EZ
872 if (b->new_data != b->data)
873 memmove (b->new_data, b->data, b->size);
e429caa2
KH
874 *b->variable = b->data = b->new_data;
875 }
876 }
877
878 if ((char *)virtual_break_value + size < (char *)first_heap->start)
879 {
880 /* We found an additional space below the first heap */
881 first_heap->start = (POINTER) ((char *)virtual_break_value + size);
882 }
dcfdbac7
JB
883 }
884
e429caa2 885 virtual_break_value = (POINTER) ((char *)address + size);
47f13333 886 break_value = (last_bloc
91a211b5
GM
887 ? (char *) last_bloc->data + last_bloc->size
888 : (char *) first_heap->bloc_start);
e429caa2 889 if (size < 0)
abe9ff32 890 relinquish ();
7516b7d5 891
e429caa2 892 return address;
dcfdbac7
JB
893}
894
0a58f946 895
dcfdbac7
JB
896/* Allocate a relocatable bloc of storage of size SIZE. A pointer to
897 the data is returned in *PTR. PTR is thus the address of some variable
98b7fe02
JB
898 which will use the data area.
899
49f82b3d 900 The allocation of 0 bytes is valid.
f96f2c5b
JB
901 In case r_alloc_freeze_level is set, a best fit of unused blocs could be
902 done before allocating a new area. Not yet done.
49f82b3d 903
98b7fe02
JB
904 If we can't allocate the necessary memory, set *PTR to zero, and
905 return zero. */
dcfdbac7
JB
906
907POINTER
971de7fb 908r_alloc (POINTER *ptr, SIZE size)
dcfdbac7
JB
909{
910 register bloc_ptr new_bloc;
911
2c46d29f
RS
912 if (! r_alloc_initialized)
913 r_alloc_init ();
914
abe9ff32 915 new_bloc = get_bloc (MEM_ROUNDUP (size));
98b7fe02
JB
916 if (new_bloc)
917 {
918 new_bloc->variable = ptr;
919 *ptr = new_bloc->data;
920 }
921 else
922 *ptr = 0;
dcfdbac7
JB
923
924 return *ptr;
925}
926
2c46d29f
RS
927/* Free a bloc of relocatable storage whose data is pointed to by PTR.
928 Store 0 in *PTR to show there's no block allocated. */
dcfdbac7
JB
929
930void
971de7fb 931r_alloc_free (register POINTER *ptr)
dcfdbac7
JB
932{
933 register bloc_ptr dead_bloc;
934
44d3dec0
RS
935 if (! r_alloc_initialized)
936 r_alloc_init ();
937
dcfdbac7
JB
938 dead_bloc = find_bloc (ptr);
939 if (dead_bloc == NIL_BLOC)
1088b922 940 emacs_abort (); /* Double free? PTR not originally used to allocate? */
dcfdbac7
JB
941
942 free_bloc (dead_bloc);
2c46d29f 943 *ptr = 0;
719b242f 944
d5179acc 945#ifdef emacs
719b242f 946 refill_memory_reserve ();
d5179acc 947#endif
dcfdbac7
JB
948}
949
16a5c729 950/* Given a pointer at address PTR to relocatable data, resize it to SIZE.
98b7fe02
JB
951 Do this by shifting all blocks above this one up in memory, unless
952 SIZE is less than or equal to the current bloc size, in which case
953 do nothing.
dcfdbac7 954
f96f2c5b 955 In case r_alloc_freeze_level is set, a new bloc is allocated, and the
8e6208c5 956 memory copied to it. Not very efficient. We could traverse the
49f82b3d
RS
957 bloc_list for a best fit of free blocs first.
958
98b7fe02
JB
959 Change *PTR to reflect the new bloc, and return this value.
960
961 If more memory cannot be allocated, then leave *PTR unchanged, and
962 return zero. */
dcfdbac7
JB
963
964POINTER
971de7fb 965r_re_alloc (POINTER *ptr, SIZE size)
dcfdbac7 966{
16a5c729 967 register bloc_ptr bloc;
dcfdbac7 968
44d3dec0
RS
969 if (! r_alloc_initialized)
970 r_alloc_init ();
971
49f82b3d
RS
972 if (!*ptr)
973 return r_alloc (ptr, size);
177c0ea7 974 if (!size)
49f82b3d
RS
975 {
976 r_alloc_free (ptr);
977 return r_alloc (ptr, 0);
978 }
979
16a5c729
JB
980 bloc = find_bloc (ptr);
981 if (bloc == NIL_BLOC)
1088b922 982 emacs_abort (); /* Already freed? PTR not originally used to allocate? */
dcfdbac7 983
177c0ea7 984 if (size < bloc->size)
49f82b3d
RS
985 {
986 /* Wouldn't it be useful to actually resize the bloc here? */
987 /* I think so too, but not if it's too expensive... */
177c0ea7
JB
988 if ((bloc->size - MEM_ROUNDUP (size) >= page_size)
989 && r_alloc_freeze_level == 0)
49f82b3d
RS
990 {
991 resize_bloc (bloc, MEM_ROUNDUP (size));
992 /* Never mind if this fails, just do nothing... */
993 /* It *should* be infallible! */
994 }
995 }
996 else if (size > bloc->size)
997 {
998 if (r_alloc_freeze_level)
999 {
1000 bloc_ptr new_bloc;
1001 new_bloc = get_bloc (MEM_ROUNDUP (size));
1002 if (new_bloc)
1003 {
1004 new_bloc->variable = ptr;
1005 *ptr = new_bloc->data;
1006 bloc->variable = (POINTER *) NIL;
1007 }
1008 else
1009 return NIL;
1010 }
177c0ea7 1011 else
49f82b3d
RS
1012 {
1013 if (! resize_bloc (bloc, MEM_ROUNDUP (size)))
1014 return NIL;
1015 }
1016 }
dcfdbac7
JB
1017 return *ptr;
1018}
81bd58e8 1019
dec41418
RS
1020
1021#if defined (emacs) && defined (DOUG_LEA_MALLOC)
1022
1023/* Reinitialize the morecore hook variables after restarting a dumped
1024 Emacs. This is needed when using Doug Lea's malloc from GNU libc. */
1025void
971de7fb 1026r_alloc_reinit (void)
dec41418
RS
1027{
1028 /* Only do this if the hook has been reset, so that we don't get an
1029 infinite loop, in case Emacs was linked statically. */
1030 if (__morecore != r_alloc_sbrk)
1031 {
1032 real_morecore = __morecore;
1033 __morecore = r_alloc_sbrk;
1034 }
1035}
0a58f946
GM
1036
1037#endif /* emacs && DOUG_LEA_MALLOC */
dec41418 1038
e429caa2 1039#ifdef DEBUG
0a58f946 1040
e429caa2
KH
1041#include <assert.h>
1042
44d3dec0 1043void
268c2c36 1044r_alloc_check (void)
e429caa2 1045{
6d16dd06
RS
1046 int found = 0;
1047 heap_ptr h, ph = 0;
1048 bloc_ptr b, pb = 0;
1049
1050 if (!r_alloc_initialized)
1051 return;
1052
1053 assert (first_heap);
1054 assert (last_heap->end <= (POINTER) sbrk (0));
1055 assert ((POINTER) first_heap < first_heap->start);
1056 assert (first_heap->start <= virtual_break_value);
1057 assert (virtual_break_value <= first_heap->end);
1058
1059 for (h = first_heap; h; h = h->next)
1060 {
1061 assert (h->prev == ph);
1062 assert ((POINTER) ROUNDUP (h->end) == h->end);
40f3f04b
RS
1063#if 0 /* ??? The code in ralloc.c does not really try to ensure
1064 the heap start has any sort of alignment.
1065 Perhaps it should. */
6d16dd06 1066 assert ((POINTER) MEM_ROUNDUP (h->start) == h->start);
40f3f04b 1067#endif
6d16dd06
RS
1068 assert ((POINTER) MEM_ROUNDUP (h->bloc_start) == h->bloc_start);
1069 assert (h->start <= h->bloc_start && h->bloc_start <= h->end);
1070
1071 if (ph)
1072 {
1073 assert (ph->end < h->start);
1074 assert (h->start <= (POINTER)h && (POINTER)(h+1) <= h->bloc_start);
1075 }
1076
1077 if (h->bloc_start <= break_value && break_value <= h->end)
1078 found = 1;
1079
1080 ph = h;
1081 }
1082
1083 assert (found);
1084 assert (last_heap == ph);
1085
1086 for (b = first_bloc; b; b = b->next)
1087 {
1088 assert (b->prev == pb);
1089 assert ((POINTER) MEM_ROUNDUP (b->data) == b->data);
1090 assert ((SIZE) MEM_ROUNDUP (b->size) == b->size);
1091
1092 ph = 0;
1093 for (h = first_heap; h; h = h->next)
1094 {
1095 if (h->bloc_start <= b->data && b->data + b->size <= h->end)
1096 break;
1097 ph = h;
1098 }
1099
1100 assert (h);
1101
1102 if (pb && pb->data + pb->size != b->data)
1103 {
1104 assert (ph && b->data == h->bloc_start);
1105 while (ph)
1106 {
1107 if (ph->bloc_start <= pb->data
1108 && pb->data + pb->size <= ph->end)
1109 {
1110 assert (pb->data + pb->size + b->size > ph->end);
1111 break;
1112 }
1113 else
1114 {
1115 assert (ph->bloc_start + b->size > ph->end);
1116 }
1117 ph = ph->prev;
1118 }
1119 }
1120 pb = b;
1121 }
1122
1123 assert (last_bloc == pb);
1124
1125 if (last_bloc)
1126 assert (last_bloc->data + last_bloc->size == break_value);
1127 else
1128 assert (first_heap->bloc_start == break_value);
e429caa2 1129}
0a58f946 1130
e429caa2 1131#endif /* DEBUG */
0a58f946 1132
baae5c2d
JR
1133/* Update the internal record of which variable points to some data to NEW.
1134 Used by buffer-swap-text in Emacs to restore consistency after it
1135 swaps the buffer text between two buffer objects. The OLD pointer
1136 is checked to ensure that memory corruption does not occur due to
1137 misuse. */
1138void
971de7fb 1139r_alloc_reset_variable (POINTER *old, POINTER *new)
baae5c2d
JR
1140{
1141 bloc_ptr bloc = first_bloc;
1142
1143 /* Find the bloc that corresponds to the data pointed to by pointer.
1144 find_bloc cannot be used, as it has internal consistency checks
0d26e0b6 1145 which fail when the variable needs resetting. */
baae5c2d
JR
1146 while (bloc != NIL_BLOC)
1147 {
1148 if (bloc->data == *new)
1149 break;
1150
1151 bloc = bloc->next;
1152 }
1153
1154 if (bloc == NIL_BLOC || bloc->variable != old)
1088b922 1155 emacs_abort (); /* Already freed? OLD not originally used to allocate? */
baae5c2d
JR
1156
1157 /* Update variable to point to the new location. */
1158 bloc->variable = new;
1159}
0a58f946 1160
52c55cc7
EZ
1161void
1162r_alloc_inhibit_buffer_relocation (int inhibit)
1163{
e8a02204
EZ
1164 if (use_relocatable_buffers > 1)
1165 use_relocatable_buffers = 1;
291d430f 1166 if (inhibit)
291d430f 1167 use_relocatable_buffers--;
e8a02204
EZ
1168 else if (use_relocatable_buffers < 1)
1169 use_relocatable_buffers++;
52c55cc7
EZ
1170}
1171
0a58f946
GM
1172\f
1173/***********************************************************************
1174 Initialization
1175 ***********************************************************************/
1176
0a58f946
GM
1177/* Initialize various things for memory allocation. */
1178
1179static void
971de7fb 1180r_alloc_init (void)
0a58f946
GM
1181{
1182 if (r_alloc_initialized)
1183 return;
0a58f946 1184 r_alloc_initialized = 1;
177c0ea7 1185
a2c23c92
DL
1186 page_size = PAGE;
1187#ifndef SYSTEM_MALLOC
0a58f946
GM
1188 real_morecore = __morecore;
1189 __morecore = r_alloc_sbrk;
1190
1191 first_heap = last_heap = &heap_base;
1192 first_heap->next = first_heap->prev = NIL_HEAP;
1193 first_heap->start = first_heap->bloc_start
1194 = virtual_break_value = break_value = (*real_morecore) (0);
1195 if (break_value == NIL)
1088b922 1196 emacs_abort ();
0a58f946 1197
0a58f946 1198 extra_bytes = ROUNDUP (50000);
a2c23c92 1199#endif
0a58f946
GM
1200
1201#ifdef DOUG_LEA_MALLOC
4d7e6e51 1202 block_input ();
1673df2e 1203 mallopt (M_TOP_PAD, 64 * 4096);
4d7e6e51 1204 unblock_input ();
0a58f946 1205#else
a2c23c92 1206#ifndef SYSTEM_MALLOC
45ba16c7
EZ
1207 /* Give GNU malloc's morecore some hysteresis so that we move all
1208 the relocatable blocks much less often. The number used to be
1209 64, but alloc.c would override that with 32 in code that was
1210 removed when SYNC_INPUT became the only input handling mode.
9b318728 1211 That code was conditioned on !DOUG_LEA_MALLOC, so the call to
45ba16c7
EZ
1212 mallopt above is left unchanged. (Actually, I think there's no
1213 system nowadays that uses DOUG_LEA_MALLOC and also uses
1214 REL_ALLOC.) */
1215 __malloc_extra_blocks = 32;
0a58f946 1216#endif
a2c23c92 1217#endif
0a58f946 1218
5ad25b24 1219#ifndef SYSTEM_MALLOC
0a58f946
GM
1220 first_heap->end = (POINTER) ROUNDUP (first_heap->start);
1221
1222 /* The extra call to real_morecore guarantees that the end of the
1223 address space is a multiple of page_size, even if page_size is
1224 not really the page size of the system running the binary in
1225 which page_size is stored. This allows a binary to be built on a
1226 system with one page size and run on a system with a smaller page
1227 size. */
91a211b5 1228 (*real_morecore) ((char *) first_heap->end - (char *) first_heap->start);
0a58f946
GM
1229
1230 /* Clear the rest of the last page; this memory is in our address space
1231 even though it is after the sbrk value. */
1232 /* Doubly true, with the additional call that explicitly adds the
1233 rest of that page to the address space. */
72af86bd
AS
1234 memset (first_heap->start, 0,
1235 (char *) first_heap->end - (char *) first_heap->start);
0a58f946 1236 virtual_break_value = break_value = first_heap->bloc_start = first_heap->end;
a2c23c92 1237#endif
177c0ea7 1238
0a58f946
GM
1239 use_relocatable_buffers = 1;
1240}