mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-05 22:20:24 -08:00
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.
This commit is contained in:
parent
3930d12e4d
commit
1b2b433fc0
3 changed files with 60 additions and 11 deletions
|
|
@ -3425,6 +3425,12 @@ if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then
|
||||||
done])
|
done])
|
||||||
if test "$emacs_cv_pthread_lib" != no; then
|
if test "$emacs_cv_pthread_lib" != no; then
|
||||||
AC_DEFINE([HAVE_PTHREAD], [1], [Define to 1 if you have POSIX threads.])
|
AC_DEFINE([HAVE_PTHREAD], [1], [Define to 1 if you have POSIX threads.])
|
||||||
|
m4_foreach([emacs_type],
|
||||||
|
[[max_align_t], [pthread_cond_t], [pthread_mutex_t]],
|
||||||
|
[AC_CHECK_ALIGNOF(emacs_type,
|
||||||
|
[[#include <stddef.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
]])])
|
||||||
case $emacs_cv_pthread_lib in
|
case $emacs_cv_pthread_lib in
|
||||||
-*) LIB_PTHREAD=$emacs_cv_pthread_lib;;
|
-*) LIB_PTHREAD=$emacs_cv_pthread_lib;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,9 @@ sys_thread_yield (void)
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_mutex_init (sys_mutex_t *mutex)
|
sys_mutex_init (sys_mutex_t *sys_mutex)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
|
||||||
pthread_mutexattr_t *attr_ptr;
|
pthread_mutexattr_t *attr_ptr;
|
||||||
#ifdef ENABLE_CHECKING
|
#ifdef ENABLE_CHECKING
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
|
|
@ -135,22 +136,25 @@ sys_mutex_init (sys_mutex_t *mutex)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_mutex_lock (sys_mutex_t *mutex)
|
sys_mutex_lock (sys_mutex_t *sys_mutex)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
|
||||||
int error = pthread_mutex_lock (mutex);
|
int error = pthread_mutex_lock (mutex);
|
||||||
eassert (error == 0);
|
eassert (error == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_mutex_unlock (sys_mutex_t *mutex)
|
sys_mutex_unlock (sys_mutex_t *sys_mutex)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
|
||||||
int error = pthread_mutex_unlock (mutex);
|
int error = pthread_mutex_unlock (mutex);
|
||||||
eassert (error == 0);
|
eassert (error == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_cond_init (sys_cond_t *cond)
|
sys_cond_init (sys_cond_t *sys_cond)
|
||||||
{
|
{
|
||||||
|
pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
|
||||||
int error = pthread_cond_init (cond, NULL);
|
int error = pthread_cond_init (cond, NULL);
|
||||||
/* We could get ENOMEM. Can't do anything except aborting. */
|
/* We could get ENOMEM. Can't do anything except aborting. */
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
|
|
@ -161,22 +165,26 @@ sys_cond_init (sys_cond_t *cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
|
sys_cond_wait (sys_cond_t *sys_cond, sys_mutex_t *sys_mutex)
|
||||||
{
|
{
|
||||||
|
pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
|
||||||
|
pthread_mutex_t *mutex = SYSTHREAD_ALIGN_PTR (pthread_mutex_t, sys_mutex);
|
||||||
int error = pthread_cond_wait (cond, mutex);
|
int error = pthread_cond_wait (cond, mutex);
|
||||||
eassert (error == 0);
|
eassert (error == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_cond_signal (sys_cond_t *cond)
|
sys_cond_signal (sys_cond_t *sys_cond)
|
||||||
{
|
{
|
||||||
|
pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
|
||||||
int error = pthread_cond_signal (cond);
|
int error = pthread_cond_signal (cond);
|
||||||
eassert (error == 0);
|
eassert (error == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_cond_broadcast (sys_cond_t *cond)
|
sys_cond_broadcast (sys_cond_t *sys_cond)
|
||||||
{
|
{
|
||||||
|
pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
|
||||||
int error = pthread_cond_broadcast (cond);
|
int error = pthread_cond_broadcast (cond);
|
||||||
eassert (error == 0);
|
eassert (error == 0);
|
||||||
#ifdef HAVE_NS
|
#ifdef HAVE_NS
|
||||||
|
|
@ -189,8 +197,9 @@ sys_cond_broadcast (sys_cond_t *cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_cond_destroy (sys_cond_t *cond)
|
sys_cond_destroy (sys_cond_t *sys_cond)
|
||||||
{
|
{
|
||||||
|
pthread_cond_t *cond = SYSTHREAD_ALIGN_PTR (pthread_cond_t, sys_cond);
|
||||||
int error = pthread_cond_destroy (cond);
|
int error = pthread_cond_destroy (cond);
|
||||||
eassert (error == 0);
|
eassert (error == 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,45 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
/* A system mutex is just a pthread mutex. This is only used for the
|
/* Deal with platforms like GNU/Linux on 32-bit HPPA, where pthread_mutex_t
|
||||||
GIL. */
|
and pthread_cond_t have alignments stricter than what malloc guarantees.
|
||||||
typedef pthread_mutex_t sys_mutex_t;
|
Unfortunately POSIX allows this curious situation.
|
||||||
|
Do this by allocating possibly-poorly-aligned objects a bit larger
|
||||||
|
than pthread_mutex_t and pthread_cond_t, and then aligning pointers
|
||||||
|
to these objects at runtime. */
|
||||||
|
|
||||||
|
#if (ALIGNOF_PTHREAD_COND_T <= ALIGNOF_MAX_ALIGN_T \
|
||||||
|
&& ALIGNOF_PTHREAD_MUTEX_T <= ALIGNOF_MAX_ALIGN_T)
|
||||||
|
/* The typical case. Align PTR for TYPE *, where PTR is of type TYPE *
|
||||||
|
and is already aligned properly. */
|
||||||
|
# define SYSTHREAD_ALIGN_PTR(type, ptr) (ptr)
|
||||||
|
#else
|
||||||
|
/* An unusual case, e.g., GNU/Linux 32-bit HPPA.
|
||||||
|
Aligning SYSTHREAD_ALIGN_ROOM (TYPE) * up for TYPE * results in a
|
||||||
|
valid pointer. TYPE's alignment must be at least that of int;
|
||||||
|
in practice it is always greater than that of max_align_t. */
|
||||||
|
# define SYSTHREAD_ALIGN_ROOM(type) \
|
||||||
|
union { int i; char room[sizeof (type) + alignof (type) - alignof (int)]; }
|
||||||
|
/* Align PTR up for TYPE *.
|
||||||
|
PTR should be of type SYSTHREAD_ALIGN_ROOM (TYPE) *. */
|
||||||
|
# define SYSTHREAD_ALIGN_PTR(type, ptr) \
|
||||||
|
((type *) ((uintptr_t) ((ptr)->room + (alignof (type) - alignof (int))) \
|
||||||
|
& ~(alignof (type) - alignof (int))))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* A system mutex is just a pthread mutex, possibly with alignment slop.
|
||||||
|
It is used only for the GIL. */
|
||||||
|
#if ALIGNOF_PTHREAD_MUTEX_T <= ALIGNOF_MAX_ALIGN_T
|
||||||
|
typedef pthread_mutex_t sys_mutex_t;
|
||||||
|
#else
|
||||||
|
typedef SYSTHREAD_ALIGN_ROOM (pthread_mutex_t) sys_mutex_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ALIGNOF_PTHREAD_COND_T <= ALIGNOF_MAX_ALIGN_T
|
||||||
typedef pthread_cond_t sys_cond_t;
|
typedef pthread_cond_t sys_cond_t;
|
||||||
|
#else
|
||||||
|
typedef SYSTHREAD_ALIGN_ROOM (pthread_cond_t) sys_cond_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* A system thread. */
|
/* A system thread. */
|
||||||
typedef pthread_t sys_thread_t;
|
typedef pthread_t sys_thread_t;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue