This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: [PATCH] PPC linuxthreads tls.h fix
- From: Roland McGrath <roland at redhat dot com>
- To: Paul Mackerras <paulus at au1 dot ibm dot com>
- Cc: sjmunroe at vnet dot ibm dot com,libc-alpha <libc-alpha at sources dot redhat dot com>,Alan Modra <amodra at bigpond dot net dot au>
- Date: Thu, 27 Feb 2003 21:49:41 -0800
- Subject: Re: [PATCH] PPC linuxthreads tls.h fix
> I couldn't get linuxthreads/sysdeps/powerpc/tcb-offsets.sym to
> generate offsets relating to the _pthread_descr_struct.
Please try the follow patch against the current glibc cvs. I am not
putting this in yet because it touches generic code and other platforms
(there are a few more diffs not included here). It's only relevant to
TLS, and we might want to release 2.3.2 now without perturbing it more.
--without-tls will still be the default for 2.3.2, and it seems reasonable
to release it as is now and say that TLS only really works on x86/x86_64 yet.
Thanks,
Roland
Index: linuxthreads/descr.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/descr.h,v
retrieving revision 1.8
diff -p -u -r1.8 descr.h
--- linuxthreads/descr.h 28 Dec 2002 10:14:16 -0000 1.8
+++ linuxthreads/descr.h 28 Feb 2003 05:45:07 -0000
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <hp-timing.h>
+#include <tls.h>
/* Fast thread-specific data internal to libc. */
enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
@@ -106,11 +107,14 @@ typedef struct _pthread_rwlock_info {
union dtv;
-
-struct _pthread_descr_struct {
- /* XXX Remove this union for IA-64 style TLS module */
- union {
- struct {
+struct _pthread_descr_struct
+{
+#if !defined USE_TLS || !TLS_DTV_AT_TP
+ /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads. */
+ union
+ {
+ struct
+ {
void *tcb; /* Pointer to the TCB. This is not always
the address of this thread descriptor. */
union dtv *dtvp;
@@ -122,6 +126,11 @@ struct _pthread_descr_struct {
} data;
void *__padding[16];
} p_header;
+# define p_multiple_threads p_header.data.multiple_threads
+#elif TLS_MULTIPLE_THREADS_IN_TCB
+ int p_multiple_threads;
+#endif
+
pthread_descr p_nextlive, p_prevlive;
/* Double chaining of active threads */
pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */
Index: linuxthreads/manager.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/manager.c,v
retrieving revision 1.90
diff -p -u -r1.90 manager.c
--- linuxthreads/manager.c 12 Jan 2003 08:42:38 -0000 1.90
+++ linuxthreads/manager.c 28 Feb 2003 05:45:07 -0000
@@ -638,13 +638,13 @@ static int pthread_handle_create(pthread
new_thread_id = sseg + pthread_threads_counter;
/* Initialize the thread descriptor. Elements which have to be
initialized to zero already have this value. */
-#if defined USE_TLS && TLS_DTV_AT_TP
- new_thread->p_header.data.tcb = new_thread + 1;
-#else
+#if !defined USE_TLS || !TLS_DTV_AT_TP
new_thread->p_header.data.tcb = new_thread;
-#endif
new_thread->p_header.data.self = new_thread;
- new_thread->p_header.data.multiple_threads = 1;
+#endif
+#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP
+ new_thread->p_multiple_threads = 1;
+#endif
new_thread->p_tid = new_thread_id;
new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
Index: linuxthreads/pthread.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/pthread.c,v
retrieving revision 1.119
diff -p -u -r1.119 pthread.c
--- linuxthreads/pthread.c 16 Jan 2003 18:16:32 -0000 1.119
+++ linuxthreads/pthread.c 28 Feb 2003 05:45:08 -0000
@@ -566,8 +566,10 @@ int __pthread_initialize_manager(void)
#endif
__pthread_multiple_threads = 1;
- __pthread_main_thread->p_header.data.multiple_threads = 1;
- * __libc_multiple_threads_ptr = 1;
+#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP
+ __pthread_main_thread->p_multiple_threads = 1;
+#endif
+ *__libc_multiple_threads_ptr = 1;
#ifndef HAVE_Z_NODELETE
if (__builtin_expect (&__dso_handle != NULL, 1))
@@ -611,9 +613,13 @@ int __pthread_initialize_manager(void)
__pthread_handles[1].h_descr = manager_thread = mgr;
/* Initialize the descriptor. */
+#if !defined USE_TLS || !TLS_DTV_AT_TP
mgr->p_header.data.tcb = tcbp;
mgr->p_header.data.self = mgr;
mgr->p_header.data.multiple_threads = 1;
+#elif TLS_MULTIPLE_THREADS_IN_TCB
+ mgr->p_multiple_threads = 1;
+#endif
mgr->p_lock = &__pthread_handles[1].h_lock;
# ifndef HAVE___THREAD
mgr->p_errnop = &mgr->p_errno;
Index: linuxthreads/sysdeps/powerpc/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/powerpc/tcb-offsets.sym,v
retrieving revision 1.1
diff -p -u -r1.1 tcb-offsets.sym
--- linuxthreads/sysdeps/powerpc/tcb-offsets.sym 17 Feb 2003 20:37:35 -0000 1.1
+++ linuxthreads/sysdeps/powerpc/tcb-offsets.sym 28 Feb 2003 05:45:09 -0000
@@ -1,4 +1,24 @@
#include <sysdep.h>
#include <tls.h>
-MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
+--
+
+-- This could go into powerpc32/ instead and conditionalize #include of it.
+#ifndef __powerpc64__
+
+# ifdef USE_TLS
+
+/* Abuse tls.h macros to derive offsets relative to the thread register. */
+# undef __thread_register
+# define __thread_register ((void *) 0)
+# define thread_offsetof(mem) ((void *) &THREAD_SELF->p_##mem - (void *) 0)
+
+# else
+
+# define thread_offsetof(mem) offsetof (tcbhead_t, mem)
+
+# endif
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (multiple_threads)
+
+#endif
Index: linuxthreads/sysdeps/powerpc/tls.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/powerpc/tls.h,v
retrieving revision 1.2
diff -p -u -r1.2 tls.h
--- linuxthreads/sysdeps/powerpc/tls.h 27 Feb 2003 20:47:12 -0000 1.2
+++ linuxthreads/sysdeps/powerpc/tls.h 28 Feb 2003 05:45:09 -0000
@@ -32,15 +32,6 @@ typedef union dtv
void *pointer;
} dtv_t;
-typedef struct
-{
- void *tcb; /* Pointer to the TCB. Not necessary the
- thread descriptor used by libpthread. */
- dtv_t *dtv;
- void *self; /* Pointer to the thread descriptor. */
- int multiple_threads;
-} tcbhead_t;
-
#else /* __ASSEMBLER__ */
# include <tcb-offsets.h>
#endif /* __ASSEMBLER__ */
@@ -52,6 +43,14 @@ typedef struct
# ifndef __ASSEMBLER__
+/* This layout is actually wholly private and not affected by the ABI.
+ Nor does it overlap the pthread data structure, so we need nothing
+ extra here at all. */
+typedef struct
+{
+ dtv_t *dtv;
+} tcbhead_t;
+
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
@@ -132,14 +131,33 @@ typedef struct
#define THREAD_SETMEM_NC(descr, member, value) \
THREAD_SETMEM ((descr), member, (value))
+/* Make sure we have the p_multiple_threads member in the thread structure.
+ See below. */
+# ifndef __powerpc64__
+# define TLS_MULTIPLE_THREADS_IN_TCB 1
+# endif
+
# endif /* __ASSEMBLER__ */
-#else /* Not HAVE_TLS_SUPPORT. */
+#elif !defined __ASSEMBLER__ && !defined __powerpc64__
+
+/* This overlaps the start of the pthread_descr. On PPC32, system
+ calls and such use this to find the multiple_threads flag and need
+ to use the same offset relative to the thread register in both
+ single-threaded and multi-threaded code. On PPC64, the global
+ variable is always used, so single-threaded code without TLS
+ never needs to initialize the thread register at all. */
+typedef struct
+{
+ void *tcb; /* Never used. */
+ dtv_t *dtv; /* Never used. */
+ void *self; /* Used only if multithreaded, and rarely. */
+ int multiple_threads; /* Only this member is really used. */
+} tcbhead_t;
#define NONTLS_INIT_TP \
do { \
- static const tcbhead_t nontls_init_tp \
- = { .multiple_threads = 0 }; \
+ static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \
__thread_self = (__typeof (__thread_self)) &nontls_init_tp; \
} while (0)