]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): Rewrite asm to use %ebx
authorRoland McGrath <roland@gnu.org>
Fri, 16 Aug 2002 20:16:38 +0000 (20:16 +0000)
committerRoland McGrath <roland@gnu.org>
Fri, 16 Aug 2002 20:16:38 +0000 (20:16 +0000)
optimally conditional on [__PIC__].
(TLS_DO_SET_THREAD_AREA): New macro, implement inline syscall
without touching errno, and use latest modify_ldt-like interface.
(TLS_SETUP_GS_SEGMENT): Use that instead of INLINE_SYSCALL.
* sysdeps/i386/useldt.h (DO_MODIFY_LDT): Set %gs in this macro.
(DO_SET_THREAD_AREA): New macro, uses current syscall interface with
existing %gs value as the segment to set.
(INIT_THREAD_SELF): Rewritten using those.  Use set_thread_area only
under [HAVE_TLS_SUPPORT] so we can rely on the initialization done
by the first thread's early TLS setup.

linuxthreads/ChangeLog
linuxthreads/sysdeps/i386/tls.h
linuxthreads/sysdeps/i386/useldt.h

index cd529e89f6864d047fbb43d97f5ca9e4d638a639..9fa83225e693f86bc242ea89a5cad6130cb15cf1 100644 (file)
@@ -1,3 +1,17 @@
+2002-08-16  Roland McGrath  <roland@redhat.com>
+
+       * sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT): Rewrite asm to use %ebx
+       optimally conditional on [__PIC__].
+       (TLS_DO_SET_THREAD_AREA): New macro, implement inline syscall
+       without touching errno, and use latest modify_ldt-like interface.
+       (TLS_SETUP_GS_SEGMENT): Use that instead of INLINE_SYSCALL.
+       * sysdeps/i386/useldt.h (DO_MODIFY_LDT): Set %gs in this macro.
+       (DO_SET_THREAD_AREA): New macro, uses current syscall interface with
+       existing %gs value as the segment to set.
+       (INIT_THREAD_SELF): Rewritten using those.  Use set_thread_area only
+       under [HAVE_TLS_SUPPORT] so we can rely on the initialization done
+       by the first thread's early TLS setup.
+
 2002-08-15  Roland McGrath  <roland@redhat.com>
 
        * sysdeps/i386/tls.h (TLS_INIT_TP): Use statement expression and
index 3e7e4c3302ccca45c08b77e95be89a087140ecfb..efbaebcd85089031e0b5ad1f6145b196b99fc361 100644 (file)
@@ -88,35 +88,59 @@ typedef struct
 #  define GET_DTV(descr) \
   (((tcbhead_t *) (descr))->dtv)
 
+#  ifdef __PIC__
+#   define TLS_EBX_ARG "r"
+#   define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
+#  else
+#   define TLS_EBX_ARG "b"
+#   define TLS_LOAD_EBX
+#  endif
+
 #  define TLS_DO_MODIFY_LDT(descr, nr)                                       \
 ({                                                                           \
   struct modify_ldt_ldt_s ldt_entry =                                        \
     { nr, (unsigned long int) (descr), sizeof (struct _pthread_descr_struct), \
       1, 0, 0, 0, 0, 1, 0 };                                                 \
   int result;                                                                \
-  asm volatile (                                                             \
-       "pushl %%ebx\n\t"                                                     \
-       "movl $1, %%ebx\n\t"                                                  \
-       "int $0x80\n\t"                                                       \
-       "popl %%ebx"                                                          \
-       : "=a" (result)                                                       \
-       : "0" (__NR_modify_ldt),                                                      \
-         /* The extra argument with the "m" constraint is necessary          \
-           to let the compiler know that we are accessing LDT_ENTRY here.  */\
-         "m" (ldt_entry), "c" (&ldt_entry), "d" (sizeof (ldt_entry)));       \
+  asm volatile (TLS_LOAD_EBX                                                 \
+               "int $0x80\n\t"                                               \
+               TLS_LOAD_EBX                                                  \
+               : "=a" (result)                                               \
+               : "0" (__NR_modify_ldt),                                      \
+               /* The extra argument with the "m" constraint is necessary    \
+                  to let the compiler know that we are accessing LDT_ENTRY   \
+                  here.  */                                                  \
+               "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry),           \
+               "d" (sizeof (ldt_entry)));                                    \
   __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7;                       \
 })
 
+#  define TLS_DO_SET_THREAD_AREA(descr)                                              \
+({                                                                           \
+  struct modify_ldt_ldt_s ldt_entry =                                        \
+    { -1, (unsigned long int) (descr), sizeof (struct _pthread_descr_struct), \
+      1, 0, 0, 0, 0, 1, 0 };                                                 \
+  int result;                                                                \
+  asm volatile (TLS_LOAD_EBX                                                 \
+               "int $0x80\n\t"                                               \
+               TLS_LOAD_EBX                                                  \
+               : "=a" (result), "=m" (ldt_entry.entry_number)                \
+               : "0" (__NR_set_thread_area),                                 \
+               /* The extra argument with the "m" constraint is necessary    \
+                  to let the compiler know that we are accessing LDT_ENTRY   \
+                  here.  */                                                  \
+               TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry));                   \
+    __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number : -1;         \
+})
+
 #  ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
-#   define TLS_SETUP_GS_SEGMENT(descr) \
-  INLINE_SYSCALL (set_thread_area, 2, descr, 1)
+#   define TLS_SETUP_GS_SEGMENT(descr) TLS_DO_SET_THREAD_AREA (descr)
 #  elif defined __NR_set_thread_area
 #   define TLS_SETUP_GS_SEGMENT(descr) \
-  ({ int __seg = INLINE_SYSCALL (set_thread_area, 2, descr, 1); \
+  ({ int __seg = TLS_DO_SET_THREAD_AREA (descr); \
      __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; })
 #  else
-#   define TLS_SETUP_GS_SEGMENT(descr) \
-  TLS_DO_MODIFY_LDT (descr, 0)
+#   define TLS_SETUP_GS_SEGMENT(descr) TLS_DO_MODIFY_LDT ((descr), 0)
 #  endif
 
 /* Code to initially initialize the thread pointer.  This might need
index 4fd226e2707236acbac83a10a53560a959aa92f7..49471d61fa8d08c8239c66f832fa52d2c2ee8594 100644 (file)
@@ -62,49 +62,48 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
   __self;                                                                    \
 })
 
-#define DO_MODIFY_LDT(descr, nr) \
+
+/* Initialize the thread-unique value.  Two possible ways to do it.  */
+
+#define DO_MODIFY_LDT(descr, nr)                                             \
 ({                                                                           \
   struct modify_ldt_ldt_s ldt_entry =                                        \
     { nr, (unsigned long int) descr, sizeof (struct _pthread_descr_struct),   \
       1, 0, 0, 0, 0, 1, 0 };                                                 \
   if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)                 \
     abort ();                                                                \
-  nr * 8 + 7;                                                                \
+  asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7));                               \
 })
 
-/* Initialize the thread-unique value.  */
-#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
-#define INIT_THREAD_SELF(descr, nr) \
-{                                                                            \
-  int __gs = INLINE_SYSCALL (set_thread_area, 2, descr, 1);                  \
-  if (__gs == -1)                                                            \
-    abort ();                                                                \
-  __asm__ __volatile__ ("movw %w0, %%gs" : : "q" (__gs));                    \
-}
-#elif defined __NR_set_thread_area
+/* When using the new set_thread_area call, we don't need to change %gs
+   because we inherited the value set up in the main thread by TLS setup.
+   We need to extract that value and set up the same segment in this
+   thread.  */
+# define DO_SET_THREAD_AREA(descr)                                           \
+({                                                                           \
+  int __gs;                                                                  \
+  struct modify_ldt_ldt_s ldt_entry =                                        \
+    { ({ asm ("movw %%gs, %w0" : "=q" (__gs)); __gs >> 2; }),                \
+      (unsigned long int) descr, sizeof (struct _pthread_descr_struct),              \
+      1, 0, 0, 0, 0, 1, 0 };                                                 \
+  __builtin_expect (INLINE_SYSCALL (set_thread_area, 1, &ldt_entry) == 0, 1)  \
+  ? __gs : -1;                                                               \
+})
 
+#if defined __ASSUME_SET_THREAD_AREA_SYSCALL && defined HAVE_TLS_SUPPORT
+# define INIT_THREAD_SELF(descr, nr)   DO_SET_THREAD_AREA (descr)
+#elif defined __NR_set_thread_area && defined HAVE_TLS_SUPPORT
+# define INIT_THREAD_SELF(descr, nr)                                         \
+({                                                                           \
+  if (__builtin_expect (__have_no_set_thread_area, 0)                        \
+      || (DO_SET_THREAD_AREA (descr) == -1                                   \
+         && (__have_no_set_thread_area = 1)))                                \
+    DO_MODIFY_LDT (descr, nr);                                               \
+})
 /* Defined in pspinlock.c.  */
 extern int __have_no_set_thread_area;
-
-#define INIT_THREAD_SELF(descr, nr) \
-{                                                                            \
-  int __gs = -1;                                                             \
-  if (! __builtin_expect (__have_no_set_thread_area, 0))                     \
-    {                                                                        \
-      if ((__gs = INLINE_SYSCALL (set_thread_area, 2, descr, 1)) == -1       \
-         && errno == ENOSYS)                                                 \
-       __have_no_set_thread_area = 1;                                        \
-    }                                                                        \
-  if (__builtin_expect (__gs == -1, 0))                                              \
-    __gs = DO_MODIFY_LDT (descr, nr);                                        \
-  __asm__ __volatile__ ("movw %w0, %%gs" : : "q" (__gs));                    \
-}
 #else
-#define INIT_THREAD_SELF(descr, nr) \
-{                                                                            \
-  int __gs = DO_MODIFY_LDT (descr, nr);                                              \
-  __asm__ __volatile__ ("movw %w0, %%gs" : : "q" (__gs));                    \
-}
+# define INIT_THREAD_SELF(descr, nr)   DO_MODIFY_LDT (descr, nr)
 #endif
 
 /* Free resources associated with thread descriptor.  */