aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/alloc.c55
-rw-r--r--src/lisp.h43
-rw-r--r--src/thread.c9
3 files changed, 78 insertions, 29 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;
diff --git a/src/lisp.h b/src/lisp.h
index 85bdc172b20..937052f6df8 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -277,7 +277,8 @@ error !;
277 allocation in a containing union that has GCALIGNED_UNION_MEMBER) 277 allocation in a containing union that has GCALIGNED_UNION_MEMBER)
278 and does not contain a GC-aligned struct or union, putting 278 and does not contain a GC-aligned struct or union, putting
279 GCALIGNED_STRUCT after its closing '}' can help the compiler 279 GCALIGNED_STRUCT after its closing '}' can help the compiler
280 generate better code. 280 generate better code. Also, such structs should be added to the
281 emacs_align_type union.
281 282
282 Although these macros are reasonably portable, they are not 283 Although these macros are reasonably portable, they are not
283 guaranteed on non-GCC platforms, as C11 does not require support 284 guaranteed on non-GCC platforms, as C11 does not require support
@@ -5059,6 +5060,46 @@ maybe_gc (void)
5059 maybe_garbage_collect (); 5060 maybe_garbage_collect ();
5060} 5061}
5061 5062
5063/* A type with alignment at least as large as any object that Emacs
5064 allocates. This is not max_align_t because some platforms (e.g.,
5065 mingw) have buggy malloc implementations that do not align for
5066 max_align_t. This union contains types of all GCALIGNED_STRUCT
5067 components visible here. */
5068union emacs_align_type
5069{
5070 struct Lisp_Bool_Vector Lisp_Bool_Vector;
5071 struct Lisp_Char_Table Lisp_Char_Table;
5072 struct Lisp_CondVar Lisp_CondVar;
5073 struct Lisp_Finalizer Lisp_Finalizer;
5074 struct Lisp_Float Lisp_Float;
5075 struct Lisp_Hash_Table Lisp_Hash_Table;
5076 struct Lisp_Marker Lisp_Marker;
5077 struct Lisp_Misc_Ptr Lisp_Misc_Ptr;
5078 struct Lisp_Mutex Lisp_Mutex;
5079 struct Lisp_Overlay Lisp_Overlay;
5080 struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
5081 struct Lisp_Subr Lisp_Subr;
5082 struct Lisp_User_Ptr Lisp_User_Ptr;
5083 struct Lisp_Vector Lisp_Vector;
5084 struct thread_state thread_state;
5085
5086 /* Omit the following since they would require including bignum.h,
5087 frame.h etc., and in practice their alignments never exceed that
5088 of the structs already listed. */
5089#if 0
5090 struct frame frame;
5091 struct Lisp_Bignum Lisp_Bignum;
5092 struct Lisp_Module_Function Lisp_Module_Function;
5093 struct Lisp_Process Lisp_Process;
5094 struct save_window_data save_window_data;
5095 struct scroll_bar scroll_bar;
5096 struct terminal terminal;
5097 struct window window;
5098 struct xwidget xwidget;
5099 struct xwidget_view xwidget_view;
5100#endif
5101};
5102
5062INLINE_HEADER_END 5103INLINE_HEADER_END
5063 5104
5064#endif /* EMACS_LISP_H */ 5105#endif /* EMACS_LISP_H */
diff --git a/src/thread.c b/src/thread.c
index df1a7053826..b638dd77f8b 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -717,12 +717,17 @@ run_thread (void *state)
717{ 717{
718 /* Make sure stack_top and m_stack_bottom are properly aligned as GC 718 /* Make sure stack_top and m_stack_bottom are properly aligned as GC
719 expects. */ 719 expects. */
720 max_align_t stack_pos; 720 union
721 {
722 Lisp_Object o;
723 void *p;
724 char c;
725 } stack_pos;
721 726
722 struct thread_state *self = state; 727 struct thread_state *self = state;
723 struct thread_state **iter; 728 struct thread_state **iter;
724 729
725 self->m_stack_bottom = self->stack_top = (char *) &stack_pos; 730 self->m_stack_bottom = self->stack_top = &stack_pos.c;
726 self->thread_id = sys_thread_self (); 731 self->thread_id = sys_thread_self ();
727 732
728 if (self->thread_name) 733 if (self->thread_name)