diff options
| author | Miles Bader | 2004-12-08 05:02:30 +0000 |
|---|---|---|
| committer | Miles Bader | 2004-12-08 05:02:30 +0000 |
| commit | 000fc2b1fad05ccd9e6cdb5810febb091f4b5738 (patch) | |
| tree | 808f1473847c7c44bc8b28d8edfa086ec25035d1 /src/alloc.c | |
| parent | 5bc63b073c3c75dbfab1f14423f01cc615e26eeb (diff) | |
| parent | ad136a7c3b310fa7240dd2adf62f23b454782bd0 (diff) | |
| download | emacs-000fc2b1fad05ccd9e6cdb5810febb091f4b5738.tar.gz emacs-000fc2b1fad05ccd9e6cdb5810febb091f4b5738.zip | |
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-74
Merge from emacs--cvs-trunk--0
Patches applied:
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-709
Update from CVS: src/indent.c (Fvertical_motion): Fix last change.
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-710
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-715
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-716
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-74
Update from CVS
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 310 |
1 files changed, 295 insertions, 15 deletions
diff --git a/src/alloc.c b/src/alloc.c index e783ba581e0..2a539920f22 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -31,6 +31,10 @@ Boston, MA 02111-1307, USA. */ | |||
| 31 | 31 | ||
| 32 | #include <signal.h> | 32 | #include <signal.h> |
| 33 | 33 | ||
| 34 | #ifdef HAVE_GTK_AND_PTHREAD | ||
| 35 | #include <pthread.h> | ||
| 36 | #endif | ||
| 37 | |||
| 34 | /* This file is part of the core Lisp implementation, and thus must | 38 | /* This file is part of the core Lisp implementation, and thus must |
| 35 | deal with the real data structures. If the Lisp implementation is | 39 | deal with the real data structures. If the Lisp implementation is |
| 36 | replaced, this file likely will not be used. */ | 40 | replaced, this file likely will not be used. */ |
| @@ -85,6 +89,52 @@ extern __malloc_size_t __malloc_extra_blocks; | |||
| 85 | 89 | ||
| 86 | #endif /* not DOUG_LEA_MALLOC */ | 90 | #endif /* not DOUG_LEA_MALLOC */ |
| 87 | 91 | ||
| 92 | #if ! defined (SYSTEM_MALLOC) && defined (HAVE_GTK_AND_PTHREAD) | ||
| 93 | |||
| 94 | /* When GTK uses the file chooser dialog, different backends can be loaded | ||
| 95 | dynamically. One such a backend is the Gnome VFS backend that gets loaded | ||
| 96 | if you run Gnome. That backend creates several threads and also allocates | ||
| 97 | memory with malloc. | ||
| 98 | |||
| 99 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* | ||
| 100 | functions below are called from malloc, there is a chance that one | ||
| 101 | of these threads preempts the Emacs main thread and the hook variables | ||
| 102 | end up in a inconsistent state. So we have a mutex to prevent that (note | ||
| 103 | that the backend handles concurrent access to malloc within its own threads | ||
| 104 | but Emacs code running in the main thread is not included in that control). | ||
| 105 | |||
| 106 | When UNBLOCK_INPUT is called, revoke_input_signal may be called. If this | ||
| 107 | happens in one of the backend threads we will have two threads that tries | ||
| 108 | to run Emacs code at once, and the code is not prepared for that. | ||
| 109 | To prevent that, we only call BLOCK/UNBLOCK from the main thread. */ | ||
| 110 | |||
| 111 | static pthread_mutex_t alloc_mutex; | ||
| 112 | pthread_t main_thread; | ||
| 113 | |||
| 114 | #define BLOCK_INPUT_ALLOC \ | ||
| 115 | do \ | ||
| 116 | { \ | ||
| 117 | pthread_mutex_lock (&alloc_mutex); \ | ||
| 118 | if (pthread_self () == main_thread) \ | ||
| 119 | BLOCK_INPUT; \ | ||
| 120 | } \ | ||
| 121 | while (0) | ||
| 122 | #define UNBLOCK_INPUT_ALLOC \ | ||
| 123 | do \ | ||
| 124 | { \ | ||
| 125 | if (pthread_self () == main_thread) \ | ||
| 126 | UNBLOCK_INPUT; \ | ||
| 127 | pthread_mutex_unlock (&alloc_mutex); \ | ||
| 128 | } \ | ||
| 129 | while (0) | ||
| 130 | |||
| 131 | #else /* SYSTEM_MALLOC || not HAVE_GTK_AND_PTHREAD */ | ||
| 132 | |||
| 133 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT | ||
| 134 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT | ||
| 135 | |||
| 136 | #endif /* SYSTEM_MALLOC || not HAVE_GTK_AND_PTHREAD */ | ||
| 137 | |||
| 88 | /* Value of _bytes_used, when spare_memory was freed. */ | 138 | /* Value of _bytes_used, when spare_memory was freed. */ |
| 89 | 139 | ||
| 90 | static __malloc_size_t bytes_used_when_full; | 140 | static __malloc_size_t bytes_used_when_full; |
| @@ -516,6 +566,140 @@ buffer_memory_full () | |||
| 516 | } | 566 | } |
| 517 | 567 | ||
| 518 | 568 | ||
| 569 | #ifdef XMALLOC_OVERRUN_CHECK | ||
| 570 | |||
| 571 | /* Check for overrun in malloc'ed buffers by wrapping a 16 byte header | ||
| 572 | and a 16 byte trailer around each block. | ||
| 573 | |||
| 574 | The header consists of 12 fixed bytes + a 4 byte integer contaning the | ||
| 575 | original block size, while the trailer consists of 16 fixed bytes. | ||
| 576 | |||
| 577 | The header is used to detect whether this block has been allocated | ||
| 578 | through these functions -- as it seems that some low-level libc | ||
| 579 | functions may bypass the malloc hooks. | ||
| 580 | */ | ||
| 581 | |||
| 582 | |||
| 583 | #define XMALLOC_OVERRUN_CHECK_SIZE 16 | ||
| 584 | |||
| 585 | static char xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE-4] = | ||
| 586 | { 0x9a, 0x9b, 0xae, 0xaf, | ||
| 587 | 0xbf, 0xbe, 0xce, 0xcf, | ||
| 588 | 0xea, 0xeb, 0xec, 0xed }; | ||
| 589 | |||
| 590 | static char xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] = | ||
| 591 | { 0xaa, 0xab, 0xac, 0xad, | ||
| 592 | 0xba, 0xbb, 0xbc, 0xbd, | ||
| 593 | 0xca, 0xcb, 0xcc, 0xcd, | ||
| 594 | 0xda, 0xdb, 0xdc, 0xdd }; | ||
| 595 | |||
| 596 | /* Macros to insert and extract the block size in the header. */ | ||
| 597 | |||
| 598 | #define XMALLOC_PUT_SIZE(ptr, size) \ | ||
| 599 | (ptr[-1] = (size & 0xff), \ | ||
| 600 | ptr[-2] = ((size >> 8) & 0xff), \ | ||
| 601 | ptr[-3] = ((size >> 16) & 0xff), \ | ||
| 602 | ptr[-4] = ((size >> 24) & 0xff)) | ||
| 603 | |||
| 604 | #define XMALLOC_GET_SIZE(ptr) \ | ||
| 605 | (size_t)((unsigned)(ptr[-1]) | \ | ||
| 606 | ((unsigned)(ptr[-2]) << 8) | \ | ||
| 607 | ((unsigned)(ptr[-3]) << 16) | \ | ||
| 608 | ((unsigned)(ptr[-4]) << 24)) | ||
| 609 | |||
| 610 | |||
| 611 | /* Like malloc, but wraps allocated block with header and trailer. */ | ||
| 612 | |||
| 613 | POINTER_TYPE * | ||
| 614 | overrun_check_malloc (size) | ||
| 615 | size_t size; | ||
| 616 | { | ||
| 617 | register unsigned char *val; | ||
| 618 | |||
| 619 | val = (unsigned char *) malloc (size + XMALLOC_OVERRUN_CHECK_SIZE*2); | ||
| 620 | if (val) | ||
| 621 | { | ||
| 622 | bcopy (xmalloc_overrun_check_header, val, XMALLOC_OVERRUN_CHECK_SIZE - 4); | ||
| 623 | val += XMALLOC_OVERRUN_CHECK_SIZE; | ||
| 624 | XMALLOC_PUT_SIZE(val, size); | ||
| 625 | bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE); | ||
| 626 | } | ||
| 627 | return (POINTER_TYPE *)val; | ||
| 628 | } | ||
| 629 | |||
| 630 | |||
| 631 | /* Like realloc, but checks old block for overrun, and wraps new block | ||
| 632 | with header and trailer. */ | ||
| 633 | |||
| 634 | POINTER_TYPE * | ||
| 635 | overrun_check_realloc (block, size) | ||
| 636 | POINTER_TYPE *block; | ||
| 637 | size_t size; | ||
| 638 | { | ||
| 639 | register unsigned char *val = (unsigned char *)block; | ||
| 640 | |||
| 641 | if (val | ||
| 642 | && bcmp (xmalloc_overrun_check_header, | ||
| 643 | val - XMALLOC_OVERRUN_CHECK_SIZE, | ||
| 644 | XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0) | ||
| 645 | { | ||
| 646 | size_t osize = XMALLOC_GET_SIZE (val); | ||
| 647 | if (bcmp (xmalloc_overrun_check_trailer, | ||
| 648 | val + osize, | ||
| 649 | XMALLOC_OVERRUN_CHECK_SIZE)) | ||
| 650 | abort (); | ||
| 651 | bzero (val + osize, XMALLOC_OVERRUN_CHECK_SIZE); | ||
| 652 | val -= XMALLOC_OVERRUN_CHECK_SIZE; | ||
| 653 | bzero (val, XMALLOC_OVERRUN_CHECK_SIZE); | ||
| 654 | } | ||
| 655 | |||
| 656 | val = (unsigned char *) realloc ((POINTER_TYPE *)val, size + XMALLOC_OVERRUN_CHECK_SIZE*2); | ||
| 657 | |||
| 658 | if (val) | ||
| 659 | { | ||
| 660 | bcopy (xmalloc_overrun_check_header, val, XMALLOC_OVERRUN_CHECK_SIZE - 4); | ||
| 661 | val += XMALLOC_OVERRUN_CHECK_SIZE; | ||
| 662 | XMALLOC_PUT_SIZE(val, size); | ||
| 663 | bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE); | ||
| 664 | } | ||
| 665 | return (POINTER_TYPE *)val; | ||
| 666 | } | ||
| 667 | |||
| 668 | /* Like free, but checks block for overrun. */ | ||
| 669 | |||
| 670 | void | ||
| 671 | overrun_check_free (block) | ||
| 672 | POINTER_TYPE *block; | ||
| 673 | { | ||
| 674 | unsigned char *val = (unsigned char *)block; | ||
| 675 | |||
| 676 | if (val | ||
| 677 | && bcmp (xmalloc_overrun_check_header, | ||
| 678 | val - XMALLOC_OVERRUN_CHECK_SIZE, | ||
| 679 | XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0) | ||
| 680 | { | ||
| 681 | size_t osize = XMALLOC_GET_SIZE (val); | ||
| 682 | if (bcmp (xmalloc_overrun_check_trailer, | ||
| 683 | val + osize, | ||
| 684 | XMALLOC_OVERRUN_CHECK_SIZE)) | ||
| 685 | abort (); | ||
| 686 | bzero (val + osize, XMALLOC_OVERRUN_CHECK_SIZE); | ||
| 687 | val -= XMALLOC_OVERRUN_CHECK_SIZE; | ||
| 688 | bzero (val, XMALLOC_OVERRUN_CHECK_SIZE); | ||
| 689 | } | ||
| 690 | |||
| 691 | free (val); | ||
| 692 | } | ||
| 693 | |||
| 694 | #undef malloc | ||
| 695 | #undef realloc | ||
| 696 | #undef free | ||
| 697 | #define malloc overrun_check_malloc | ||
| 698 | #define realloc overrun_check_realloc | ||
| 699 | #define free overrun_check_free | ||
| 700 | #endif | ||
| 701 | |||
| 702 | |||
| 519 | /* Like malloc but check for no memory and block interrupt input.. */ | 703 | /* Like malloc but check for no memory and block interrupt input.. */ |
| 520 | 704 | ||
| 521 | POINTER_TYPE * | 705 | POINTER_TYPE * |
| @@ -602,7 +786,9 @@ safe_alloca_unwind (arg) | |||
| 602 | number of bytes to allocate, TYPE describes the intended use of the | 786 | number of bytes to allocate, TYPE describes the intended use of the |
| 603 | allcated memory block (for strings, for conses, ...). */ | 787 | allcated memory block (for strings, for conses, ...). */ |
| 604 | 788 | ||
| 789 | #ifndef USE_LSB_TAG | ||
| 605 | static void *lisp_malloc_loser; | 790 | static void *lisp_malloc_loser; |
| 791 | #endif | ||
| 606 | 792 | ||
| 607 | static POINTER_TYPE * | 793 | static POINTER_TYPE * |
| 608 | lisp_malloc (nbytes, type) | 794 | lisp_malloc (nbytes, type) |
| @@ -932,7 +1118,7 @@ static void | |||
| 932 | emacs_blocked_free (ptr) | 1118 | emacs_blocked_free (ptr) |
| 933 | void *ptr; | 1119 | void *ptr; |
| 934 | { | 1120 | { |
| 935 | BLOCK_INPUT; | 1121 | BLOCK_INPUT_ALLOC; |
| 936 | 1122 | ||
| 937 | #ifdef GC_MALLOC_CHECK | 1123 | #ifdef GC_MALLOC_CHECK |
| 938 | if (ptr) | 1124 | if (ptr) |
| @@ -970,7 +1156,7 @@ emacs_blocked_free (ptr) | |||
| 970 | spare_memory = (char *) malloc ((size_t) SPARE_MEMORY); | 1156 | spare_memory = (char *) malloc ((size_t) SPARE_MEMORY); |
| 971 | 1157 | ||
| 972 | __free_hook = emacs_blocked_free; | 1158 | __free_hook = emacs_blocked_free; |
| 973 | UNBLOCK_INPUT; | 1159 | UNBLOCK_INPUT_ALLOC; |
| 974 | } | 1160 | } |
| 975 | 1161 | ||
| 976 | 1162 | ||
| @@ -996,7 +1182,7 @@ emacs_blocked_malloc (size) | |||
| 996 | { | 1182 | { |
| 997 | void *value; | 1183 | void *value; |
| 998 | 1184 | ||
| 999 | BLOCK_INPUT; | 1185 | BLOCK_INPUT_ALLOC; |
| 1000 | __malloc_hook = old_malloc_hook; | 1186 | __malloc_hook = old_malloc_hook; |
| 1001 | #ifdef DOUG_LEA_MALLOC | 1187 | #ifdef DOUG_LEA_MALLOC |
| 1002 | mallopt (M_TOP_PAD, malloc_hysteresis * 4096); | 1188 | mallopt (M_TOP_PAD, malloc_hysteresis * 4096); |
| @@ -1028,7 +1214,7 @@ emacs_blocked_malloc (size) | |||
| 1028 | #endif /* GC_MALLOC_CHECK */ | 1214 | #endif /* GC_MALLOC_CHECK */ |
| 1029 | 1215 | ||
| 1030 | __malloc_hook = emacs_blocked_malloc; | 1216 | __malloc_hook = emacs_blocked_malloc; |
| 1031 | UNBLOCK_INPUT; | 1217 | UNBLOCK_INPUT_ALLOC; |
| 1032 | 1218 | ||
| 1033 | /* fprintf (stderr, "%p malloc\n", value); */ | 1219 | /* fprintf (stderr, "%p malloc\n", value); */ |
| 1034 | return value; | 1220 | return value; |
| @@ -1044,7 +1230,7 @@ emacs_blocked_realloc (ptr, size) | |||
| 1044 | { | 1230 | { |
| 1045 | void *value; | 1231 | void *value; |
| 1046 | 1232 | ||
| 1047 | BLOCK_INPUT; | 1233 | BLOCK_INPUT_ALLOC; |
| 1048 | __realloc_hook = old_realloc_hook; | 1234 | __realloc_hook = old_realloc_hook; |
| 1049 | 1235 | ||
| 1050 | #ifdef GC_MALLOC_CHECK | 1236 | #ifdef GC_MALLOC_CHECK |
| @@ -1089,17 +1275,45 @@ emacs_blocked_realloc (ptr, size) | |||
| 1089 | #endif /* GC_MALLOC_CHECK */ | 1275 | #endif /* GC_MALLOC_CHECK */ |
| 1090 | 1276 | ||
| 1091 | __realloc_hook = emacs_blocked_realloc; | 1277 | __realloc_hook = emacs_blocked_realloc; |
| 1092 | UNBLOCK_INPUT; | 1278 | UNBLOCK_INPUT_ALLOC; |
| 1093 | 1279 | ||
| 1094 | return value; | 1280 | return value; |
| 1095 | } | 1281 | } |
| 1096 | 1282 | ||
| 1097 | 1283 | ||
| 1284 | #ifdef HAVE_GTK_AND_PTHREAD | ||
| 1285 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a | ||
| 1286 | normal malloc. Some thread implementations need this as they call | ||
| 1287 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then | ||
| 1288 | calls malloc because it is the first call, and we have an endless loop. */ | ||
| 1289 | |||
| 1290 | void | ||
| 1291 | reset_malloc_hooks () | ||
| 1292 | { | ||
| 1293 | __free_hook = 0; | ||
| 1294 | __malloc_hook = 0; | ||
| 1295 | __realloc_hook = 0; | ||
| 1296 | } | ||
| 1297 | #endif /* HAVE_GTK_AND_PTHREAD */ | ||
| 1298 | |||
| 1299 | |||
| 1098 | /* Called from main to set up malloc to use our hooks. */ | 1300 | /* Called from main to set up malloc to use our hooks. */ |
| 1099 | 1301 | ||
| 1100 | void | 1302 | void |
| 1101 | uninterrupt_malloc () | 1303 | uninterrupt_malloc () |
| 1102 | { | 1304 | { |
| 1305 | #ifdef HAVE_GTK_AND_PTHREAD | ||
| 1306 | pthread_mutexattr_t attr; | ||
| 1307 | |||
| 1308 | /* GLIBC has a faster way to do this, but lets keep it portable. | ||
| 1309 | This is according to the Single UNIX Specification. */ | ||
| 1310 | pthread_mutexattr_init (&attr); | ||
| 1311 | pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); | ||
| 1312 | pthread_mutex_init (&alloc_mutex, &attr); | ||
| 1313 | |||
| 1314 | main_thread = pthread_self (); | ||
| 1315 | #endif /* HAVE_GTK_AND_PTHREAD */ | ||
| 1316 | |||
| 1103 | if (__free_hook != emacs_blocked_free) | 1317 | if (__free_hook != emacs_blocked_free) |
| 1104 | old_free_hook = __free_hook; | 1318 | old_free_hook = __free_hook; |
| 1105 | __free_hook = emacs_blocked_free; | 1319 | __free_hook = emacs_blocked_free; |
| @@ -1428,6 +1642,21 @@ static int total_string_size; | |||
| 1428 | 1642 | ||
| 1429 | #endif /* not GC_CHECK_STRING_BYTES */ | 1643 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 1430 | 1644 | ||
| 1645 | |||
| 1646 | #ifdef GC_CHECK_STRING_OVERRUN | ||
| 1647 | |||
| 1648 | /* We check for overrun in string data blocks by appending a small | ||
| 1649 | "cookie" after each allocated string data block, and check for the | ||
| 1650 | presense of this cookie during GC. */ | ||
| 1651 | |||
| 1652 | #define GC_STRING_OVERRUN_COOKIE_SIZE 4 | ||
| 1653 | static char string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] = | ||
| 1654 | { 0xde, 0xad, 0xbe, 0xef }; | ||
| 1655 | |||
| 1656 | #else | ||
| 1657 | #define GC_STRING_OVERRUN_COOKIE_SIZE 0 | ||
| 1658 | #endif | ||
| 1659 | |||
| 1431 | /* Value is the size of an sdata structure large enough to hold NBYTES | 1660 | /* Value is the size of an sdata structure large enough to hold NBYTES |
| 1432 | bytes of string data. The value returned includes a terminating | 1661 | bytes of string data. The value returned includes a terminating |
| 1433 | NUL byte, the size of the sdata structure, and padding. */ | 1662 | NUL byte, the size of the sdata structure, and padding. */ |
| @@ -1451,6 +1680,10 @@ static int total_string_size; | |||
| 1451 | 1680 | ||
| 1452 | #endif /* not GC_CHECK_STRING_BYTES */ | 1681 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 1453 | 1682 | ||
| 1683 | /* Extra bytes to allocate for each string. */ | ||
| 1684 | |||
| 1685 | #define GC_STRING_EXTRA (GC_STRING_OVERRUN_COOKIE_SIZE) | ||
| 1686 | |||
| 1454 | /* Initialize string allocation. Called from init_alloc_once. */ | 1687 | /* Initialize string allocation. Called from init_alloc_once. */ |
| 1455 | 1688 | ||
| 1456 | void | 1689 | void |
| @@ -1515,7 +1748,7 @@ check_sblock (b) | |||
| 1515 | nbytes = SDATA_NBYTES (from); | 1748 | nbytes = SDATA_NBYTES (from); |
| 1516 | 1749 | ||
| 1517 | nbytes = SDATA_SIZE (nbytes); | 1750 | nbytes = SDATA_SIZE (nbytes); |
| 1518 | from_end = (struct sdata *) ((char *) from + nbytes); | 1751 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1519 | } | 1752 | } |
| 1520 | } | 1753 | } |
| 1521 | 1754 | ||
| @@ -1548,6 +1781,28 @@ check_string_bytes (all_p) | |||
| 1548 | 1781 | ||
| 1549 | #endif /* GC_CHECK_STRING_BYTES */ | 1782 | #endif /* GC_CHECK_STRING_BYTES */ |
| 1550 | 1783 | ||
| 1784 | #ifdef GC_CHECK_STRING_FREE_LIST | ||
| 1785 | |||
| 1786 | /* Walk through the string free list looking for bogus next pointers. | ||
| 1787 | This may catch buffer overrun from a previous string. */ | ||
| 1788 | |||
| 1789 | static void | ||
| 1790 | check_string_free_list () | ||
| 1791 | { | ||
| 1792 | struct Lisp_String *s; | ||
| 1793 | |||
| 1794 | /* Pop a Lisp_String off the free-list. */ | ||
| 1795 | s = string_free_list; | ||
| 1796 | while (s != NULL) | ||
| 1797 | { | ||
| 1798 | if ((unsigned)s < 1024) | ||
| 1799 | abort(); | ||
| 1800 | s = NEXT_FREE_LISP_STRING (s); | ||
| 1801 | } | ||
| 1802 | } | ||
| 1803 | #else | ||
| 1804 | #define check_string_free_list() | ||
| 1805 | #endif | ||
| 1551 | 1806 | ||
| 1552 | /* Return a new Lisp_String. */ | 1807 | /* Return a new Lisp_String. */ |
| 1553 | 1808 | ||
| @@ -1579,6 +1834,8 @@ allocate_string () | |||
| 1579 | total_free_strings += STRING_BLOCK_SIZE; | 1834 | total_free_strings += STRING_BLOCK_SIZE; |
| 1580 | } | 1835 | } |
| 1581 | 1836 | ||
| 1837 | check_string_free_list (); | ||
| 1838 | |||
| 1582 | /* Pop a Lisp_String off the free-list. */ | 1839 | /* Pop a Lisp_String off the free-list. */ |
| 1583 | s = string_free_list; | 1840 | s = string_free_list; |
| 1584 | string_free_list = NEXT_FREE_LISP_STRING (s); | 1841 | string_free_list = NEXT_FREE_LISP_STRING (s); |
| @@ -1648,7 +1905,7 @@ allocate_string_data (s, nchars, nbytes) | |||
| 1648 | mallopt (M_MMAP_MAX, 0); | 1905 | mallopt (M_MMAP_MAX, 0); |
| 1649 | #endif | 1906 | #endif |
| 1650 | 1907 | ||
| 1651 | b = (struct sblock *) lisp_malloc (size, MEM_TYPE_NON_LISP); | 1908 | b = (struct sblock *) lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); |
| 1652 | 1909 | ||
| 1653 | #ifdef DOUG_LEA_MALLOC | 1910 | #ifdef DOUG_LEA_MALLOC |
| 1654 | /* Back to a reasonable maximum of mmap'ed areas. */ | 1911 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| @@ -1663,7 +1920,7 @@ allocate_string_data (s, nchars, nbytes) | |||
| 1663 | else if (current_sblock == NULL | 1920 | else if (current_sblock == NULL |
| 1664 | || (((char *) current_sblock + SBLOCK_SIZE | 1921 | || (((char *) current_sblock + SBLOCK_SIZE |
| 1665 | - (char *) current_sblock->next_free) | 1922 | - (char *) current_sblock->next_free) |
| 1666 | < needed)) | 1923 | < (needed + GC_STRING_EXTRA))) |
| 1667 | { | 1924 | { |
| 1668 | /* Not enough room in the current sblock. */ | 1925 | /* Not enough room in the current sblock. */ |
| 1669 | b = (struct sblock *) lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); | 1926 | b = (struct sblock *) lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); |
| @@ -1692,7 +1949,11 @@ allocate_string_data (s, nchars, nbytes) | |||
| 1692 | s->size = nchars; | 1949 | s->size = nchars; |
| 1693 | s->size_byte = nbytes; | 1950 | s->size_byte = nbytes; |
| 1694 | s->data[nbytes] = '\0'; | 1951 | s->data[nbytes] = '\0'; |
| 1695 | b->next_free = (struct sdata *) ((char *) data + needed); | 1952 | #ifdef GC_CHECK_STRING_OVERRUN |
| 1953 | bcopy (string_overrun_cookie, (char *) data + needed, | ||
| 1954 | GC_STRING_OVERRUN_COOKIE_SIZE); | ||
| 1955 | #endif | ||
| 1956 | b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); | ||
| 1696 | 1957 | ||
| 1697 | /* If S had already data assigned, mark that as free by setting its | 1958 | /* If S had already data assigned, mark that as free by setting its |
| 1698 | string back-pointer to null, and recording the size of the data | 1959 | string back-pointer to null, and recording the size of the data |
| @@ -1797,9 +2058,13 @@ sweep_strings () | |||
| 1797 | } | 2058 | } |
| 1798 | } | 2059 | } |
| 1799 | 2060 | ||
| 2061 | check_string_free_list (); | ||
| 2062 | |||
| 1800 | string_blocks = live_blocks; | 2063 | string_blocks = live_blocks; |
| 1801 | free_large_strings (); | 2064 | free_large_strings (); |
| 1802 | compact_small_strings (); | 2065 | compact_small_strings (); |
| 2066 | |||
| 2067 | check_string_free_list (); | ||
| 1803 | } | 2068 | } |
| 1804 | 2069 | ||
| 1805 | 2070 | ||
| @@ -1871,28 +2136,38 @@ compact_small_strings () | |||
| 1871 | else | 2136 | else |
| 1872 | nbytes = SDATA_NBYTES (from); | 2137 | nbytes = SDATA_NBYTES (from); |
| 1873 | 2138 | ||
| 2139 | if (nbytes > LARGE_STRING_BYTES) | ||
| 2140 | abort (); | ||
| 2141 | |||
| 1874 | nbytes = SDATA_SIZE (nbytes); | 2142 | nbytes = SDATA_SIZE (nbytes); |
| 1875 | from_end = (struct sdata *) ((char *) from + nbytes); | 2143 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 2144 | |||
| 2145 | #ifdef GC_CHECK_STRING_OVERRUN | ||
| 2146 | if (bcmp (string_overrun_cookie, | ||
| 2147 | ((char *) from_end) - GC_STRING_OVERRUN_COOKIE_SIZE, | ||
| 2148 | GC_STRING_OVERRUN_COOKIE_SIZE)) | ||
| 2149 | abort (); | ||
| 2150 | #endif | ||
| 1876 | 2151 | ||
| 1877 | /* FROM->string non-null means it's alive. Copy its data. */ | 2152 | /* FROM->string non-null means it's alive. Copy its data. */ |
| 1878 | if (from->string) | 2153 | if (from->string) |
| 1879 | { | 2154 | { |
| 1880 | /* If TB is full, proceed with the next sblock. */ | 2155 | /* If TB is full, proceed with the next sblock. */ |
| 1881 | to_end = (struct sdata *) ((char *) to + nbytes); | 2156 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1882 | if (to_end > tb_end) | 2157 | if (to_end > tb_end) |
| 1883 | { | 2158 | { |
| 1884 | tb->next_free = to; | 2159 | tb->next_free = to; |
| 1885 | tb = tb->next; | 2160 | tb = tb->next; |
| 1886 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 2161 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1887 | to = &tb->first_data; | 2162 | to = &tb->first_data; |
| 1888 | to_end = (struct sdata *) ((char *) to + nbytes); | 2163 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1889 | } | 2164 | } |
| 1890 | 2165 | ||
| 1891 | /* Copy, and update the string's `data' pointer. */ | 2166 | /* Copy, and update the string's `data' pointer. */ |
| 1892 | if (from != to) | 2167 | if (from != to) |
| 1893 | { | 2168 | { |
| 1894 | xassert (tb != b || to <= from); | 2169 | xassert (tb != b || to <= from); |
| 1895 | safe_bcopy ((char *) from, (char *) to, nbytes); | 2170 | safe_bcopy ((char *) from, (char *) to, nbytes + GC_STRING_EXTRA); |
| 1896 | to->string->data = SDATA_DATA (to); | 2171 | to->string->data = SDATA_DATA (to); |
| 1897 | } | 2172 | } |
| 1898 | 2173 | ||
| @@ -2402,9 +2677,9 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2402 | void | 2677 | void |
| 2403 | check_cons_list () | 2678 | check_cons_list () |
| 2404 | { | 2679 | { |
| 2680 | #ifdef GC_CHECK_CONS_LIST | ||
| 2405 | struct Lisp_Cons *tail = cons_free_list; | 2681 | struct Lisp_Cons *tail = cons_free_list; |
| 2406 | 2682 | ||
| 2407 | #if 0 | ||
| 2408 | while (tail) | 2683 | while (tail) |
| 2409 | tail = *(struct Lisp_Cons **)&tail->cdr; | 2684 | tail = *(struct Lisp_Cons **)&tail->cdr; |
| 2410 | #endif | 2685 | #endif |
| @@ -4056,6 +4331,11 @@ mark_stack () | |||
| 4056 | #endif | 4331 | #endif |
| 4057 | for (i = 0; i < sizeof (Lisp_Object); i += GC_LISP_OBJECT_ALIGNMENT) | 4332 | for (i = 0; i < sizeof (Lisp_Object); i += GC_LISP_OBJECT_ALIGNMENT) |
| 4058 | mark_memory ((char *) stack_base + i, end); | 4333 | mark_memory ((char *) stack_base + i, end); |
| 4334 | /* Allow for marking a secondary stack, like the register stack on the | ||
| 4335 | ia64. */ | ||
| 4336 | #ifdef GC_MARK_SECONDARY_STACK | ||
| 4337 | GC_MARK_SECONDARY_STACK (); | ||
| 4338 | #endif | ||
| 4059 | 4339 | ||
| 4060 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 4340 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| 4061 | check_gcpros (); | 4341 | check_gcpros (); |