|
From: Nicholas N. <nj...@ca...> - 2004-10-19 13:18:11
|
CVS commit by nethercote:
Arch-abstraction:
- 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.
M +2 -1 Makefile.am 1.91
M +22 -0 core.h 1.43
M +8 -116 vg_libpthread.c 1.174
M +2 -2 x86/Makefile.am 1.16
M +9 -0 x86/core_arch.h 1.12
M +129 -10 x86/libpthread.c 1.2
--- valgrind/coregrind/Makefile.am #1.90:1.91
@@ -117,5 +117,6 @@
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 \
--- valgrind/coregrind/core.h #1.42:1.43
@@ -1533,4 +1533,26 @@ extern void VGA_(push_signal_frame) ( Th
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
--- valgrind/coregrind/vg_libpthread.c #1.173:1.174
@@ -311,6 +311,5 @@ 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];
@@ -327,12 +326,4 @@ void my_assert_fail ( const Char* expr,
}
-#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 )
@@ -658,42 +649,4 @@ 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. */
@@ -733,9 +686,5 @@ void thread_exit_wrapper ( void* ret_val
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. */
@@ -770,10 +719,8 @@ 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;
@@ -798,7 +745,4 @@ void thread_wrapper ( NewThreadInfo* inf
{
int attr__detachstate;
- void* tls_data;
- int tls_segment;
- unsigned long sysinfo;
void* (*root_fn) ( void* );
void* arg;
@@ -807,38 +751,8 @@ void thread_wrapper ( NewThreadInfo* inf
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. */
@@ -1128,5 +1042,4 @@ pthread_create (pthread_t *__restrict __
int tid_child;
NewThreadInfo* info;
- int gs;
StackInfo si;
vg_pthread_attr_t* __vg_attr;
@@ -1150,26 +1063,5 @@ pthread_create (pthread_t *__restrict __
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;
@@ -2200,5 +2092,5 @@ int* __errno_location ( void )
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)
@@ -2221,5 +2113,5 @@ int* __h_errno_location ( void )
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)
@@ -2242,5 +2134,5 @@ struct __res_state* __res_state ( void )
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");
--- valgrind/coregrind/x86/Makefile.am #1.15:1.16
@@ -12,5 +12,6 @@
EXTRA_DIST = \
- jmp_with_stack.c
+ jmp_with_stack.c \
+ libpthread.c
BUILT_SOURCES = stage2.lds
@@ -18,5 +19,4 @@
libarch_a_SOURCES = \
- libpthread.c \
signal.c \
state.c
--- valgrind/coregrind/x86/core_arch.h #1.11:1.12
@@ -306,4 +306,13 @@ typedef struct {
arch_thread_t;
+/* ---------------------------------------------------------------------
+ libpthread stuff
+ ------------------------------------------------------------------ */
+
+struct arch_thread_aux {
+ void* tls_data;
+ int tls_segment;
+ unsigned long sysinfo;
+};
/* ---------------------------------------------------------------------
--- valgrind/coregrind/x86/libpthread.c #1.1:1.2
@@ -35,18 +35,137 @@
*/
-//#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 */
|