about summary refs log tree commit diff
path: root/linuxthreads/sysdeps/sh/tls.h
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads/sysdeps/sh/tls.h')
-rw-r--r--linuxthreads/sysdeps/sh/tls.h123
1 files changed, 71 insertions, 52 deletions
diff --git a/linuxthreads/sysdeps/sh/tls.h b/linuxthreads/sysdeps/sh/tls.h
index de79aaed0a..af67a8eded 100644
--- a/linuxthreads/sysdeps/sh/tls.h
+++ b/linuxthreads/sysdeps/sh/tls.h
@@ -34,15 +34,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__ */
@@ -55,73 +46,101 @@ typedef struct
 /* Signal that TLS support is available.  */
 # define USE_TLS	1
 
-#ifndef __ASSEMBLER__
-
-/* Get system call information.  */
-# include <sysdep.h>
+# ifndef __ASSEMBLER__
 
-/* Get the thread descriptor definition.  */
-# include <linuxthreads/descr.h>
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
 
 /* This is the size of the initial TCB.  */
-# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+#  define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
 
 /* Alignment requirements for the initial TCB.  */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+#  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
 
 /* This is the size of the TCB.  */
-# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
+#  define TLS_TCB_SIZE sizeof (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
 
 /* Alignment requirements for the TCB.  */
-# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
 
 /* The TLS blocks start right after the TCB.  */
-# define TLS_DTV_AT_TP	1
-
+#  define TLS_DTV_AT_TP	1
 
 /* Install the dtv pointer.  The pointer passed is to the element with
    index -1 which contain the length.  */
-# define INSTALL_DTV(descr, dtvp) \
-  ((tcbhead_t *) (descr))->dtv = dtvp + 1
+#  define INSTALL_DTV(tcbp, dtvp) \
+  ((tcbhead_t *) (tcbp))->dtv = dtvp + 1
 
 /* Install new dtv for current thread.  */
-# define INSTALL_NEW_DTV(dtv) \
-  ({ struct _pthread_descr_struct *__descr;				      \
-     THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
+#  define INSTALL_NEW_DTV(dtv) \
+  ({ tcbhead_t *__tcbp;							      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));			      \
+     __tcbp->dtv = (dtv);})
 
 /* Return dtv of given thread descriptor.  */
-# define GET_DTV(descr) \
-  (((tcbhead_t *) (descr))->dtv)
+#  define GET_DTV(tcbp) \
+  (((tcbhead_t *) (tcbp))->dtv)
 
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-# define TLS_INIT_TP(descr, secondcall) \
-  ({									      \
-    void *_descr = (descr);						      \
-    int result;								      \
-    tcbhead_t *head = _descr;						      \
-									      \
-    head->tcb = _descr;							      \
-    /* For now the thread descriptor is at the same address.  */	      \
-    head->self = _descr;						      \
-									      \
-    asm ("ldc %0,gbr" : : "r" (_descr));				      \
-									      \
-    0;									      \
-  })
-
-/* Indicate that dynamic linker shouldn't try to initialize TLS even
-   when no PT_TLS segments are found in the program and libraries
-   it is linked against.  */
-#  define TLS_INIT_TP_EXPENSIVE 1
+#  define TLS_INIT_TP(tcbp, secondcall) \
+  ({ __asm __volatile ("ldc %0,gbr" : : "r" (tcbp)); 0; })
 
 /* Return the address of the dtv for the current thread.  */
-# define THREAD_DTV() \
-  ({ struct _pthread_descr_struct *__descr;				      \
-     THREAD_GETMEM (__descr, p_header.data.dtvp); })
+#  define THREAD_DTV() \
+  ({ tcbhead_t *__tcbp;							      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));			      \
+     __tcbp->dtv;})
 
-# endif	/* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
-#endif /* __ASSEMBLER__ */
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF \
+  ({ struct _pthread_descr_struct *__self;				      \
+     __asm ("stc gbr,%0" : "=r" (__self));				      \
+     __self - 1;})
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(descr, nr) \
+  ({ struct _pthread_descr_struct *__self = (void *) descr;		      \
+     __asm __volatile ("ldc %0,gbr" : : "r" (__self + 1));		      \
+     0; })
+
+/* Get the thread descriptor definition.  This must be after the
+   the definition of THREAD_SELF for TLS.  */
+#  include <linuxthreads/descr.h>
+
+# endif /* __ASSEMBLER__ */
+
+#else
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  void *tcb;
+  dtv_t *dtv;
+  void *self;
+  int multiple_threads;
+} tcbhead_t;
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+#  define NONTLS_INIT_TP \
+  do { 									\
+    static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 };	\
+    __asm __volatile ("ldc %0,gbr" : : "r" (&nontls_init_tp));	        \
+  } while (0)
+
+# endif /* __ASSEMBLER__ */
+
+#endif	/* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
 
 #endif	/* tls.h */