diff options
| author | Paul Eggert | 2012-09-16 14:43:55 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-09-16 14:43:55 -0700 |
| commit | 0caaedb1c3c9c48980144e41d2a95329d39c399a (patch) | |
| tree | 3e191e2b290e9adf91594be047c1f268cacde932 /src/alloc.c | |
| parent | 634b8cacd6cc0557c1963ad7409db247963046d2 (diff) | |
| download | emacs-0caaedb1c3c9c48980144e41d2a95329d39c399a.tar.gz emacs-0caaedb1c3c9c48980144e41d2a95329d39c399a.zip | |
Remove configure's --without-sync-input option.
When auditing signal-handling in preparation for cleaning it up,
I found that SYNC_INPUT has race conditions and would be a real
pain to fix. Since it's an undocumented and deprecated
configure-time option, now seems like a good time to remove it.
Also see <http://bugs.gnu.org/11080#16>.
* configure.ac (SYNC_INPUT, BROKEN_SA_RESTART): Remove.
* admin/CPP-DEFINES (BROKEN_SA_RESTART, SA_RESTART): Remove.
* etc/TODO (Make SYNC_INPUT the default): Remove, as the code now
behaves as if SYNC_INPUT is always true.
* src/alloc.c (_bytes_used, __malloc_extra_blocks, _malloc_internal)
(_free_internal) [!DOUG_LEA_MALLOC]: Remove decls.
(alloc_mutex) [!SYSTEM_MALLOC && !SYNC_INPUT && HAVE_PTHREAD]:
(malloc_hysteresis):
(check_depth) [XMALLOC_OVERRUN_CHECK]:
(MALLOC_BLOCK_INPUT, MALLOC_UNBLOCK_INPUT):
(__malloc_hook, __realloc_hook, __free_hook, BYTES_USED)
(dont_register_blocks, bytes_used_when_reconsidered)
(bytes_used_when_full, emacs_blocked_free, emacs_blocked_malloc)
(emacs_blocked_realloc, reset_malloc_hooks, uninterrupt_malloc):
[!SYSTEM_MALLOC && !SYNC_INPUT]:
Remove. All uses removed.
(MALLOC_BLOCK_INPUT, MALLOC_UNBLOCK_INPUT): Use a different
implementation, one that depends on whether the new macro
XMALLOC_BLOCK_INPUT_CHECK is defined, not on whether SYNC_INPUT
is defined.
* src/atimer.c (run_timers, handle_alarm_signal):
* src/keyboard.c (pending_signal, poll_for_input_1, poll_for_input)
(handle_async_input, process_pending_signals)
(handle_input_available_signal, init_keyboard):
* src/nsterm.m (ns_read_socket):
* src/process.c (wait_reading_process_output):
* src/regex.c (immediate_quit, IMMEDIATE_QUIT_CHECK):
* src/sysdep.c (emacs_sigaction_init) [SA_RESTART]:
(emacs_write):
* src/xterm.c (XTread_socket):
Assume SYNC_INPUT.
* src/conf_post.h (SA_RESTART) [IRIX6_5]: Do not #undef.
* src/eval.c (handling_signal): Remove. All uses removed.
* src/lisp.h (ELSE_PENDING_SIGNALS): Remove.
All uses replaced with the SYNC_INPUT version.
(reset_malloc_hooks, uninterrupt_malloc, handling_signal):
Remove decls.
* src/sysdep.c, src/syssignal.h (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
Now static.
Fixes: debbugs:12450
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 424 |
1 files changed, 36 insertions, 388 deletions
diff --git a/src/alloc.c b/src/alloc.c index 0bfbb0c88b1..fb7d35b5590 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -85,68 +85,8 @@ extern void *sbrk (); | |||
| 85 | 85 | ||
| 86 | #define MMAP_MAX_AREAS 100000000 | 86 | #define MMAP_MAX_AREAS 100000000 |
| 87 | 87 | ||
| 88 | #else /* not DOUG_LEA_MALLOC */ | ||
| 89 | |||
| 90 | /* The following come from gmalloc.c. */ | ||
| 91 | |||
| 92 | extern size_t _bytes_used; | ||
| 93 | extern size_t __malloc_extra_blocks; | ||
| 94 | extern void *_malloc_internal (size_t); | ||
| 95 | extern void _free_internal (void *); | ||
| 96 | |||
| 97 | #endif /* not DOUG_LEA_MALLOC */ | 88 | #endif /* not DOUG_LEA_MALLOC */ |
| 98 | 89 | ||
| 99 | #if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT | ||
| 100 | #ifdef HAVE_PTHREAD | ||
| 101 | |||
| 102 | # include "syssignal.h" | ||
| 103 | |||
| 104 | /* When GTK uses the file chooser dialog, different backends can be loaded | ||
| 105 | dynamically. One such a backend is the Gnome VFS backend that gets loaded | ||
| 106 | if you run Gnome. That backend creates several threads and also allocates | ||
| 107 | memory with malloc. | ||
| 108 | |||
| 109 | Also, gconf and gsettings may create several threads. | ||
| 110 | |||
| 111 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* | ||
| 112 | functions below are called from malloc, there is a chance that one | ||
| 113 | of these threads preempts the Emacs main thread and the hook variables | ||
| 114 | end up in an inconsistent state. So we have a mutex to prevent that (note | ||
| 115 | that the backend handles concurrent access to malloc within its own threads | ||
| 116 | but Emacs code running in the main thread is not included in that control). | ||
| 117 | |||
| 118 | When UNBLOCK_INPUT is called, reinvoke_input_signal may be called. If this | ||
| 119 | happens in one of the backend threads we will have two threads that tries | ||
| 120 | to run Emacs code at once, and the code is not prepared for that. | ||
| 121 | To prevent that, we only call BLOCK/UNBLOCK from the main thread. */ | ||
| 122 | |||
| 123 | static pthread_mutex_t alloc_mutex; | ||
| 124 | |||
| 125 | #define BLOCK_INPUT_ALLOC \ | ||
| 126 | do \ | ||
| 127 | { \ | ||
| 128 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 129 | BLOCK_INPUT; \ | ||
| 130 | pthread_mutex_lock (&alloc_mutex); \ | ||
| 131 | } \ | ||
| 132 | while (0) | ||
| 133 | #define UNBLOCK_INPUT_ALLOC \ | ||
| 134 | do \ | ||
| 135 | { \ | ||
| 136 | pthread_mutex_unlock (&alloc_mutex); \ | ||
| 137 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 138 | UNBLOCK_INPUT; \ | ||
| 139 | } \ | ||
| 140 | while (0) | ||
| 141 | |||
| 142 | #else /* ! defined HAVE_PTHREAD */ | ||
| 143 | |||
| 144 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT | ||
| 145 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT | ||
| 146 | |||
| 147 | #endif /* ! defined HAVE_PTHREAD */ | ||
| 148 | #endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */ | ||
| 149 | |||
| 150 | /* 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 |
| 151 | to a struct Lisp_String. */ | 91 | to a struct Lisp_String. */ |
| 152 | 92 | ||
| @@ -205,10 +145,6 @@ static char *spare_memory[7]; | |||
| 205 | 145 | ||
| 206 | #define SPARE_MEMORY (1 << 14) | 146 | #define SPARE_MEMORY (1 << 14) |
| 207 | 147 | ||
| 208 | /* Number of extra blocks malloc should get when it needs more core. */ | ||
| 209 | |||
| 210 | static int malloc_hysteresis; | ||
| 211 | |||
| 212 | /* 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 |
| 213 | (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 |
| 214 | space (pure), on some systems. We have not implemented the | 150 | space (pure), on some systems. We have not implemented the |
| @@ -413,12 +349,12 @@ static void mark_memory (void *, void *); | |||
| 413 | static void mem_init (void); | 349 | static void mem_init (void); |
| 414 | static struct mem_node *mem_insert (void *, void *, enum mem_type); | 350 | static struct mem_node *mem_insert (void *, void *, enum mem_type); |
| 415 | static void mem_insert_fixup (struct mem_node *); | 351 | static void mem_insert_fixup (struct mem_node *); |
| 416 | #endif | ||
| 417 | static void mem_rotate_left (struct mem_node *); | 352 | static void mem_rotate_left (struct mem_node *); |
| 418 | static void mem_rotate_right (struct mem_node *); | 353 | static void mem_rotate_right (struct mem_node *); |
| 419 | static void mem_delete (struct mem_node *); | 354 | static void mem_delete (struct mem_node *); |
| 420 | static void mem_delete_fixup (struct mem_node *); | 355 | static void mem_delete_fixup (struct mem_node *); |
| 421 | static inline struct mem_node *mem_find (void *); | 356 | static inline struct mem_node *mem_find (void *); |
| 357 | #endif | ||
| 422 | 358 | ||
| 423 | 359 | ||
| 424 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 360 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| @@ -587,39 +523,17 @@ xmalloc_get_size (unsigned char *ptr) | |||
| 587 | } | 523 | } |
| 588 | 524 | ||
| 589 | 525 | ||
| 590 | /* The call depth in overrun_check functions. For example, this might happen: | ||
| 591 | xmalloc() | ||
| 592 | overrun_check_malloc() | ||
| 593 | -> malloc -> (via hook)_-> emacs_blocked_malloc | ||
| 594 | -> overrun_check_malloc | ||
| 595 | call malloc (hooks are NULL, so real malloc is called). | ||
| 596 | malloc returns 10000. | ||
| 597 | add overhead, return 10016. | ||
| 598 | <- (back in overrun_check_malloc) | ||
| 599 | add overhead again, return 10032 | ||
| 600 | xmalloc returns 10032. | ||
| 601 | |||
| 602 | (time passes). | ||
| 603 | |||
| 604 | xfree(10032) | ||
| 605 | overrun_check_free(10032) | ||
| 606 | decrease overhead | ||
| 607 | free(10016) <- crash, because 10000 is the original pointer. */ | ||
| 608 | |||
| 609 | static ptrdiff_t check_depth; | ||
| 610 | |||
| 611 | /* Like malloc, but wraps allocated block with header and trailer. */ | 526 | /* Like malloc, but wraps allocated block with header and trailer. */ |
| 612 | 527 | ||
| 613 | static void * | 528 | static void * |
| 614 | overrun_check_malloc (size_t size) | 529 | overrun_check_malloc (size_t size) |
| 615 | { | 530 | { |
| 616 | register unsigned char *val; | 531 | register unsigned char *val; |
| 617 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 532 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 618 | if (SIZE_MAX - overhead < size) | ||
| 619 | emacs_abort (); | 533 | emacs_abort (); |
| 620 | 534 | ||
| 621 | val = malloc (size + overhead); | 535 | val = malloc (size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 622 | if (val && check_depth == 1) | 536 | if (val) |
| 623 | { | 537 | { |
| 624 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 538 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 625 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 539 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -627,7 +541,6 @@ overrun_check_malloc (size_t size) | |||
| 627 | memcpy (val + size, xmalloc_overrun_check_trailer, | 541 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 628 | XMALLOC_OVERRUN_CHECK_SIZE); | 542 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 629 | } | 543 | } |
| 630 | --check_depth; | ||
| 631 | return val; | 544 | return val; |
| 632 | } | 545 | } |
| 633 | 546 | ||
| @@ -639,12 +552,10 @@ static void * | |||
| 639 | overrun_check_realloc (void *block, size_t size) | 552 | overrun_check_realloc (void *block, size_t size) |
| 640 | { | 553 | { |
| 641 | register unsigned char *val = (unsigned char *) block; | 554 | register unsigned char *val = (unsigned char *) block; |
| 642 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 555 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 643 | if (SIZE_MAX - overhead < size) | ||
| 644 | emacs_abort (); | 556 | emacs_abort (); |
| 645 | 557 | ||
| 646 | if (val | 558 | if (val |
| 647 | && check_depth == 1 | ||
| 648 | && memcmp (xmalloc_overrun_check_header, | 559 | && memcmp (xmalloc_overrun_check_header, |
| 649 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 560 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 650 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 561 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -658,9 +569,9 @@ overrun_check_realloc (void *block, size_t size) | |||
| 658 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); | 569 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); |
| 659 | } | 570 | } |
| 660 | 571 | ||
| 661 | val = realloc (val, size + overhead); | 572 | val = realloc (val, size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 662 | 573 | ||
| 663 | if (val && check_depth == 1) | 574 | if (val) |
| 664 | { | 575 | { |
| 665 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 576 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 666 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 577 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -668,7 +579,6 @@ overrun_check_realloc (void *block, size_t size) | |||
| 668 | memcpy (val + size, xmalloc_overrun_check_trailer, | 579 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 669 | XMALLOC_OVERRUN_CHECK_SIZE); | 580 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 670 | } | 581 | } |
| 671 | --check_depth; | ||
| 672 | return val; | 582 | return val; |
| 673 | } | 583 | } |
| 674 | 584 | ||
| @@ -679,9 +589,7 @@ overrun_check_free (void *block) | |||
| 679 | { | 589 | { |
| 680 | unsigned char *val = (unsigned char *) block; | 590 | unsigned char *val = (unsigned char *) block; |
| 681 | 591 | ||
| 682 | ++check_depth; | ||
| 683 | if (val | 592 | if (val |
| 684 | && check_depth == 1 | ||
| 685 | && memcmp (xmalloc_overrun_check_header, | 593 | && memcmp (xmalloc_overrun_check_header, |
| 686 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 594 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 687 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 595 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -701,7 +609,6 @@ overrun_check_free (void *block) | |||
| 701 | } | 609 | } |
| 702 | 610 | ||
| 703 | free (val); | 611 | free (val); |
| 704 | --check_depth; | ||
| 705 | } | 612 | } |
| 706 | 613 | ||
| 707 | #undef malloc | 614 | #undef malloc |
| @@ -712,14 +619,33 @@ overrun_check_free (void *block) | |||
| 712 | #define free overrun_check_free | 619 | #define free overrun_check_free |
| 713 | #endif | 620 | #endif |
| 714 | 621 | ||
| 715 | #ifdef SYNC_INPUT | 622 | /* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol |
| 716 | /* 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. |
| 717 | there's no need to block input around malloc. */ | 624 | If that variable is set, block input while in one of Emacs's memory |
| 718 | #define MALLOC_BLOCK_INPUT ((void)0) | 625 | allocation functions. There should be no need for this debugging |
| 719 | #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 () | ||
| 720 | #else | 646 | #else |
| 721 | #define MALLOC_BLOCK_INPUT BLOCK_INPUT | 647 | # define MALLOC_BLOCK_INPUT ((void) 0) |
| 722 | #define MALLOC_UNBLOCK_INPUT UNBLOCK_INPUT | 648 | # define MALLOC_UNBLOCK_INPUT ((void) 0) |
| 723 | #endif | 649 | #endif |
| 724 | 650 | ||
| 725 | /* Like malloc but check for no memory and block interrupt input.. */ | 651 | /* Like malloc but check for no memory and block interrupt input.. */ |
| @@ -788,8 +714,7 @@ xfree (void *block) | |||
| 788 | free (block); | 714 | free (block); |
| 789 | MALLOC_UNBLOCK_INPUT; | 715 | MALLOC_UNBLOCK_INPUT; |
| 790 | /* We don't call refill_memory_reserve here | 716 | /* We don't call refill_memory_reserve here |
| 791 | because that duplicates doing so in emacs_blocked_free | 717 | because in practice the call in r_alloc_free seems to suffice. */ |
| 792 | and the criterion should go there. */ | ||
| 793 | } | 718 | } |
| 794 | 719 | ||
| 795 | 720 | ||
| @@ -1216,256 +1141,6 @@ lisp_align_free (void *block) | |||
| 1216 | } | 1141 | } |
| 1217 | 1142 | ||
| 1218 | 1143 | ||
| 1219 | #ifndef SYSTEM_MALLOC | ||
| 1220 | |||
| 1221 | /* Arranging to disable input signals while we're in malloc. | ||
| 1222 | |||
| 1223 | This only works with GNU malloc. To help out systems which can't | ||
| 1224 | use GNU malloc, all the calls to malloc, realloc, and free | ||
| 1225 | elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT | ||
| 1226 | pair; unfortunately, we have no idea what C library functions | ||
| 1227 | might call malloc, so we can't really protect them unless you're | ||
| 1228 | using GNU malloc. Fortunately, most of the major operating systems | ||
| 1229 | can use GNU malloc. */ | ||
| 1230 | |||
| 1231 | #ifndef SYNC_INPUT | ||
| 1232 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | ||
| 1233 | there's no need to block input around malloc. */ | ||
| 1234 | |||
| 1235 | #ifndef DOUG_LEA_MALLOC | ||
| 1236 | extern void * (*__malloc_hook) (size_t, const void *); | ||
| 1237 | extern void * (*__realloc_hook) (void *, size_t, const void *); | ||
| 1238 | extern void (*__free_hook) (void *, const void *); | ||
| 1239 | /* Else declared in malloc.h, perhaps with an extra arg. */ | ||
| 1240 | #endif /* DOUG_LEA_MALLOC */ | ||
| 1241 | static void * (*old_malloc_hook) (size_t, const void *); | ||
| 1242 | static void * (*old_realloc_hook) (void *, size_t, const void*); | ||
| 1243 | static void (*old_free_hook) (void*, const void*); | ||
| 1244 | |||
| 1245 | #ifdef DOUG_LEA_MALLOC | ||
| 1246 | # define BYTES_USED (mallinfo ().uordblks) | ||
| 1247 | #else | ||
| 1248 | # define BYTES_USED _bytes_used | ||
| 1249 | #endif | ||
| 1250 | |||
| 1251 | #ifdef GC_MALLOC_CHECK | ||
| 1252 | static bool dont_register_blocks; | ||
| 1253 | #endif | ||
| 1254 | |||
| 1255 | static size_t bytes_used_when_reconsidered; | ||
| 1256 | |||
| 1257 | /* Value of _bytes_used, when spare_memory was freed. */ | ||
| 1258 | |||
| 1259 | static size_t bytes_used_when_full; | ||
| 1260 | |||
| 1261 | /* This function is used as the hook for free to call. */ | ||
| 1262 | |||
| 1263 | static void | ||
| 1264 | emacs_blocked_free (void *ptr, const void *ptr2) | ||
| 1265 | { | ||
| 1266 | BLOCK_INPUT_ALLOC; | ||
| 1267 | |||
| 1268 | #ifdef GC_MALLOC_CHECK | ||
| 1269 | if (ptr) | ||
| 1270 | { | ||
| 1271 | struct mem_node *m; | ||
| 1272 | |||
| 1273 | m = mem_find (ptr); | ||
| 1274 | if (m == MEM_NIL || m->start != ptr) | ||
| 1275 | { | ||
| 1276 | fprintf (stderr, | ||
| 1277 | "Freeing `%p' which wasn't allocated with malloc\n", ptr); | ||
| 1278 | emacs_abort (); | ||
| 1279 | } | ||
| 1280 | else | ||
| 1281 | { | ||
| 1282 | /* fprintf (stderr, "free %p...%p (%p)\n", m->start, m->end, ptr); */ | ||
| 1283 | mem_delete (m); | ||
| 1284 | } | ||
| 1285 | } | ||
| 1286 | #endif /* GC_MALLOC_CHECK */ | ||
| 1287 | |||
| 1288 | __free_hook = old_free_hook; | ||
| 1289 | free (ptr); | ||
| 1290 | |||
| 1291 | /* If we released our reserve (due to running out of memory), | ||
| 1292 | and we have a fair amount free once again, | ||
| 1293 | try to set aside another reserve in case we run out once more. */ | ||
| 1294 | if (! NILP (Vmemory_full) | ||
| 1295 | /* Verify there is enough space that even with the malloc | ||
| 1296 | hysteresis this call won't run out again. | ||
| 1297 | The code here is correct as long as SPARE_MEMORY | ||
| 1298 | is substantially larger than the block size malloc uses. */ | ||
| 1299 | && (bytes_used_when_full | ||
| 1300 | > ((bytes_used_when_reconsidered = BYTES_USED) | ||
| 1301 | + max (malloc_hysteresis, 4) * SPARE_MEMORY))) | ||
| 1302 | refill_memory_reserve (); | ||
| 1303 | |||
| 1304 | __free_hook = emacs_blocked_free; | ||
| 1305 | UNBLOCK_INPUT_ALLOC; | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | |||
| 1309 | /* This function is the malloc hook that Emacs uses. */ | ||
| 1310 | |||
| 1311 | static void * | ||
| 1312 | emacs_blocked_malloc (size_t size, const void *ptr) | ||
| 1313 | { | ||
| 1314 | void *value; | ||
| 1315 | |||
| 1316 | BLOCK_INPUT_ALLOC; | ||
| 1317 | __malloc_hook = old_malloc_hook; | ||
| 1318 | #ifdef DOUG_LEA_MALLOC | ||
| 1319 | /* Segfaults on my system. --lorentey */ | ||
| 1320 | /* mallopt (M_TOP_PAD, malloc_hysteresis * 4096); */ | ||
| 1321 | #else | ||
| 1322 | __malloc_extra_blocks = malloc_hysteresis; | ||
| 1323 | #endif | ||
| 1324 | |||
| 1325 | value = malloc (size); | ||
| 1326 | |||
| 1327 | #ifdef GC_MALLOC_CHECK | ||
| 1328 | { | ||
| 1329 | struct mem_node *m = mem_find (value); | ||
| 1330 | if (m != MEM_NIL) | ||
| 1331 | { | ||
| 1332 | fprintf (stderr, "Malloc returned %p which is already in use\n", | ||
| 1333 | value); | ||
| 1334 | fprintf (stderr, "Region in use is %p...%p, %td bytes, type %d\n", | ||
| 1335 | m->start, m->end, (char *) m->end - (char *) m->start, | ||
| 1336 | m->type); | ||
| 1337 | emacs_abort (); | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | if (!dont_register_blocks) | ||
| 1341 | { | ||
| 1342 | mem_insert (value, (char *) value + max (1, size), allocated_mem_type); | ||
| 1343 | allocated_mem_type = MEM_TYPE_NON_LISP; | ||
| 1344 | } | ||
| 1345 | } | ||
| 1346 | #endif /* GC_MALLOC_CHECK */ | ||
| 1347 | |||
| 1348 | __malloc_hook = emacs_blocked_malloc; | ||
| 1349 | UNBLOCK_INPUT_ALLOC; | ||
| 1350 | |||
| 1351 | /* fprintf (stderr, "%p malloc\n", value); */ | ||
| 1352 | return value; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | |||
| 1356 | /* This function is the realloc hook that Emacs uses. */ | ||
| 1357 | |||
| 1358 | static void * | ||
| 1359 | emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2) | ||
| 1360 | { | ||
| 1361 | void *value; | ||
| 1362 | |||
| 1363 | BLOCK_INPUT_ALLOC; | ||
| 1364 | __realloc_hook = old_realloc_hook; | ||
| 1365 | |||
| 1366 | #ifdef GC_MALLOC_CHECK | ||
| 1367 | if (ptr) | ||
| 1368 | { | ||
| 1369 | struct mem_node *m = mem_find (ptr); | ||
| 1370 | if (m == MEM_NIL || m->start != ptr) | ||
| 1371 | { | ||
| 1372 | fprintf (stderr, | ||
| 1373 | "Realloc of %p which wasn't allocated with malloc\n", | ||
| 1374 | ptr); | ||
| 1375 | emacs_abort (); | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | mem_delete (m); | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | /* fprintf (stderr, "%p -> realloc\n", ptr); */ | ||
| 1382 | |||
| 1383 | /* Prevent malloc from registering blocks. */ | ||
| 1384 | dont_register_blocks = 1; | ||
| 1385 | #endif /* GC_MALLOC_CHECK */ | ||
| 1386 | |||
| 1387 | value = realloc (ptr, size); | ||
| 1388 | |||
| 1389 | #ifdef GC_MALLOC_CHECK | ||
| 1390 | dont_register_blocks = 0; | ||
| 1391 | |||
| 1392 | { | ||
| 1393 | struct mem_node *m = mem_find (value); | ||
| 1394 | if (m != MEM_NIL) | ||
| 1395 | { | ||
| 1396 | fprintf (stderr, "Realloc returns memory that is already in use\n"); | ||
| 1397 | emacs_abort (); | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | /* Can't handle zero size regions in the red-black tree. */ | ||
| 1401 | mem_insert (value, (char *) value + max (size, 1), MEM_TYPE_NON_LISP); | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | /* fprintf (stderr, "%p <- realloc\n", value); */ | ||
| 1405 | #endif /* GC_MALLOC_CHECK */ | ||
| 1406 | |||
| 1407 | __realloc_hook = emacs_blocked_realloc; | ||
| 1408 | UNBLOCK_INPUT_ALLOC; | ||
| 1409 | |||
| 1410 | return value; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | |||
| 1414 | #ifdef HAVE_PTHREAD | ||
| 1415 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a | ||
| 1416 | normal malloc. Some thread implementations need this as they call | ||
| 1417 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then | ||
| 1418 | calls malloc because it is the first call, and we have an endless loop. */ | ||
| 1419 | |||
| 1420 | void | ||
| 1421 | reset_malloc_hooks (void) | ||
| 1422 | { | ||
| 1423 | __free_hook = old_free_hook; | ||
| 1424 | __malloc_hook = old_malloc_hook; | ||
| 1425 | __realloc_hook = old_realloc_hook; | ||
| 1426 | } | ||
| 1427 | #endif /* HAVE_PTHREAD */ | ||
| 1428 | |||
| 1429 | |||
| 1430 | /* Called from main to set up malloc to use our hooks. */ | ||
| 1431 | |||
| 1432 | void | ||
| 1433 | uninterrupt_malloc (void) | ||
| 1434 | { | ||
| 1435 | #ifdef HAVE_PTHREAD | ||
| 1436 | #ifdef DOUG_LEA_MALLOC | ||
| 1437 | pthread_mutexattr_t attr; | ||
| 1438 | |||
| 1439 | /* GLIBC has a faster way to do this, but let's keep it portable. | ||
| 1440 | This is according to the Single UNIX Specification. */ | ||
| 1441 | pthread_mutexattr_init (&attr); | ||
| 1442 | pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); | ||
| 1443 | pthread_mutex_init (&alloc_mutex, &attr); | ||
| 1444 | #else /* !DOUG_LEA_MALLOC */ | ||
| 1445 | /* Some systems such as Solaris 2.6 don't have a recursive mutex, | ||
| 1446 | and the bundled gmalloc.c doesn't require it. */ | ||
| 1447 | pthread_mutex_init (&alloc_mutex, NULL); | ||
| 1448 | #endif /* !DOUG_LEA_MALLOC */ | ||
| 1449 | #endif /* HAVE_PTHREAD */ | ||
| 1450 | |||
| 1451 | if (__free_hook != emacs_blocked_free) | ||
| 1452 | old_free_hook = __free_hook; | ||
| 1453 | __free_hook = emacs_blocked_free; | ||
| 1454 | |||
| 1455 | if (__malloc_hook != emacs_blocked_malloc) | ||
| 1456 | old_malloc_hook = __malloc_hook; | ||
| 1457 | __malloc_hook = emacs_blocked_malloc; | ||
| 1458 | |||
| 1459 | if (__realloc_hook != emacs_blocked_realloc) | ||
| 1460 | old_realloc_hook = __realloc_hook; | ||
| 1461 | __realloc_hook = emacs_blocked_realloc; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | #endif /* not SYNC_INPUT */ | ||
| 1465 | #endif /* not SYSTEM_MALLOC */ | ||
| 1466 | |||
| 1467 | |||
| 1468 | |||
| 1469 | /*********************************************************************** | 1144 | /*********************************************************************** |
| 1470 | Interval Allocation | 1145 | Interval Allocation |
| 1471 | ***********************************************************************/ | 1146 | ***********************************************************************/ |
| @@ -1511,8 +1186,6 @@ make_interval (void) | |||
| 1511 | { | 1186 | { |
| 1512 | INTERVAL val; | 1187 | INTERVAL val; |
| 1513 | 1188 | ||
| 1514 | /* eassert (!handling_signal); */ | ||
| 1515 | |||
| 1516 | MALLOC_BLOCK_INPUT; | 1189 | MALLOC_BLOCK_INPUT; |
| 1517 | 1190 | ||
| 1518 | if (interval_free_list) | 1191 | if (interval_free_list) |
| @@ -1896,8 +1569,6 @@ allocate_string (void) | |||
| 1896 | { | 1569 | { |
| 1897 | struct Lisp_String *s; | 1570 | struct Lisp_String *s; |
| 1898 | 1571 | ||
| 1899 | /* eassert (!handling_signal); */ | ||
| 1900 | |||
| 1901 | MALLOC_BLOCK_INPUT; | 1572 | MALLOC_BLOCK_INPUT; |
| 1902 | 1573 | ||
| 1903 | /* 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 |
| @@ -2589,8 +2260,6 @@ make_float (double float_value) | |||
| 2589 | { | 2260 | { |
| 2590 | register Lisp_Object val; | 2261 | register Lisp_Object val; |
| 2591 | 2262 | ||
| 2592 | /* eassert (!handling_signal); */ | ||
| 2593 | |||
| 2594 | MALLOC_BLOCK_INPUT; | 2263 | MALLOC_BLOCK_INPUT; |
| 2595 | 2264 | ||
| 2596 | if (float_free_list) | 2265 | if (float_free_list) |
| @@ -2698,8 +2367,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2698 | { | 2367 | { |
| 2699 | register Lisp_Object val; | 2368 | register Lisp_Object val; |
| 2700 | 2369 | ||
| 2701 | /* eassert (!handling_signal); */ | ||
| 2702 | |||
| 2703 | MALLOC_BLOCK_INPUT; | 2370 | MALLOC_BLOCK_INPUT; |
| 2704 | 2371 | ||
| 2705 | if (cons_free_list) | 2372 | if (cons_free_list) |
| @@ -3205,9 +2872,6 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3205 | 2872 | ||
| 3206 | MALLOC_BLOCK_INPUT; | 2873 | MALLOC_BLOCK_INPUT; |
| 3207 | 2874 | ||
| 3208 | /* This gets triggered by code which I haven't bothered to fix. --Stef */ | ||
| 3209 | /* eassert (!handling_signal); */ | ||
| 3210 | |||
| 3211 | if (len == 0) | 2875 | if (len == 0) |
| 3212 | p = XVECTOR (zero_vector); | 2876 | p = XVECTOR (zero_vector); |
| 3213 | else | 2877 | else |
| @@ -3492,8 +3156,6 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3492 | 3156 | ||
| 3493 | CHECK_STRING (name); | 3157 | CHECK_STRING (name); |
| 3494 | 3158 | ||
| 3495 | /* eassert (!handling_signal); */ | ||
| 3496 | |||
| 3497 | MALLOC_BLOCK_INPUT; | 3159 | MALLOC_BLOCK_INPUT; |
| 3498 | 3160 | ||
| 3499 | if (symbol_free_list) | 3161 | if (symbol_free_list) |
| @@ -3578,8 +3240,6 @@ allocate_misc (enum Lisp_Misc_Type type) | |||
| 3578 | { | 3240 | { |
| 3579 | Lisp_Object val; | 3241 | Lisp_Object val; |
| 3580 | 3242 | ||
| 3581 | /* eassert (!handling_signal); */ | ||
| 3582 | |||
| 3583 | MALLOC_BLOCK_INPUT; | 3243 | MALLOC_BLOCK_INPUT; |
| 3584 | 3244 | ||
| 3585 | if (marker_free_list) | 3245 | if (marker_free_list) |
| @@ -3799,12 +3459,6 @@ memory_full (size_t nbytes) | |||
| 3799 | lisp_free (spare_memory[i]); | 3459 | lisp_free (spare_memory[i]); |
| 3800 | spare_memory[i] = 0; | 3460 | spare_memory[i] = 0; |
| 3801 | } | 3461 | } |
| 3802 | |||
| 3803 | /* Record the space now used. When it decreases substantially, | ||
| 3804 | we can refill the memory reserve. */ | ||
| 3805 | #if !defined SYSTEM_MALLOC && !defined SYNC_INPUT | ||
| 3806 | bytes_used_when_full = BYTES_USED; | ||
| 3807 | #endif | ||
| 3808 | } | 3462 | } |
| 3809 | 3463 | ||
| 3810 | /* 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 |
| @@ -3942,7 +3596,7 @@ mem_insert (void *start, void *end, enum mem_type type) | |||
| 3942 | 3596 | ||
| 3943 | /* Create a new node. */ | 3597 | /* Create a new node. */ |
| 3944 | #ifdef GC_MALLOC_CHECK | 3598 | #ifdef GC_MALLOC_CHECK |
| 3945 | x = _malloc_internal (sizeof *x); | 3599 | x = malloc (sizeof *x); |
| 3946 | if (x == NULL) | 3600 | if (x == NULL) |
| 3947 | emacs_abort (); | 3601 | emacs_abort (); |
| 3948 | #else | 3602 | #else |
| @@ -4166,7 +3820,7 @@ mem_delete (struct mem_node *z) | |||
| 4166 | mem_delete_fixup (x); | 3820 | mem_delete_fixup (x); |
| 4167 | 3821 | ||
| 4168 | #ifdef GC_MALLOC_CHECK | 3822 | #ifdef GC_MALLOC_CHECK |
| 4169 | _free_internal (y); | 3823 | free (y); |
| 4170 | #else | 3824 | #else |
| 4171 | xfree (y); | 3825 | xfree (y); |
| 4172 | #endif | 3826 | #endif |
| @@ -6767,12 +6421,6 @@ init_alloc_once (void) | |||
| 6767 | init_strings (); | 6421 | init_strings (); |
| 6768 | init_vectors (); | 6422 | init_vectors (); |
| 6769 | 6423 | ||
| 6770 | #ifdef REL_ALLOC | ||
| 6771 | malloc_hysteresis = 32; | ||
| 6772 | #else | ||
| 6773 | malloc_hysteresis = 0; | ||
| 6774 | #endif | ||
| 6775 | |||
| 6776 | refill_memory_reserve (); | 6424 | refill_memory_reserve (); |
| 6777 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; | 6425 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; |
| 6778 | } | 6426 | } |