diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 489 |
1 files changed, 66 insertions, 423 deletions
diff --git a/src/alloc.c b/src/alloc.c index 61cb7086c25..02ba2f5f9e3 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -24,7 +24,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 24 | 24 | ||
| 25 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | #include <limits.h> /* For CHAR_BIT. */ | 26 | #include <limits.h> /* For CHAR_BIT. */ |
| 27 | #include <setjmp.h> | ||
| 28 | 27 | ||
| 29 | #ifdef ENABLE_CHECKING | 28 | #ifdef ENABLE_CHECKING |
| 30 | #include <signal.h> /* For SIGABRT. */ | 29 | #include <signal.h> /* For SIGABRT. */ |
| @@ -45,7 +44,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 45 | #include "frame.h" | 44 | #include "frame.h" |
| 46 | #include "blockinput.h" | 45 | #include "blockinput.h" |
| 47 | #include "termhooks.h" /* For struct terminal. */ | 46 | #include "termhooks.h" /* For struct terminal. */ |
| 48 | #include <setjmp.h> | 47 | |
| 49 | #include <verify.h> | 48 | #include <verify.h> |
| 50 | 49 | ||
| 51 | /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. | 50 | /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. |
| @@ -86,66 +85,8 @@ extern void *sbrk (); | |||
| 86 | 85 | ||
| 87 | #define MMAP_MAX_AREAS 100000000 | 86 | #define MMAP_MAX_AREAS 100000000 |
| 88 | 87 | ||
| 89 | #else /* not DOUG_LEA_MALLOC */ | ||
| 90 | |||
| 91 | /* The following come from gmalloc.c. */ | ||
| 92 | |||
| 93 | extern size_t _bytes_used; | ||
| 94 | extern size_t __malloc_extra_blocks; | ||
| 95 | extern void *_malloc_internal (size_t); | ||
| 96 | extern void _free_internal (void *); | ||
| 97 | |||
| 98 | #endif /* not DOUG_LEA_MALLOC */ | 88 | #endif /* not DOUG_LEA_MALLOC */ |
| 99 | 89 | ||
| 100 | #if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT | ||
| 101 | #ifdef HAVE_PTHREAD | ||
| 102 | |||
| 103 | /* When GTK uses the file chooser dialog, different backends can be loaded | ||
| 104 | dynamically. One such a backend is the Gnome VFS backend that gets loaded | ||
| 105 | if you run Gnome. That backend creates several threads and also allocates | ||
| 106 | memory with malloc. | ||
| 107 | |||
| 108 | Also, gconf and gsettings may create several threads. | ||
| 109 | |||
| 110 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* | ||
| 111 | functions below are called from malloc, there is a chance that one | ||
| 112 | of these threads preempts the Emacs main thread and the hook variables | ||
| 113 | end up in an inconsistent state. So we have a mutex to prevent that (note | ||
| 114 | that the backend handles concurrent access to malloc within its own threads | ||
| 115 | but Emacs code running in the main thread is not included in that control). | ||
| 116 | |||
| 117 | When UNBLOCK_INPUT is called, reinvoke_input_signal may be called. If this | ||
| 118 | happens in one of the backend threads we will have two threads that tries | ||
| 119 | to run Emacs code at once, and the code is not prepared for that. | ||
| 120 | To prevent that, we only call BLOCK/UNBLOCK from the main thread. */ | ||
| 121 | |||
| 122 | static pthread_mutex_t alloc_mutex; | ||
| 123 | |||
| 124 | #define BLOCK_INPUT_ALLOC \ | ||
| 125 | do \ | ||
| 126 | { \ | ||
| 127 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 128 | BLOCK_INPUT; \ | ||
| 129 | pthread_mutex_lock (&alloc_mutex); \ | ||
| 130 | } \ | ||
| 131 | while (0) | ||
| 132 | #define UNBLOCK_INPUT_ALLOC \ | ||
| 133 | do \ | ||
| 134 | { \ | ||
| 135 | pthread_mutex_unlock (&alloc_mutex); \ | ||
| 136 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 137 | UNBLOCK_INPUT; \ | ||
| 138 | } \ | ||
| 139 | while (0) | ||
| 140 | |||
| 141 | #else /* ! defined HAVE_PTHREAD */ | ||
| 142 | |||
| 143 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT | ||
| 144 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT | ||
| 145 | |||
| 146 | #endif /* ! defined HAVE_PTHREAD */ | ||
| 147 | #endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */ | ||
| 148 | |||
| 149 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer | 90 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer |
| 150 | to a struct Lisp_String. */ | 91 | to a struct Lisp_String. */ |
| 151 | 92 | ||
| @@ -204,10 +145,6 @@ static char *spare_memory[7]; | |||
| 204 | 145 | ||
| 205 | #define SPARE_MEMORY (1 << 14) | 146 | #define SPARE_MEMORY (1 << 14) |
| 206 | 147 | ||
| 207 | /* Number of extra blocks malloc should get when it needs more core. */ | ||
| 208 | |||
| 209 | static int malloc_hysteresis; | ||
| 210 | |||
| 211 | /* Initialize it to a nonzero value to force it into data space | 148 | /* Initialize it to a nonzero value to force it into data space |
| 212 | (rather than bss space). That way unexec will remap it into text | 149 | (rather than bss space). That way unexec will remap it into text |
| 213 | space (pure), on some systems. We have not implemented the | 150 | space (pure), on some systems. We have not implemented the |
| @@ -412,12 +349,12 @@ static void mark_memory (void *, void *); | |||
| 412 | static void mem_init (void); | 349 | static void mem_init (void); |
| 413 | static struct mem_node *mem_insert (void *, void *, enum mem_type); | 350 | static struct mem_node *mem_insert (void *, void *, enum mem_type); |
| 414 | static void mem_insert_fixup (struct mem_node *); | 351 | static void mem_insert_fixup (struct mem_node *); |
| 415 | #endif | ||
| 416 | static void mem_rotate_left (struct mem_node *); | 352 | static void mem_rotate_left (struct mem_node *); |
| 417 | static void mem_rotate_right (struct mem_node *); | 353 | static void mem_rotate_right (struct mem_node *); |
| 418 | static void mem_delete (struct mem_node *); | 354 | static void mem_delete (struct mem_node *); |
| 419 | static void mem_delete_fixup (struct mem_node *); | 355 | static void mem_delete_fixup (struct mem_node *); |
| 420 | static inline struct mem_node *mem_find (void *); | 356 | static inline struct mem_node *mem_find (void *); |
| 357 | #endif | ||
| 421 | 358 | ||
| 422 | 359 | ||
| 423 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 360 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| @@ -586,39 +523,17 @@ xmalloc_get_size (unsigned char *ptr) | |||
| 586 | } | 523 | } |
| 587 | 524 | ||
| 588 | 525 | ||
| 589 | /* The call depth in overrun_check functions. For example, this might happen: | ||
| 590 | xmalloc() | ||
| 591 | overrun_check_malloc() | ||
| 592 | -> malloc -> (via hook)_-> emacs_blocked_malloc | ||
| 593 | -> overrun_check_malloc | ||
| 594 | call malloc (hooks are NULL, so real malloc is called). | ||
| 595 | malloc returns 10000. | ||
| 596 | add overhead, return 10016. | ||
| 597 | <- (back in overrun_check_malloc) | ||
| 598 | add overhead again, return 10032 | ||
| 599 | xmalloc returns 10032. | ||
| 600 | |||
| 601 | (time passes). | ||
| 602 | |||
| 603 | xfree(10032) | ||
| 604 | overrun_check_free(10032) | ||
| 605 | decrease overhead | ||
| 606 | free(10016) <- crash, because 10000 is the original pointer. */ | ||
| 607 | |||
| 608 | static ptrdiff_t check_depth; | ||
| 609 | |||
| 610 | /* Like malloc, but wraps allocated block with header and trailer. */ | 526 | /* Like malloc, but wraps allocated block with header and trailer. */ |
| 611 | 527 | ||
| 612 | static void * | 528 | static void * |
| 613 | overrun_check_malloc (size_t size) | 529 | overrun_check_malloc (size_t size) |
| 614 | { | 530 | { |
| 615 | register unsigned char *val; | 531 | register unsigned char *val; |
| 616 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 532 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 617 | if (SIZE_MAX - overhead < size) | ||
| 618 | emacs_abort (); | 533 | emacs_abort (); |
| 619 | 534 | ||
| 620 | val = malloc (size + overhead); | 535 | val = malloc (size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 621 | if (val && check_depth == 1) | 536 | if (val) |
| 622 | { | 537 | { |
| 623 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 538 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 624 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 539 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -626,7 +541,6 @@ overrun_check_malloc (size_t size) | |||
| 626 | memcpy (val + size, xmalloc_overrun_check_trailer, | 541 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 627 | XMALLOC_OVERRUN_CHECK_SIZE); | 542 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 628 | } | 543 | } |
| 629 | --check_depth; | ||
| 630 | return val; | 544 | return val; |
| 631 | } | 545 | } |
| 632 | 546 | ||
| @@ -638,12 +552,10 @@ static void * | |||
| 638 | overrun_check_realloc (void *block, size_t size) | 552 | overrun_check_realloc (void *block, size_t size) |
| 639 | { | 553 | { |
| 640 | register unsigned char *val = (unsigned char *) block; | 554 | register unsigned char *val = (unsigned char *) block; |
| 641 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 555 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 642 | if (SIZE_MAX - overhead < size) | ||
| 643 | emacs_abort (); | 556 | emacs_abort (); |
| 644 | 557 | ||
| 645 | if (val | 558 | if (val |
| 646 | && check_depth == 1 | ||
| 647 | && memcmp (xmalloc_overrun_check_header, | 559 | && memcmp (xmalloc_overrun_check_header, |
| 648 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 560 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 649 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 561 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -657,9 +569,9 @@ overrun_check_realloc (void *block, size_t size) | |||
| 657 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); | 569 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); |
| 658 | } | 570 | } |
| 659 | 571 | ||
| 660 | val = realloc (val, size + overhead); | 572 | val = realloc (val, size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 661 | 573 | ||
| 662 | if (val && check_depth == 1) | 574 | if (val) |
| 663 | { | 575 | { |
| 664 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 576 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 665 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 577 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -667,7 +579,6 @@ overrun_check_realloc (void *block, size_t size) | |||
| 667 | memcpy (val + size, xmalloc_overrun_check_trailer, | 579 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 668 | XMALLOC_OVERRUN_CHECK_SIZE); | 580 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 669 | } | 581 | } |
| 670 | --check_depth; | ||
| 671 | return val; | 582 | return val; |
| 672 | } | 583 | } |
| 673 | 584 | ||
| @@ -678,9 +589,7 @@ overrun_check_free (void *block) | |||
| 678 | { | 589 | { |
| 679 | unsigned char *val = (unsigned char *) block; | 590 | unsigned char *val = (unsigned char *) block; |
| 680 | 591 | ||
| 681 | ++check_depth; | ||
| 682 | if (val | 592 | if (val |
| 683 | && check_depth == 1 | ||
| 684 | && memcmp (xmalloc_overrun_check_header, | 593 | && memcmp (xmalloc_overrun_check_header, |
| 685 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 594 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 686 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 595 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -700,7 +609,6 @@ overrun_check_free (void *block) | |||
| 700 | } | 609 | } |
| 701 | 610 | ||
| 702 | free (val); | 611 | free (val); |
| 703 | --check_depth; | ||
| 704 | } | 612 | } |
| 705 | 613 | ||
| 706 | #undef malloc | 614 | #undef malloc |
| @@ -711,14 +619,33 @@ overrun_check_free (void *block) | |||
| 711 | #define free overrun_check_free | 619 | #define free overrun_check_free |
| 712 | #endif | 620 | #endif |
| 713 | 621 | ||
| 714 | #ifdef SYNC_INPUT | 622 | /* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol |
| 715 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | 623 | BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger. |
| 716 | there's no need to block input around malloc. */ | 624 | If that variable is set, block input while in one of Emacs's memory |
| 717 | #define MALLOC_BLOCK_INPUT ((void)0) | 625 | allocation functions. There should be no need for this debugging |
| 718 | #define MALLOC_UNBLOCK_INPUT ((void)0) | 626 | option, since signal handlers do not allocate memory, but Emacs |
| 627 | formerly allocated memory in signal handlers and this compile-time | ||
| 628 | option remains as a way to help debug the issue should it rear its | ||
| 629 | ugly head again. */ | ||
| 630 | #ifdef XMALLOC_BLOCK_INPUT_CHECK | ||
| 631 | bool block_input_in_memory_allocators EXTERNALLY_VISIBLE; | ||
| 632 | static void | ||
| 633 | malloc_block_input (void) | ||
| 634 | { | ||
| 635 | if (block_input_in_memory_allocators) | ||
| 636 | BLOCK_INPUT; | ||
| 637 | } | ||
| 638 | static void | ||
| 639 | malloc_unblock_input (void) | ||
| 640 | { | ||
| 641 | if (block_input_in_memory_allocators) | ||
| 642 | UNBLOCK_INPUT; | ||
| 643 | } | ||
| 644 | # define MALLOC_BLOCK_INPUT malloc_block_input () | ||
| 645 | # define MALLOC_UNBLOCK_INPUT malloc_unblock_input () | ||
| 719 | #else | 646 | #else |
| 720 | #define MALLOC_BLOCK_INPUT BLOCK_INPUT | 647 | # define MALLOC_BLOCK_INPUT ((void) 0) |
| 721 | #define MALLOC_UNBLOCK_INPUT UNBLOCK_INPUT | 648 | # define MALLOC_UNBLOCK_INPUT ((void) 0) |
| 722 | #endif | 649 | #endif |
| 723 | 650 | ||
| 724 | /* Like malloc but check for no memory and block interrupt input.. */ | 651 | /* Like malloc but check for no memory and block interrupt input.. */ |
| @@ -787,8 +714,7 @@ xfree (void *block) | |||
| 787 | free (block); | 714 | free (block); |
| 788 | MALLOC_UNBLOCK_INPUT; | 715 | MALLOC_UNBLOCK_INPUT; |
| 789 | /* We don't call refill_memory_reserve here | 716 | /* We don't call refill_memory_reserve here |
| 790 | because that duplicates doing so in emacs_blocked_free | 717 | because in practice the call in r_alloc_free seems to suffice. */ |
| 791 | and the criterion should go there. */ | ||
| 792 | } | 718 | } |
| 793 | 719 | ||
| 794 | 720 | ||
| @@ -1215,256 +1141,6 @@ lisp_align_free (void *block) | |||
| 1215 | } | 1141 | } |
| 1216 | 1142 | ||
| 1217 | 1143 | ||
| 1218 | #ifndef SYSTEM_MALLOC | ||
| 1219 | |||
| 1220 | /* Arranging to disable input signals while we're in malloc. | ||
| 1221 | |||
| 1222 | This only works with GNU malloc. To help out systems which can't | ||
| 1223 | use GNU malloc, all the calls to malloc, realloc, and free | ||
| 1224 | elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT | ||
| 1225 | pair; unfortunately, we have no idea what C library functions | ||
| 1226 | might call malloc, so we can't really protect them unless you're | ||
| 1227 | using GNU malloc. Fortunately, most of the major operating systems | ||
| 1228 | can use GNU malloc. */ | ||
| 1229 | |||
| 1230 | #ifndef SYNC_INPUT | ||
| 1231 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | ||
| 1232 | there's no need to block input around malloc. */ | ||
| 1233 | |||
| 1234 | #ifndef DOUG_LEA_MALLOC | ||
| 1235 | extern void * (*__malloc_hook) (size_t, const void *); | ||
| 1236 | extern void * (*__realloc_hook) (void *, size_t, const void *); | ||
| 1237 | extern void (*__free_hook) (void *, const void *); | ||
| 1238 | /* Else declared in malloc.h, perhaps with an extra arg. */ | ||
| 1239 | #endif /* DOUG_LEA_MALLOC */ | ||
| 1240 | static void * (*old_malloc_hook) (size_t, const void *); | ||
| 1241 | static void * (*old_realloc_hook) (void *, size_t, const void*); | ||
| 1242 | static void (*old_free_hook) (void*, const void*); | ||
| 1243 | |||
| 1244 | #ifdef DOUG_LEA_MALLOC | ||
| 1245 | # define BYTES_USED (mallinfo ().uordblks) | ||
| 1246 | #else | ||
| 1247 | # define BYTES_USED _bytes_used | ||
| 1248 | #endif | ||
| 1249 | |||
| 1250 | #ifdef GC_MALLOC_CHECK | ||
| 1251 | static bool dont_register_blocks; | ||
| 1252 | #endif | ||
| 1253 | |||
| 1254 | static size_t bytes_used_when_reconsidered; | ||
| 1255 | |||
| 1256 | /* Value of _bytes_used, when spare_memory was freed. */ | ||
| 1257 | |||
| 1258 | static size_t bytes_used_when_full; | ||
| 1259 | |||
| 1260 | /* This function is used as the hook for free to call. */ | ||
| 1261 | |||
| 1262 | static void | ||
| 1263 | emacs_blocked_free (void *ptr, const void *ptr2) | ||
| 1264 | { | ||
| 1265 | BLOCK_INPUT_ALLOC; | ||
| 1266 | |||
| 1267 | #ifdef GC_MALLOC_CHECK | ||
| 1268 | if (ptr) | ||
| 1269 | { | ||
| 1270 | struct mem_node *m; | ||
| 1271 | |||
| 1272 | m = mem_find (ptr); | ||
| 1273 | if (m == MEM_NIL || m->start != ptr) | ||
| 1274 | { | ||
| 1275 | fprintf (stderr, | ||
| 1276 | "Freeing `%p' which wasn't allocated with malloc\n", ptr); | ||
| 1277 | emacs_abort (); | ||
| 1278 | } | ||
| 1279 | else | ||
| 1280 | { | ||
| 1281 | /* fprintf (stderr, "free %p...%p (%p)\n", m->start, m->end, ptr); */ | ||
| 1282 | mem_delete (m); | ||
| 1283 | } | ||
| 1284 | } | ||
| 1285 | #endif /* GC_MALLOC_CHECK */ | ||
| 1286 | |||
| 1287 | __free_hook = old_free_hook; | ||
| 1288 | free (ptr); | ||
| 1289 | |||
| 1290 | /* If we released our reserve (due to running out of memory), | ||
| 1291 | and we have a fair amount free once again, | ||
| 1292 | try to set aside another reserve in case we run out once more. */ | ||
| 1293 | if (! NILP (Vmemory_full) | ||
| 1294 | /* Verify there is enough space that even with the malloc | ||
| 1295 | hysteresis this call won't run out again. | ||
| 1296 | The code here is correct as long as SPARE_MEMORY | ||
| 1297 | is substantially larger than the block size malloc uses. */ | ||
| 1298 | && (bytes_used_when_full | ||
| 1299 | > ((bytes_used_when_reconsidered = BYTES_USED) | ||
| 1300 | + max (malloc_hysteresis, 4) * SPARE_MEMORY))) | ||
| 1301 | refill_memory_reserve (); | ||
| 1302 | |||
| 1303 | __free_hook = emacs_blocked_free; | ||
| 1304 | UNBLOCK_INPUT_ALLOC; | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | |||
| 1308 | /* This function is the malloc hook that Emacs uses. */ | ||
| 1309 | |||
| 1310 | static void * | ||
| 1311 | emacs_blocked_malloc (size_t size, const void *ptr) | ||
| 1312 | { | ||
| 1313 | void *value; | ||
| 1314 | |||
| 1315 | BLOCK_INPUT_ALLOC; | ||
| 1316 | __malloc_hook = old_malloc_hook; | ||
| 1317 | #ifdef DOUG_LEA_MALLOC | ||
| 1318 | /* Segfaults on my system. --lorentey */ | ||
| 1319 | /* mallopt (M_TOP_PAD, malloc_hysteresis * 4096); */ | ||
| 1320 | #else | ||
| 1321 | __malloc_extra_blocks = malloc_hysteresis; | ||
| 1322 | #endif | ||
| 1323 | |||
| 1324 | value = malloc (size); | ||
| 1325 | |||
| 1326 | #ifdef GC_MALLOC_CHECK | ||
| 1327 | { | ||
| 1328 | struct mem_node *m = mem_find (value); | ||
| 1329 | if (m != MEM_NIL) | ||
| 1330 | { | ||
| 1331 | fprintf (stderr, "Malloc returned %p which is already in use\n", | ||
| 1332 | value); | ||
| 1333 | fprintf (stderr, "Region in use is %p...%p, %td bytes, type %d\n", | ||
| 1334 | m->start, m->end, (char *) m->end - (char *) m->start, | ||
| 1335 | m->type); | ||
| 1336 | emacs_abort (); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | if (!dont_register_blocks) | ||
| 1340 | { | ||
| 1341 | mem_insert (value, (char *) value + max (1, size), allocated_mem_type); | ||
| 1342 | allocated_mem_type = MEM_TYPE_NON_LISP; | ||
| 1343 | } | ||
| 1344 | } | ||
| 1345 | #endif /* GC_MALLOC_CHECK */ | ||
| 1346 | |||
| 1347 | __malloc_hook = emacs_blocked_malloc; | ||
| 1348 | UNBLOCK_INPUT_ALLOC; | ||
| 1349 | |||
| 1350 | /* fprintf (stderr, "%p malloc\n", value); */ | ||
| 1351 | return value; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | |||
| 1355 | /* This function is the realloc hook that Emacs uses. */ | ||
| 1356 | |||
| 1357 | static void * | ||
| 1358 | emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2) | ||
| 1359 | { | ||
| 1360 | void *value; | ||
| 1361 | |||
| 1362 | BLOCK_INPUT_ALLOC; | ||
| 1363 | __realloc_hook = old_realloc_hook; | ||
| 1364 | |||
| 1365 | #ifdef GC_MALLOC_CHECK | ||
| 1366 | if (ptr) | ||
| 1367 | { | ||
| 1368 | struct mem_node *m = mem_find (ptr); | ||
| 1369 | if (m == MEM_NIL || m->start != ptr) | ||
| 1370 | { | ||
| 1371 | fprintf (stderr, | ||
| 1372 | "Realloc of %p which wasn't allocated with malloc\n", | ||
| 1373 | ptr); | ||
| 1374 | emacs_abort (); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | mem_delete (m); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | /* fprintf (stderr, "%p -> realloc\n", ptr); */ | ||
| 1381 | |||
| 1382 | /* Prevent malloc from registering blocks. */ | ||
| 1383 | dont_register_blocks = 1; | ||
| 1384 | #endif /* GC_MALLOC_CHECK */ | ||
| 1385 | |||
| 1386 | value = realloc (ptr, size); | ||
| 1387 | |||
| 1388 | #ifdef GC_MALLOC_CHECK | ||
| 1389 | dont_register_blocks = 0; | ||
| 1390 | |||
| 1391 | { | ||
| 1392 | struct mem_node *m = mem_find (value); | ||
| 1393 | if (m != MEM_NIL) | ||
| 1394 | { | ||
| 1395 | fprintf (stderr, "Realloc returns memory that is already in use\n"); | ||
| 1396 | emacs_abort (); | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | /* Can't handle zero size regions in the red-black tree. */ | ||
| 1400 | mem_insert (value, (char *) value + max (size, 1), MEM_TYPE_NON_LISP); | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | /* fprintf (stderr, "%p <- realloc\n", value); */ | ||
| 1404 | #endif /* GC_MALLOC_CHECK */ | ||
| 1405 | |||
| 1406 | __realloc_hook = emacs_blocked_realloc; | ||
| 1407 | UNBLOCK_INPUT_ALLOC; | ||
| 1408 | |||
| 1409 | return value; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | |||
| 1413 | #ifdef HAVE_PTHREAD | ||
| 1414 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a | ||
| 1415 | normal malloc. Some thread implementations need this as they call | ||
| 1416 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then | ||
| 1417 | calls malloc because it is the first call, and we have an endless loop. */ | ||
| 1418 | |||
| 1419 | void | ||
| 1420 | reset_malloc_hooks (void) | ||
| 1421 | { | ||
| 1422 | __free_hook = old_free_hook; | ||
| 1423 | __malloc_hook = old_malloc_hook; | ||
| 1424 | __realloc_hook = old_realloc_hook; | ||
| 1425 | } | ||
| 1426 | #endif /* HAVE_PTHREAD */ | ||
| 1427 | |||
| 1428 | |||
| 1429 | /* Called from main to set up malloc to use our hooks. */ | ||
| 1430 | |||
| 1431 | void | ||
| 1432 | uninterrupt_malloc (void) | ||
| 1433 | { | ||
| 1434 | #ifdef HAVE_PTHREAD | ||
| 1435 | #ifdef DOUG_LEA_MALLOC | ||
| 1436 | pthread_mutexattr_t attr; | ||
| 1437 | |||
| 1438 | /* GLIBC has a faster way to do this, but let's keep it portable. | ||
| 1439 | This is according to the Single UNIX Specification. */ | ||
| 1440 | pthread_mutexattr_init (&attr); | ||
| 1441 | pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); | ||
| 1442 | pthread_mutex_init (&alloc_mutex, &attr); | ||
| 1443 | #else /* !DOUG_LEA_MALLOC */ | ||
| 1444 | /* Some systems such as Solaris 2.6 don't have a recursive mutex, | ||
| 1445 | and the bundled gmalloc.c doesn't require it. */ | ||
| 1446 | pthread_mutex_init (&alloc_mutex, NULL); | ||
| 1447 | #endif /* !DOUG_LEA_MALLOC */ | ||
| 1448 | #endif /* HAVE_PTHREAD */ | ||
| 1449 | |||
| 1450 | if (__free_hook != emacs_blocked_free) | ||
| 1451 | old_free_hook = __free_hook; | ||
| 1452 | __free_hook = emacs_blocked_free; | ||
| 1453 | |||
| 1454 | if (__malloc_hook != emacs_blocked_malloc) | ||
| 1455 | old_malloc_hook = __malloc_hook; | ||
| 1456 | __malloc_hook = emacs_blocked_malloc; | ||
| 1457 | |||
| 1458 | if (__realloc_hook != emacs_blocked_realloc) | ||
| 1459 | old_realloc_hook = __realloc_hook; | ||
| 1460 | __realloc_hook = emacs_blocked_realloc; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | #endif /* not SYNC_INPUT */ | ||
| 1464 | #endif /* not SYSTEM_MALLOC */ | ||
| 1465 | |||
| 1466 | |||
| 1467 | |||
| 1468 | /*********************************************************************** | 1144 | /*********************************************************************** |
| 1469 | Interval Allocation | 1145 | Interval Allocation |
| 1470 | ***********************************************************************/ | 1146 | ***********************************************************************/ |
| @@ -1510,8 +1186,6 @@ make_interval (void) | |||
| 1510 | { | 1186 | { |
| 1511 | INTERVAL val; | 1187 | INTERVAL val; |
| 1512 | 1188 | ||
| 1513 | /* eassert (!handling_signal); */ | ||
| 1514 | |||
| 1515 | MALLOC_BLOCK_INPUT; | 1189 | MALLOC_BLOCK_INPUT; |
| 1516 | 1190 | ||
| 1517 | if (interval_free_list) | 1191 | if (interval_free_list) |
| @@ -1895,8 +1569,6 @@ allocate_string (void) | |||
| 1895 | { | 1569 | { |
| 1896 | struct Lisp_String *s; | 1570 | struct Lisp_String *s; |
| 1897 | 1571 | ||
| 1898 | /* eassert (!handling_signal); */ | ||
| 1899 | |||
| 1900 | MALLOC_BLOCK_INPUT; | 1572 | MALLOC_BLOCK_INPUT; |
| 1901 | 1573 | ||
| 1902 | /* If the free-list is empty, allocate a new string_block, and | 1574 | /* If the free-list is empty, allocate a new string_block, and |
| @@ -2588,8 +2260,6 @@ make_float (double float_value) | |||
| 2588 | { | 2260 | { |
| 2589 | register Lisp_Object val; | 2261 | register Lisp_Object val; |
| 2590 | 2262 | ||
| 2591 | /* eassert (!handling_signal); */ | ||
| 2592 | |||
| 2593 | MALLOC_BLOCK_INPUT; | 2263 | MALLOC_BLOCK_INPUT; |
| 2594 | 2264 | ||
| 2595 | if (float_free_list) | 2265 | if (float_free_list) |
| @@ -2697,8 +2367,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2697 | { | 2367 | { |
| 2698 | register Lisp_Object val; | 2368 | register Lisp_Object val; |
| 2699 | 2369 | ||
| 2700 | /* eassert (!handling_signal); */ | ||
| 2701 | |||
| 2702 | MALLOC_BLOCK_INPUT; | 2370 | MALLOC_BLOCK_INPUT; |
| 2703 | 2371 | ||
| 2704 | if (cons_free_list) | 2372 | if (cons_free_list) |
| @@ -3204,9 +2872,6 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3204 | 2872 | ||
| 3205 | MALLOC_BLOCK_INPUT; | 2873 | MALLOC_BLOCK_INPUT; |
| 3206 | 2874 | ||
| 3207 | /* This gets triggered by code which I haven't bothered to fix. --Stef */ | ||
| 3208 | /* eassert (!handling_signal); */ | ||
| 3209 | |||
| 3210 | if (len == 0) | 2875 | if (len == 0) |
| 3211 | p = XVECTOR (zero_vector); | 2876 | p = XVECTOR (zero_vector); |
| 3212 | else | 2877 | else |
| @@ -3491,8 +3156,6 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3491 | 3156 | ||
| 3492 | CHECK_STRING (name); | 3157 | CHECK_STRING (name); |
| 3493 | 3158 | ||
| 3494 | /* eassert (!handling_signal); */ | ||
| 3495 | |||
| 3496 | MALLOC_BLOCK_INPUT; | 3159 | MALLOC_BLOCK_INPUT; |
| 3497 | 3160 | ||
| 3498 | if (symbol_free_list) | 3161 | if (symbol_free_list) |
| @@ -3577,8 +3240,6 @@ allocate_misc (enum Lisp_Misc_Type type) | |||
| 3577 | { | 3240 | { |
| 3578 | Lisp_Object val; | 3241 | Lisp_Object val; |
| 3579 | 3242 | ||
| 3580 | /* eassert (!handling_signal); */ | ||
| 3581 | |||
| 3582 | MALLOC_BLOCK_INPUT; | 3243 | MALLOC_BLOCK_INPUT; |
| 3583 | 3244 | ||
| 3584 | if (marker_free_list) | 3245 | if (marker_free_list) |
| @@ -3798,12 +3459,6 @@ memory_full (size_t nbytes) | |||
| 3798 | lisp_free (spare_memory[i]); | 3459 | lisp_free (spare_memory[i]); |
| 3799 | spare_memory[i] = 0; | 3460 | spare_memory[i] = 0; |
| 3800 | } | 3461 | } |
| 3801 | |||
| 3802 | /* Record the space now used. When it decreases substantially, | ||
| 3803 | we can refill the memory reserve. */ | ||
| 3804 | #if !defined SYSTEM_MALLOC && !defined SYNC_INPUT | ||
| 3805 | bytes_used_when_full = BYTES_USED; | ||
| 3806 | #endif | ||
| 3807 | } | 3462 | } |
| 3808 | 3463 | ||
| 3809 | /* This used to call error, but if we've run out of memory, we could | 3464 | /* This used to call error, but if we've run out of memory, we could |
| @@ -3941,7 +3596,7 @@ mem_insert (void *start, void *end, enum mem_type type) | |||
| 3941 | 3596 | ||
| 3942 | /* Create a new node. */ | 3597 | /* Create a new node. */ |
| 3943 | #ifdef GC_MALLOC_CHECK | 3598 | #ifdef GC_MALLOC_CHECK |
| 3944 | x = _malloc_internal (sizeof *x); | 3599 | x = malloc (sizeof *x); |
| 3945 | if (x == NULL) | 3600 | if (x == NULL) |
| 3946 | emacs_abort (); | 3601 | emacs_abort (); |
| 3947 | #else | 3602 | #else |
| @@ -4165,7 +3820,7 @@ mem_delete (struct mem_node *z) | |||
| 4165 | mem_delete_fixup (x); | 3820 | mem_delete_fixup (x); |
| 4166 | 3821 | ||
| 4167 | #ifdef GC_MALLOC_CHECK | 3822 | #ifdef GC_MALLOC_CHECK |
| 4168 | _free_internal (y); | 3823 | free (y); |
| 4169 | #else | 3824 | #else |
| 4170 | xfree (y); | 3825 | xfree (y); |
| 4171 | #endif | 3826 | #endif |
| @@ -4762,14 +4417,14 @@ test_setjmp (void) | |||
| 4762 | { | 4417 | { |
| 4763 | char buf[10]; | 4418 | char buf[10]; |
| 4764 | register int x; | 4419 | register int x; |
| 4765 | jmp_buf jbuf; | 4420 | sys_jmp_buf jbuf; |
| 4766 | 4421 | ||
| 4767 | /* Arrange for X to be put in a register. */ | 4422 | /* Arrange for X to be put in a register. */ |
| 4768 | sprintf (buf, "1"); | 4423 | sprintf (buf, "1"); |
| 4769 | x = strlen (buf); | 4424 | x = strlen (buf); |
| 4770 | x = 2 * x - 1; | 4425 | x = 2 * x - 1; |
| 4771 | 4426 | ||
| 4772 | _setjmp (jbuf); | 4427 | sys_setjmp (jbuf); |
| 4773 | if (longjmps_done == 1) | 4428 | if (longjmps_done == 1) |
| 4774 | { | 4429 | { |
| 4775 | /* Came here after the longjmp at the end of the function. | 4430 | /* Came here after the longjmp at the end of the function. |
| @@ -4794,7 +4449,7 @@ test_setjmp (void) | |||
| 4794 | ++longjmps_done; | 4449 | ++longjmps_done; |
| 4795 | x = 2; | 4450 | x = 2; |
| 4796 | if (longjmps_done == 1) | 4451 | if (longjmps_done == 1) |
| 4797 | _longjmp (jbuf, 1); | 4452 | sys_longjmp (jbuf, 1); |
| 4798 | } | 4453 | } |
| 4799 | 4454 | ||
| 4800 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ | 4455 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ |
| @@ -4900,7 +4555,7 @@ mark_stack (void) | |||
| 4900 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ | 4555 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ |
| 4901 | union aligned_jmpbuf { | 4556 | union aligned_jmpbuf { |
| 4902 | Lisp_Object o; | 4557 | Lisp_Object o; |
| 4903 | jmp_buf j; | 4558 | sys_jmp_buf j; |
| 4904 | } j; | 4559 | } j; |
| 4905 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; | 4560 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; |
| 4906 | #endif | 4561 | #endif |
| @@ -4936,7 +4591,7 @@ mark_stack (void) | |||
| 4936 | } | 4591 | } |
| 4937 | #endif /* GC_SETJMP_WORKS */ | 4592 | #endif /* GC_SETJMP_WORKS */ |
| 4938 | 4593 | ||
| 4939 | _setjmp (j.j); | 4594 | sys_setjmp (j.j); |
| 4940 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; | 4595 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; |
| 4941 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ | 4596 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ |
| 4942 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ | 4597 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ |
| @@ -5865,16 +5520,16 @@ mark_buffer (struct buffer *buffer) | |||
| 5865 | mark_buffer (buffer->base_buffer); | 5520 | mark_buffer (buffer->base_buffer); |
| 5866 | } | 5521 | } |
| 5867 | 5522 | ||
| 5868 | /* Remove killed buffers or items whose car is a killed buffer | 5523 | /* Remove killed buffers or items whose car is a killed buffer from |
| 5869 | from LIST and return changed LIST. Called during GC. */ | 5524 | LIST, and mark other items. Return changed LIST, which is marked. */ |
| 5870 | 5525 | ||
| 5871 | static Lisp_Object | 5526 | static Lisp_Object |
| 5872 | discard_killed_buffers (Lisp_Object list) | 5527 | mark_discard_killed_buffers (Lisp_Object list) |
| 5873 | { | 5528 | { |
| 5874 | Lisp_Object *prev = &list; | 5529 | Lisp_Object tail, *prev = &list; |
| 5875 | Lisp_Object tail; | ||
| 5876 | 5530 | ||
| 5877 | for (tail = list; CONSP (tail); tail = XCDR (tail)) | 5531 | for (tail = list; CONSP (tail) && !CONS_MARKED_P (XCONS (tail)); |
| 5532 | tail = XCDR (tail)) | ||
| 5878 | { | 5533 | { |
| 5879 | Lisp_Object tem = XCAR (tail); | 5534 | Lisp_Object tem = XCAR (tail); |
| 5880 | if (CONSP (tem)) | 5535 | if (CONSP (tem)) |
| @@ -5882,8 +5537,13 @@ discard_killed_buffers (Lisp_Object list) | |||
| 5882 | if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem))) | 5537 | if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem))) |
| 5883 | *prev = XCDR (tail); | 5538 | *prev = XCDR (tail); |
| 5884 | else | 5539 | else |
| 5885 | prev = &XCDR_AS_LVALUE (tail); | 5540 | { |
| 5541 | CONS_MARK (XCONS (tail)); | ||
| 5542 | mark_object (XCAR (tail)); | ||
| 5543 | prev = &XCDR_AS_LVALUE (tail); | ||
| 5544 | } | ||
| 5886 | } | 5545 | } |
| 5546 | mark_object (tail); | ||
| 5887 | return list; | 5547 | return list; |
| 5888 | } | 5548 | } |
| 5889 | 5549 | ||
| @@ -6023,18 +5683,8 @@ mark_object (Lisp_Object arg) | |||
| 6023 | break; | 5683 | break; |
| 6024 | 5684 | ||
| 6025 | case PVEC_FRAME: | 5685 | case PVEC_FRAME: |
| 6026 | { | 5686 | mark_vectorlike (ptr); |
| 6027 | struct frame *f = (struct frame *) ptr; | 5687 | mark_face_cache (((struct frame *) ptr)->face_cache); |
| 6028 | |||
| 6029 | /* For live frames, killed buffers are filtered out by | ||
| 6030 | store_frame_param. For dead frames, we do it here in | ||
| 6031 | attempt to help GC to reclaim killed buffers faster. */ | ||
| 6032 | if (!FRAME_LIVE_P (f)) | ||
| 6033 | fset_buffer_list (f, discard_killed_buffers (f->buffer_list)); | ||
| 6034 | |||
| 6035 | mark_vectorlike (ptr); | ||
| 6036 | mark_face_cache (f->face_cache); | ||
| 6037 | } | ||
| 6038 | break; | 5688 | break; |
| 6039 | 5689 | ||
| 6040 | case PVEC_WINDOW: | 5690 | case PVEC_WINDOW: |
| @@ -6042,18 +5692,8 @@ mark_object (Lisp_Object arg) | |||
| 6042 | struct window *w = (struct window *) ptr; | 5692 | struct window *w = (struct window *) ptr; |
| 6043 | bool leaf = NILP (w->hchild) && NILP (w->vchild); | 5693 | bool leaf = NILP (w->hchild) && NILP (w->vchild); |
| 6044 | 5694 | ||
| 6045 | /* For live windows, Lisp code filters out killed buffers | ||
| 6046 | from both buffer lists. For dead windows, we do it here | ||
| 6047 | in attempt to help GC to reclaim killed buffers faster. */ | ||
| 6048 | if (leaf && NILP (w->buffer)) | ||
| 6049 | { | ||
| 6050 | wset_prev_buffers | ||
| 6051 | (w, discard_killed_buffers (w->prev_buffers)); | ||
| 6052 | wset_next_buffers | ||
| 6053 | (w, discard_killed_buffers (w->next_buffers)); | ||
| 6054 | } | ||
| 6055 | |||
| 6056 | mark_vectorlike (ptr); | 5695 | mark_vectorlike (ptr); |
| 5696 | |||
| 6057 | /* Mark glyphs for leaf windows. Marking window | 5697 | /* Mark glyphs for leaf windows. Marking window |
| 6058 | matrices is sufficient because frame matrices | 5698 | matrices is sufficient because frame matrices |
| 6059 | use the same glyph memory. */ | 5699 | use the same glyph memory. */ |
| @@ -6062,6 +5702,15 @@ mark_object (Lisp_Object arg) | |||
| 6062 | mark_glyph_matrix (w->current_matrix); | 5702 | mark_glyph_matrix (w->current_matrix); |
| 6063 | mark_glyph_matrix (w->desired_matrix); | 5703 | mark_glyph_matrix (w->desired_matrix); |
| 6064 | } | 5704 | } |
| 5705 | |||
| 5706 | /* Filter out killed buffers from both buffer lists | ||
| 5707 | in attempt to help GC to reclaim killed buffers faster. | ||
| 5708 | We can do it elsewhere for live windows, but this is the | ||
| 5709 | best place to do it for dead windows. */ | ||
| 5710 | wset_prev_buffers | ||
| 5711 | (w, mark_discard_killed_buffers (w->prev_buffers)); | ||
| 5712 | wset_next_buffers | ||
| 5713 | (w, mark_discard_killed_buffers (w->next_buffers)); | ||
| 6065 | } | 5714 | } |
| 6066 | break; | 5715 | break; |
| 6067 | 5716 | ||
| @@ -6772,12 +6421,6 @@ init_alloc_once (void) | |||
| 6772 | init_strings (); | 6421 | init_strings (); |
| 6773 | init_vectors (); | 6422 | init_vectors (); |
| 6774 | 6423 | ||
| 6775 | #ifdef REL_ALLOC | ||
| 6776 | malloc_hysteresis = 32; | ||
| 6777 | #else | ||
| 6778 | malloc_hysteresis = 0; | ||
| 6779 | #endif | ||
| 6780 | |||
| 6781 | refill_memory_reserve (); | 6424 | refill_memory_reserve (); |
| 6782 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; | 6425 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; |
| 6783 | } | 6426 | } |