]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Arch-abstraction:
authorNicholas Nethercote <n.nethercote@gmail.com>
Tue, 19 Oct 2004 13:18:00 +0000 (13:18 +0000)
committerNicholas Nethercote <n.nethercote@gmail.com>
Tue, 19 Oct 2004 13:18:00 +0000 (13:18 +0000)
- Factored out the remaining arch-specific code from vg_libpthread.c.
- Also fixed up the build process for x86/libpthread.c, which was done
  wrongly in the previous commit.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2798

coregrind/Makefile.am
coregrind/core.h
coregrind/vg_libpthread.c
coregrind/x86/Makefile.am
coregrind/x86/core_arch.h
coregrind/x86/libpthread.c

index 56c006f9582c2cb72d101560d67f0119e0bfb244..2d4497b86de38de7d983cdc229073f77a1bf8451 100644 (file)
@@ -116,7 +116,8 @@ vg_toolint.h:  $(srcdir)/gen_toolint.pl $(srcdir)/toolfuncs.def ./Makefile
 libpthread_so_SOURCES = \
        vg_libpthread.c \
        vg_libpthread_unimp.c \
-       vg_syscall.S
+       vg_syscall.S \
+       ${VG_ARCH}/libpthread.c 
 libpthread_so_DEPENDENCIES = $(srcdir)/vg_libpthread.vs
 libpthread_so_LDFLAGS     = -Werror -fno-omit-frame-pointer -UVG_LIBDIR \
        -shared -fpic -ldl \
index a3dc1060eb9a3e1f0f0c8ff3b85e094596c39b3f..68f16cca7610db31150323afe39e72f42a170752 100644 (file)
@@ -1532,6 +1532,28 @@ extern void VGA_(push_signal_frame) ( ThreadId tid, Addr esp_top_of_frame,
                                       const vki_ksigset_t *mask);
 extern Int  VGA_(pop_signal_frame)  ( ThreadId tid );
 
+// libpthread stuff
+typedef struct arch_thread_aux arch_thread_aux_t;
+
+void VGA_(thread_create) ( arch_thread_aux_t *aux );
+void VGA_(thread_wrapper)( arch_thread_aux_t *aux );
+void VGA_(thread_exit)   ( void );
+
+Bool VGA_(has_tls)       ( void );
+
+#define MY__STRING(__str)  #__str
+
+// Assertion to use in code running on the simulated CPU.
+#define my_assert(expr)                                               \
+  ((void) ((expr) ? 0 :                                                      \
+          (VG_(user_assert_fail) (MY__STRING(expr),                  \
+                             __FILE__, __LINE__,                     \
+                              __PRETTY_FUNCTION__), 0)))
+
+extern void VG_(user_assert_fail) ( const Char* expr, const Char* file,
+                                    Int line, const Char* fn );
+
+
 // ---------------------------------------------------------------------
 // Platform-specific things defined in eg. x86/*.c
 // ---------------------------------------------------------------------
index cb017231642b7c9827f056f5d58a94f01b5d5efd..1fa7acf101a78080b44f1d3905090721a9a007a3 100644 (file)
@@ -310,8 +310,7 @@ void vgPlain_unimp ( char* fn )
 }
 
 
-static
-void my_assert_fail ( const Char* expr, const Char* file, Int line, const Char* fn )
+void VG_(user_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
 {
    char buf[1000];
    static Bool entered = False;
@@ -326,14 +325,6 @@ void my_assert_fail ( const Char* expr, const Char* file, Int line, const Char*
    _exit(1);
 }
 
-#define MY__STRING(__str)  #__str
-
-#define my_assert(expr)                                               \
-  ((void) ((expr) ? 0 :                                                      \
-          (my_assert_fail  (MY__STRING(expr),                        \
-                             __FILE__, __LINE__,                     \
-                              __PRETTY_FUNCTION__), 0)))
-
 static
 void my_free ( void* ptr )
 {
@@ -657,44 +648,6 @@ int pthread_getconcurrency(void)
 }
 
 
-
-/* --------------------------------------------------- 
-   Helper functions for running a thread 
-   and for clearing up afterwards.
-   ------------------------------------------------ */
-
-typedef void *(*__attribute__ ((stdcall)) REGPARM(3) allocate_tls_t) (void *result);
-typedef void (*__attribute__ ((stdcall)) REGPARM(3) deallocate_tls_t) (void *tcb, int dealloc_tcb);
-
-static allocate_tls_t allocate_tls = NULL;
-static deallocate_tls_t deallocate_tls = NULL;
-
-static
-int get_gs()
-{
-   int gs;
-
-   asm volatile ("movw %%gs, %w0" : "=q" (gs));
-
-   return gs & 0xffff;
-}
-
-static
-void set_gs( int gs )
-{
-   asm volatile ("movw %w0, %%gs" :: "q" (gs));
-}
-
-static
-void *get_tcb()
-{
-   void *tcb;
-
-   asm volatile ("movl %%gs:0, %0" : "=r" (tcb));
-
-   return tcb;
-}
-
 /* All exiting threads eventually pass through here, bearing the
    return value, or PTHREAD_CANCELED, in ret_val. */
 static
@@ -732,11 +685,7 @@ void thread_exit_wrapper ( void* ret_val )
    if (specifics_ptr != NULL)
       my_free(specifics_ptr);
    
-   /* Free up any TLS data */
-   if ((get_gs() & 7) == 3 && pthread_self() > 1) {
-      my_assert(deallocate_tls != NULL);
-      deallocate_tls(get_tcb(), 1);
-   }
+   VGA_(thread_exit)();
    
    /* Decide on my final disposition. */
    VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
@@ -769,12 +718,10 @@ void thread_exit_wrapper ( void* ret_val )
 typedef
    struct {
       int           attr__detachstate;
-      void*         tls_data;
-      int           tls_segment;
-      unsigned long sysinfo;
       void*         (*root_fn) ( void* );
       void*         arg;
       sigset_t     sigmask;
+      arch_thread_aux_t aux;
    }
    NewThreadInfo;
 
@@ -797,49 +744,16 @@ __attribute__((noreturn))
 void thread_wrapper ( NewThreadInfo* info )
 {
    int                    attr__detachstate;
-   void*                  tls_data;
-   int                    tls_segment;
-   unsigned long          sysinfo;
    void*                  (*root_fn) ( void* );
    void*                  arg;
    void*                  ret_val;
    __pthread_unwind_buf_t ub;
 
    attr__detachstate = info->attr__detachstate;
-   tls_data          = info->tls_data;
-   tls_segment       = info->tls_segment;
-   sysinfo           = info->sysinfo;
    root_fn           = info->root_fn;
    arg               = info->arg;
 
-   if (tls_data) {
-      tcbhead_t *tcb = tls_data;
-      struct vki_modify_ldt_ldt_s ldt_info;
-
-      /* Fill in the TCB header */
-      tcb->tcb = tcb;
-      tcb->self = tcb;
-      tcb->multiple_threads = 1;
-      tcb->sysinfo = sysinfo;
-      
-      /* Fill in an LDT descriptor */
-      ldt_info.entry_number = tls_segment;
-      ldt_info.base_addr = (unsigned long)tls_data;
-      ldt_info.limit = 0xfffff;
-      ldt_info.seg_32bit = 1;
-      ldt_info.contents = 0;
-      ldt_info.read_exec_only = 0;
-      ldt_info.limit_in_pages = 1;
-      ldt_info.seg_not_present = 0;
-      ldt_info.useable = 1;
-      ldt_info.reserved = 0;
-      
-      /* Install the thread area */
-      VG_(do_syscall)(__NR_set_thread_area, &ldt_info);
-      
-      /* Setup the GS segment register */
-      set_gs(ldt_info.entry_number * 8 + 3);
-   }
+   VGA_(thread_wrapper)(&info->aux);
 
    /* Minimally observe the attributes supplied. */
    if (attr__detachstate != PTHREAD_CREATE_DETACHED
@@ -1127,7 +1041,6 @@ pthread_create (pthread_t *__restrict __thredd,
 {
    int            tid_child;
    NewThreadInfo* info;
-   int            gs;
    StackInfo      si;
    vg_pthread_attr_t* __vg_attr;
    CONVERT(attr, __attr, __vg_attr);
@@ -1149,28 +1062,7 @@ pthread_create (pthread_t *__restrict __thredd,
    else 
       info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
 
-   gs = get_gs();
-
-   if ((gs & 7) == 3) {
-      tcbhead_t *tcb = get_tcb();
-
-      if (allocate_tls == NULL || deallocate_tls == NULL) {
-         allocate_tls = (allocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_allocate_tls");
-         deallocate_tls = (deallocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_deallocate_tls");
-      }
-
-      my_assert(allocate_tls != NULL);
-      
-      info->tls_data = allocate_tls(NULL);
-      info->tls_segment = gs >> 3;
-      info->sysinfo = tcb->sysinfo;
-
-      tcb->multiple_threads = 1;
-   } else {
-      info->tls_data = NULL;
-      info->tls_segment = -1;
-      info->sysinfo = 0;
-   }
+   VGA_(thread_create)(&info->aux);
 
    info->root_fn = __start_routine;
    info->arg     = __arg;
@@ -2199,7 +2091,7 @@ int* __errno_location ( void )
    if (tid < 1 || tid >= VG_N_THREADS)
       barf("__errno_location: invalid ThreadId");
    if (thread_specific_state[tid].errno_ptr == NULL) {
-      if ((get_gs() & 7) == 3)
+      if (VGA_(has_tls)())
          thread_specific_state[tid].errno_ptr = dlsym(RTLD_DEFAULT, "errno");
       else if (tid == 1)
          thread_specific_state[tid].errno_ptr = dlvsym(RTLD_DEFAULT, "errno", "GLIBC_2.0");
@@ -2220,7 +2112,7 @@ int* __h_errno_location ( void )
    if (tid < 1 || tid >= VG_N_THREADS)
       barf("__h_errno_location: invalid ThreadId");
    if (thread_specific_state[tid].h_errno_ptr == NULL) {
-      if ((get_gs() & 7) == 3)
+      if (VGA_(has_tls)())
          thread_specific_state[tid].h_errno_ptr = dlsym(RTLD_DEFAULT, "h_errno");
       else if (tid == 1)
          thread_specific_state[tid].h_errno_ptr = dlvsym(RTLD_DEFAULT, "h_errno", "GLIBC_2.0");
@@ -2241,7 +2133,7 @@ struct __res_state* __res_state ( void )
    if (tid < 1 || tid >= VG_N_THREADS)
       barf("__res_state: invalid ThreadId");
    if (thread_specific_state[tid].res_state_ptr == NULL) {
-      if ((get_gs() & 7) == 3) {
+      if (VGA_(has_tls)()) {
          struct __res_state **resp = dlsym(RTLD_DEFAULT, "__resp");
          
          thread_specific_state[tid].res_state_ptr = *resp;
index 7581c031013e19334d601f75c46821dab12c37a9..c0142a63055f19ce228d818819e448a315aeee98 100644 (file)
@@ -11,13 +11,13 @@ noinst_HEADERS = \
 noinst_LIBRARIES = libarch.a
 
 EXTRA_DIST = \
-       jmp_with_stack.c
+       jmp_with_stack.c \
+       libpthread.c
 
 BUILT_SOURCES = stage2.lds
 CLEANFILES = stage2.lds
 
 libarch_a_SOURCES = \
-       libpthread.c \
        signal.c \
        state.c
 
index b9e306b2a8aa00ac5b57a148112c84f6bfebf752..35b76cc10bf8945eefa54d80025d9cfa384cb053 100644 (file)
@@ -305,6 +305,15 @@ typedef struct {
 } 
 arch_thread_t;
 
+/* ---------------------------------------------------------------------
+   libpthread stuff
+   ------------------------------------------------------------------ */
+
+struct arch_thread_aux {
+   void*         tls_data;
+   int           tls_segment;
+   unsigned long sysinfo;
+};
 
 /* ---------------------------------------------------------------------
    Miscellaneous constants
index 54fd493b127fcc961f197f04bc1dfd28fb4861b9..c9f7a74bb828f6e16471b558b10480a59149da06 100644 (file)
    caveats.
 */
 
-//#include "valgrind.h"    /* For the request-passing mechanism */
-//#include "core.h"        /* For the VG_USERREQ__* constants */
+#include "core.h"        /* For the VG_USERREQ__* constants */
 
-//#define __USE_UNIX98
-//#include <sys/types.h>
-//#include <pthread.h>
-//#undef __USE_UNIX98
+#define __USE_UNIX98
+#include <pthread.h>
+#undef __USE_UNIX98
 
-//#define __USE_GNU
-//#include <dlfcn.h>
-//#undef __USE_GNU
+#define __USE_GNU
+#include <dlfcn.h>
+#undef __USE_GNU
 
 #include <errno.h>
 
+// Struct used to describe a TDB header, copied from glibc.
+typedef
+   struct {
+      void *tcb;
+      void *dtv;
+      void *self;                
+      int multiple_threads;
+      unsigned long sysinfo;
+   }
+   tcbhead_t;
+
+/* --------------------------------------------------- 
+   Helper functions for running a thread 
+   and for clearing up afterwards.
+   ------------------------------------------------ */
+
+typedef void *(*__attribute__ ((stdcall)) REGPARM(3) allocate_tls_t) (void *result);
+typedef void (*__attribute__ ((stdcall)) REGPARM(3) deallocate_tls_t) (void *tcb, int dealloc_tcb);
+
+static allocate_tls_t allocate_tls = NULL;
+static deallocate_tls_t deallocate_tls = NULL;
+
+static int get_gs()
+{
+   int gs;
+   asm volatile ("movw %%gs, %w0" : "=q" (gs));
+   return gs & 0xffff;
+}
+
+static void set_gs( int gs )
+{
+   asm volatile ("movw %w0, %%gs" :: "q" (gs));
+}
+
+static void *get_tcb()
+{
+   void *tcb;
+   asm volatile ("movl %%gs:0, %0" : "=r" (tcb));
+   return tcb;
+}
+
+
+Bool VGA_(has_tls)(void)
+{
+   return (get_gs() & 7) == 3;
+}  
+
+
+void VGA_(thread_create)(arch_thread_aux_t *aux)
+{
+   if (VGA_(has_tls)) {
+      tcbhead_t *tcb = get_tcb();
+
+      if (allocate_tls == NULL || deallocate_tls == NULL) {
+         allocate_tls = (allocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_allocate_tls");
+         deallocate_tls = (deallocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_deallocate_tls");
+      }
+
+      my_assert(allocate_tls != NULL);
+      
+      aux->tls_data = allocate_tls(NULL);
+      aux->tls_segment = get_gs() >> 3;
+      aux->sysinfo = tcb->sysinfo;
+
+      tcb->multiple_threads = 1;
+   } else {
+      aux->tls_data = NULL;
+      aux->tls_segment = -1;
+      aux->sysinfo = 0;
+   }
+}
+   
+void VGA_(thread_wrapper)(arch_thread_aux_t *aux)
+{
+   void*         tls_data;
+   int           tls_segment;
+   unsigned long sysinfo;
+      
+   tls_data    = aux->tls_data;
+   tls_segment = aux->tls_segment;
+   sysinfo     = aux->sysinfo;
+
+   if (tls_data) {
+      tcbhead_t *tcb = tls_data;
+      struct vki_modify_ldt_ldt_s ldt_info;
+
+      /* Fill in the TCB header */
+      tcb->tcb = tcb;
+      tcb->self = tcb;
+      tcb->multiple_threads = 1;
+      tcb->sysinfo = sysinfo;
+      
+      /* Fill in an LDT descriptor */
+      ldt_info.entry_number = tls_segment;
+      ldt_info.base_addr = (unsigned long)tls_data;
+      ldt_info.limit = 0xfffff;
+      ldt_info.seg_32bit = 1;
+      ldt_info.contents = 0;
+      ldt_info.read_exec_only = 0;
+      ldt_info.limit_in_pages = 1;
+      ldt_info.seg_not_present = 0;
+      ldt_info.useable = 1;
+      ldt_info.reserved = 0;
+      
+      /* Install the thread area */
+      VG_(do_syscall)(__NR_set_thread_area, &ldt_info);
+      
+      /* Setup the GS segment register */
+      set_gs(ldt_info.entry_number * 8 + 3);
+   }
+}
+   
+void VGA_(thread_exit)(void)
+{
+   /* Free up any TLS data */
+   if ((get_gs() & 7) == 3 && pthread_self() > 1) {
+      my_assert(deallocate_tls != NULL);
+      deallocate_tls(get_tcb(), 1);
+   }
+}   
+
 /* POSIX spinlocks, taken from glibc linuxthreads/sysdeps/i386 */
 
 typedef volatile int pthread_spinlock_t; /* Huh?  Guarded by __USE_XOPEN2K */