aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2020-05-25 20:26:14 -0700
committerPaul Eggert2020-05-25 20:29:50 -0700
commit0dc529175dc027c1567fb9b7cd529d29236aad44 (patch)
tree12e250b10b6a14d25c3c6dacc8ee82bd9e8fc4e2 /src/alloc.c
parent8b940dac32c2a37f93b8670751a0e5f72ec86cea (diff)
downloademacs-0dc529175dc027c1567fb9b7cd529d29236aad44.tar.gz
emacs-0dc529175dc027c1567fb9b7cd529d29236aad44.zip
Fix aborts due to GC losing pseudovectors
Problem reported by Eli Zaretskii (Bug#41321). * src/alloc.c (MALLOC_ALIGNMENT_BOUND): New constant. (LISP_ALIGNMENT): Lower it to avoid crashes on MinGW and similarly buggy platforms where malloc returns pointers not aligned to alignof (max_align_t). But keep it higher on platforms where this is known to work, as it helps GC performance. (MALLOC_IS_LISP_ALIGNED): Define in terms of the other two. * src/alloc.c (stacktop_sentry): * src/thread.c (run_thread): Don’t overalign or oversize stack sentries; they need to be aligned only for pointers and Lisp_Object, not for arbitrary pseudovector contents. * src/lisp.h (union emacs_align_type): New type, used for LISP_ALIGNMENT.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/src/alloc.c b/src/alloc.c
index d5a6d9167ea..602282e5704 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -112,9 +112,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
112 adds sizeof (size_t) to SIZE for internal overhead, and then rounds 112 adds sizeof (size_t) to SIZE for internal overhead, and then rounds
113 up to a multiple of MALLOC_ALIGNMENT. Emacs can improve 113 up to a multiple of MALLOC_ALIGNMENT. Emacs can improve
114 performance a bit on GNU platforms by arranging for the resulting 114 performance a bit on GNU platforms by arranging for the resulting
115 size to be a power of two. This heuristic is good for glibc 2.0 115 size to be a power of two. This heuristic is good for glibc 2.26
116 (1997) through at least glibc 2.31 (2020), and does not affect 116 (2017) and later, and does not affect correctness on other
117 correctness on other platforms. */ 117 platforms. */
118 118
119#define MALLOC_SIZE_NEAR(n) \ 119#define MALLOC_SIZE_NEAR(n) \
120 (ROUNDUP (max (n, sizeof (size_t)), MALLOC_ALIGNMENT) - sizeof (size_t)) 120 (ROUNDUP (max (n, sizeof (size_t)), MALLOC_ALIGNMENT) - sizeof (size_t))
@@ -655,28 +655,30 @@ buffer_memory_full (ptrdiff_t nbytes)
655#define COMMON_MULTIPLE(a, b) \ 655#define COMMON_MULTIPLE(a, b) \
656 ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) 656 ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b))
657 657
658/* LISP_ALIGNMENT is the alignment of Lisp objects. It must be at 658/* A lower bound on the alignment of malloc. For better performance
659 least GCALIGNMENT so that pointers can be tagged. It also must be 659 this bound should be tighter. For glibc 2.26 and later a tighter
660 at least as strict as the alignment of all the C types used to 660 bound is known. */
661 implement Lisp objects; since pseudovectors can contain any C type, 661#if 2 < __GLIBC__ + (26 <= __GLIBC_MINOR__)
662 this is max_align_t. On recent GNU/Linux x86 and x86-64 this can 662enum { MALLOC_ALIGNMENT_BOUND = MALLOC_ALIGNMENT };
663 often waste up to 8 bytes, since alignof (max_align_t) is 16 but 663#else
664 typical vectors need only an alignment of 8. Although shrinking 664/* A bound known to work for all Emacs porting targets. Tightening
665 the alignment to 8 would save memory, it cost a 20% hit to Emacs 665 this looser bound by using max_align_t instead of long long int
666 CPU performance on Fedora 28 x86-64 when compiled with gcc -m32. */ 666 would break buggy malloc implementations like MinGW circa 2020. */
667enum { LISP_ALIGNMENT = alignof (union { max_align_t x; 667enum { MALLOC_ALIGNMENT_BOUND = alignof (long long int) };
668 GCALIGNED_UNION_MEMBER }) }; 668#endif
669verify (LISP_ALIGNMENT % GCALIGNMENT == 0); 669
670/* A lower bound on the alignment of Lisp objects. All Lisp objects
671 must have an address that is a multiple of LISP_ALIGNMENT;
672 otherwise maybe_lisp_pointer can issue false negatives, causing crashes.
673 It's good to make this bound tight: if Lisp objects are always
674 aligned more strictly than LISP_ALIGNMENT, maybe_lisp_pointer will
675 issue more false positives, hurting performance. */
676enum { LISP_ALIGNMENT = max (max (GCALIGNMENT, MALLOC_ALIGNMENT_BOUND),
677 alignof (union emacs_align_type)) };
670 678
671/* True if malloc (N) is known to return storage suitably aligned for 679/* True if malloc (N) is known to return storage suitably aligned for
672 Lisp objects whenever N is a multiple of LISP_ALIGNMENT. In 680 Lisp objects whenever N is a multiple of LISP_ALIGNMENT. */
673 practice this is true whenever alignof (max_align_t) is also a 681enum { MALLOC_IS_LISP_ALIGNED = MALLOC_ALIGNMENT_BOUND % LISP_ALIGNMENT == 0 };
674 multiple of LISP_ALIGNMENT. This works even for x86, where some
675 platform combinations (e.g., GCC 7 and later, glibc 2.25 and
676 earlier) have bugs where alignof (max_align_t) is 16 even though
677 the malloc alignment is only 8, and where Emacs still works because
678 it never does anything that requires an alignment of 16. */
679enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 };
680 682
681/* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol 683/* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol
682 BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger. 684 BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger.
@@ -4885,9 +4887,10 @@ test_setjmp (void)
4885 as a stack scan limit. */ 4887 as a stack scan limit. */
4886typedef union 4888typedef union
4887{ 4889{
4888 /* Align the stack top properly. Even if !HAVE___BUILTIN_UNWIND_INIT, 4890 /* Make sure stack_top and m_stack_bottom are properly aligned as GC
4889 jmp_buf may not be aligned enough on darwin-ppc64. */ 4891 expects. */
4890 max_align_t o; 4892 Lisp_Object o;
4893 void *p;
4891#ifndef HAVE___BUILTIN_UNWIND_INIT 4894#ifndef HAVE___BUILTIN_UNWIND_INIT
4892 sys_jmp_buf j; 4895 sys_jmp_buf j;
4893 char c; 4896 char c;