aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2025-12-02 17:24:43 -0800
committerPaul Eggert2025-12-02 17:46:56 -0800
commit1b2b433fc0a62db933399eb37c8cae73e0446e86 (patch)
treed9e0b677729ef3dc32ae7be55889df75e982af37 /src
parent3930d12e4dcb2d79d70c3aa8a199aec0340d0b39 (diff)
downloademacs-1b2b433fc0a62db933399eb37c8cae73e0446e86.tar.gz
emacs-1b2b433fc0a62db933399eb37c8cae73e0446e86.zip
Port to GNU/Linux HPPA malloc
On this platform, you cannot reliably malloc objects containing values of type pthread_mutex_t or pthread_cond_t, since malloc guarantees only 8-byte alignment but these two types require 16-byte alignment. See GCC bug 115750 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115750> reported by Sam James and Emacs bug 79936 <https://bugs.gnu.org/79936> reported by John Paul Adrian Glaubitz. * configure.ac (ALIGNOF_MAX_ALIGN_T, ALIGNOF_PTHREAD_COND_T) (ALIGNOF_PTHREAD_MUTEX_T) [HAVE_PTHREAD]: New C macros. * src/systhread.c (sys_mutex_init, sys_mutex_lock) (sys_mutex_unlock, sys_cond_init, sys_cond_wait) (sys_cond_signal, sys_cond_broadcast, sys_cond_destroy): Use SYTHREAD_ALIGN_PTR to convert sys_mutex_t and sys_cond_t to pthread_mutex_t and pthread_cond_t, since runtime conversion is needed on GNU/Linux HPPA. * src/systhread.h (SYSTHREAD_ALIGN_ROOM, SYSTHREAD_ALIGN_PTR): New macros, which affect the generated code only on unusual platforms like GNU/Linux HPPA. (sys_mutex_t, sys_cond_t) [HAVE_PTHREAD]: Use them.
Diffstat (limited to 'src')
-rw-r--r--src/systhread.c25
-rw-r--r--src/systhread.h38
2 files changed, 53 insertions, 10 deletions
diff --git a/src/systhread.c b/src/systhread.c
index a14a4929d57..5cde785630d 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -106,8 +106,9 @@ sys_thread_yield (void)
106#include <sched.h> 106#include <sched.h>
107 107
108void 108void
109sys_mutex_init (sys_mutex_t *mutex) 109sys_mutex_init (sys_mutex_t *sys_mutex)
110{ 110{
111 pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
111 pthread_mutexattr_t *attr_ptr; 112 pthread_mutexattr_t *attr_ptr;
112#ifdef ENABLE_CHECKING 113#ifdef ENABLE_CHECKING
113 pthread_mutexattr_t attr; 114 pthread_mutexattr_t attr;
@@ -135,22 +136,25 @@ sys_mutex_init (sys_mutex_t *mutex)
135} 136}
136 137
137void 138void
138sys_mutex_lock (sys_mutex_t *mutex) 139sys_mutex_lock (sys_mutex_t *sys_mutex)
139{ 140{
141 pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
140 int error = pthread_mutex_lock (mutex); 142 int error = pthread_mutex_lock (mutex);
141 eassert (error == 0); 143 eassert (error == 0);
142} 144}
143 145
144void 146void
145sys_mutex_unlock (sys_mutex_t *mutex) 147sys_mutex_unlock (sys_mutex_t *sys_mutex)
146{ 148{
149 pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
147 int error = pthread_mutex_unlock (mutex); 150 int error = pthread_mutex_unlock (mutex);
148 eassert (error == 0); 151 eassert (error == 0);
149} 152}
150 153
151void 154void
152sys_cond_init (sys_cond_t *cond) 155sys_cond_init (sys_cond_t *sys_cond)
153{ 156{
157 pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
154 int error = pthread_cond_init (cond, NULL); 158 int error = pthread_cond_init (cond, NULL);
155 /* We could get ENOMEM. Can't do anything except aborting. */ 159 /* We could get ENOMEM. Can't do anything except aborting. */
156 if (error != 0) 160 if (error != 0)
@@ -161,22 +165,26 @@ sys_cond_init (sys_cond_t *cond)
161} 165}
162 166
163void 167void
164sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex) 168sys_cond_wait (sys_cond_t *sys_cond, sys_mutex_t *sys_mutex)
165{ 169{
170 pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
171 pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
166 int error = pthread_cond_wait (cond, mutex); 172 int error = pthread_cond_wait (cond, mutex);
167 eassert (error == 0); 173 eassert (error == 0);
168} 174}
169 175
170void 176void
171sys_cond_signal (sys_cond_t *cond) 177sys_cond_signal (sys_cond_t *sys_cond)
172{ 178{
179 pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
173 int error = pthread_cond_signal (cond); 180 int error = pthread_cond_signal (cond);
174 eassert (error == 0); 181 eassert (error == 0);
175} 182}
176 183
177void 184void
178sys_cond_broadcast (sys_cond_t *cond) 185sys_cond_broadcast (sys_cond_t *sys_cond)
179{ 186{
187 pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
180 int error = pthread_cond_broadcast (cond); 188 int error = pthread_cond_broadcast (cond);
181 eassert (error == 0); 189 eassert (error == 0);
182#ifdef HAVE_NS 190#ifdef HAVE_NS
@@ -189,8 +197,9 @@ sys_cond_broadcast (sys_cond_t *cond)
189} 197}
190 198
191void 199void
192sys_cond_destroy (sys_cond_t *cond) 200sys_cond_destroy (sys_cond_t *sys_cond)
193{ 201{
202 pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
194 int error = pthread_cond_destroy (cond); 203 int error = pthread_cond_destroy (cond);
195 eassert (error == 0); 204 eassert (error == 0);
196} 205}
diff --git a/src/systhread.h b/src/systhread.h
index a321514d2bc..30fa5a94b45 100644
--- a/src/systhread.h
+++ b/src/systhread.h
@@ -27,11 +27,45 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
27 27
28#include <pthread.h> 28#include <pthread.h>
29 29
30/* A system mutex is just a pthread mutex. This is only used for the 30/* Deal with platforms like GNU/Linux on 32-bit HPPA, where pthread_mutex_t
31 GIL. */ 31 and pthread_cond_t have alignments stricter than what malloc guarantees.
32 Unfortunately POSIX allows this curious situation.
33 Do this by allocating possibly-poorly-aligned objects a bit larger
34 than pthread_mutex_t and pthread_cond_t, and then aligning pointers
35 to these objects at runtime. */
36
37#if (ALIGNOF_PTHREAD_COND_T <= ALIGNOF_MAX_ALIGN_T \
38 && ALIGNOF_PTHREAD_MUTEX_T <= ALIGNOF_MAX_ALIGN_T)
39/* The typical case. Align PTR for TYPE *, where PTR is of type TYPE *
40 and is already aligned properly. */
41# define SYSTHREAD_ALIGN_PTR(type, ptr) (ptr)
42#else
43/* An unusual case, e.g., GNU/Linux 32-bit HPPA.
44 Aligning SYSTHREAD_ALIGN_ROOM (TYPE) * up for TYPE * results in a
45 valid pointer. TYPE's alignment must be at least that of int;
46 in practice it is always greater than that of max_align_t. */
47# define SYSTHREAD_ALIGN_ROOM(type) \
48 union { int i; char room[sizeof (type) + alignof (type) - alignof (int)]; }
49/* Align PTR up for TYPE *.
50 PTR should be of type SYSTHREAD_ALIGN_ROOM (TYPE) *. */
51# define SYSTHREAD_ALIGN_PTR(type, ptr) \
52 ((type *) ((uintptr_t) ((ptr)->room + (alignof (type) - alignof (int))) \
53 & ~(alignof (type) - alignof (int))))
54#endif
55
56/* A system mutex is just a pthread mutex, possibly with alignment slop.
57 It is used only for the GIL. */
58#if ALIGNOF_PTHREAD_MUTEX_T <= ALIGNOF_MAX_ALIGN_T
32typedef pthread_mutex_t sys_mutex_t; 59typedef pthread_mutex_t sys_mutex_t;
60#else
61typedef SYSTHREAD_ALIGN_ROOM (pthread_mutex_t) sys_mutex_t;
62#endif
33 63
64#if ALIGNOF_PTHREAD_COND_T <= ALIGNOF_MAX_ALIGN_T
34typedef pthread_cond_t sys_cond_t; 65typedef pthread_cond_t sys_cond_t;
66#else
67typedef SYSTHREAD_ALIGN_ROOM (pthread_cond_t) sys_cond_t;
68#endif
35 69
36/* A system thread. */ 70/* A system thread. */
37typedef pthread_t sys_thread_t; 71typedef pthread_t sys_thread_t;