diff options
| author | Paul Eggert | 2025-12-02 17:24:43 -0800 |
|---|---|---|
| committer | Paul Eggert | 2025-12-02 17:46:56 -0800 |
| commit | 1b2b433fc0a62db933399eb37c8cae73e0446e86 (patch) | |
| tree | d9e0b677729ef3dc32ae7be55889df75e982af37 /src | |
| parent | 3930d12e4dcb2d79d70c3aa8a199aec0340d0b39 (diff) | |
| download | emacs-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.c | 25 | ||||
| -rw-r--r-- | src/systhread.h | 38 |
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 | ||
| 108 | void | 108 | void |
| 109 | sys_mutex_init (sys_mutex_t *mutex) | 109 | sys_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 | ||
| 137 | void | 138 | void |
| 138 | sys_mutex_lock (sys_mutex_t *mutex) | 139 | sys_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 | ||
| 144 | void | 146 | void |
| 145 | sys_mutex_unlock (sys_mutex_t *mutex) | 147 | sys_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 | ||
| 151 | void | 154 | void |
| 152 | sys_cond_init (sys_cond_t *cond) | 155 | sys_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 | ||
| 163 | void | 167 | void |
| 164 | sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex) | 168 | sys_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 | ||
| 170 | void | 176 | void |
| 171 | sys_cond_signal (sys_cond_t *cond) | 177 | sys_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 | ||
| 177 | void | 184 | void |
| 178 | sys_cond_broadcast (sys_cond_t *cond) | 185 | sys_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 | ||
| 191 | void | 199 | void |
| 192 | sys_cond_destroy (sys_cond_t *cond) | 200 | sys_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 | ||
| 32 | typedef pthread_mutex_t sys_mutex_t; | 59 | typedef pthread_mutex_t sys_mutex_t; |
| 60 | #else | ||
| 61 | typedef SYSTHREAD_ALIGN_ROOM (pthread_mutex_t) sys_mutex_t; | ||
| 62 | #endif | ||
| 33 | 63 | ||
| 64 | #if ALIGNOF_PTHREAD_COND_T <= ALIGNOF_MAX_ALIGN_T | ||
| 34 | typedef pthread_cond_t sys_cond_t; | 65 | typedef pthread_cond_t sys_cond_t; |
| 66 | #else | ||
| 67 | typedef SYSTHREAD_ALIGN_ROOM (pthread_cond_t) sys_cond_t; | ||
| 68 | #endif | ||
| 35 | 69 | ||
| 36 | /* A system thread. */ | 70 | /* A system thread. */ |
| 37 | typedef pthread_t sys_thread_t; | 71 | typedef pthread_t sys_thread_t; |