From 883d3c52d336fba74babad5de41fe859d271ed34 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 3 Sep 2005 15:11:29 +0000 Subject: [PATCH] Use explicit function pointers for pthread support instead of relying on ELF symbol overriding. --- dlls/kernel/pthread.c | 22 ++++++++++-------- dlls/kernel/thread.c | 1 - dlls/ntdll/server.c | 6 +++-- dlls/ntdll/thread.c | 14 +++++++----- include/wine/pthread.h | 25 ++++++++++++-------- libs/wine/port.c | 52 ++++++------------------------------------ libs/wine/wine.def | 9 ++------ libs/wine/wine.map | 9 ++------ loader/kthread.c | 51 ++++++++++++++++++++++++++--------------- loader/main.c | 1 + loader/main.h | 4 ++++ loader/pthread.c | 51 ++++++++++++++++++++++++++--------------- 12 files changed, 121 insertions(+), 124 deletions(-) diff --git a/dlls/kernel/pthread.c b/dlls/kernel/pthread.c index c461603c1e1..fea5a86b80f 100644 --- a/dlls/kernel/pthread.c +++ b/dlls/kernel/pthread.c @@ -354,7 +354,7 @@ static void wine_cond_real_init(pthread_cond_t *cond) } } -int wine_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) +static int wine_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) { /* The same as for wine_pthread_mutex_init, we postpone initialization until condition is really used.*/ @@ -362,7 +362,7 @@ int wine_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_ return 0; } -int wine_pthread_cond_destroy(pthread_cond_t *cond) +static int wine_pthread_cond_destroy(pthread_cond_t *cond) { wine_cond_detail *detail = ((wine_cond)cond)->cond; @@ -375,7 +375,7 @@ int wine_pthread_cond_destroy(pthread_cond_t *cond) return 0; } -int wine_pthread_cond_signal(pthread_cond_t *cond) +static int wine_pthread_cond_signal(pthread_cond_t *cond) { int have_waiters; wine_cond_detail *detail; @@ -394,7 +394,7 @@ int wine_pthread_cond_signal(pthread_cond_t *cond) return 0; } -int wine_pthread_cond_broadcast(pthread_cond_t *cond) +static int wine_pthread_cond_broadcast(pthread_cond_t *cond) { int have_waiters = 0; wine_cond_detail *detail; @@ -438,7 +438,7 @@ int wine_pthread_cond_broadcast(pthread_cond_t *cond) return 0; } -int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +static int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { wine_cond_detail *detail; int last_waiter; @@ -474,8 +474,8 @@ int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) return 0; } -int wine_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - const struct timespec *abstime) +static int wine_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) { DWORD ms = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; int last_waiter; @@ -539,9 +539,8 @@ static void wine_set_thread_data( void *data ) kernel_get_thread_data()->pthread_data = data; } -static const struct wine_pthread_functions functions = +static const struct wine_pthread_callbacks callbacks = { - sizeof(functions), /* size */ wine_get_thread_data, /* ptr_get_thread_data */ wine_set_thread_data, /* ptr_set_thread_data */ wine_pthread_self, /* ptr_pthread_self */ @@ -571,9 +570,12 @@ static const struct wine_pthread_functions functions = wine_pthread_cond_timedwait /* ptr_pthread_cond_timedwait */ }; +static struct wine_pthread_functions pthread_functions; + void PTHREAD_Init(void) { - wine_pthread_init_process( &functions ); + wine_pthread_get_functions( &pthread_functions, sizeof(pthread_functions) ); + pthread_functions.init_process( &callbacks, sizeof(callbacks) ); } #endif /* HAVE_PTHREAD_H */ diff --git a/dlls/kernel/thread.c b/dlls/kernel/thread.c index ee3e601c6ae..1999473ce27 100644 --- a/dlls/kernel/thread.c +++ b/dlls/kernel/thread.c @@ -42,7 +42,6 @@ #include "wine/winbase16.h" #include "wine/exception.h" #include "wine/library.h" -#include "wine/pthread.h" #include "wine/server.h" #include "wine/debug.h" diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 652700850e1..b1333ca8636 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -83,6 +83,8 @@ struct cmsg_fd time_t server_start_time = 0; /* time of server startup */ +extern struct wine_pthread_functions pthread_functions; + static sigset_t block_set; /* signals to block during server calls */ static int fd_socket = -1; /* socket to exchange file descriptors with the server */ @@ -148,7 +150,7 @@ void server_exit_thread( int status ) close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); - wine_pthread_exit_thread( &info ); + pthread_functions.exit_thread( &info ); } @@ -162,7 +164,7 @@ void server_abort_thread( int status ) close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); - wine_pthread_abort_thread( status ); + pthread_functions.abort_thread( status ); } diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 6541711029b..285f8874d95 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -53,6 +53,7 @@ static RTL_BITMAP tls_bitmap; static RTL_BITMAP tls_expansion_bitmap; static LIST_ENTRY tls_links; +struct wine_pthread_functions pthread_functions = { NULL }; /*********************************************************************** * init_teb @@ -136,8 +137,9 @@ void thread_init(void) thread_info.stack_size = 0; thread_info.teb_base = teb; thread_info.teb_sel = thread_data->teb_sel; - wine_pthread_init_current_teb( &thread_info ); - wine_pthread_init_thread( &thread_info ); + wine_pthread_get_functions( &pthread_functions, sizeof(pthread_functions) ); + pthread_functions.init_current_teb( &thread_info ); + pthread_functions.init_thread( &thread_info ); debug_info.str_pos = debug_info.strings; debug_info.out_pos = debug_info.output; @@ -197,10 +199,10 @@ static void start_thread( struct wine_pthread_thread_info *info ) debug_info.out_pos = debug_info.output; thread_data->debug_info = &debug_info; - wine_pthread_init_current_teb( info ); + pthread_functions.init_current_teb( info ); SIGNAL_Init(); server_init_thread( info->pid, info->tid, func ); - wine_pthread_init_thread( info ); + pthread_functions.init_thread( info ); /* allocate a memory view for the stack */ size = info->stack_size; @@ -305,7 +307,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * info->entry_point = start; info->entry_arg = param; - if (wine_pthread_create_thread( &info->pthread_info ) == -1) + if (pthread_functions.create_thread( &info->pthread_info ) == -1) { status = STATUS_NO_MEMORY; goto error; @@ -673,7 +675,7 @@ __ASM_GLOBAL_FUNC( NtCurrentTeb, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" ); TEB * WINAPI NtCurrentTeb(void) { - return wine_pthread_get_current_teb(); + return pthread_functions.get_current_teb(); } #endif /* __i386__ */ diff --git a/include/wine/pthread.h b/include/wine/pthread.h index b8add660ca6..c78561ddda7 100644 --- a/include/wine/pthread.h +++ b/include/wine/pthread.h @@ -21,7 +21,7 @@ #ifndef __WINE_WINE_PTHREAD_H #define __WINE_WINE_PTHREAD_H -struct wine_pthread_functions; +struct wine_pthread_callbacks; #ifdef HAVE_PTHREAD_H @@ -35,9 +35,8 @@ typedef void *pthread_rwlock_t; typedef void *pthread_rwlockattr_t; #endif -struct wine_pthread_functions +struct wine_pthread_callbacks { - size_t size; void * (*ptr_get_thread_data)(void); void (*ptr_set_thread_data)(void *data); pthread_t (*ptr_pthread_self)(void); @@ -97,12 +96,18 @@ struct wine_pthread_thread_info int exit_status; /* thread exit status when calling wine_pthread_exit_thread */ }; -extern void wine_pthread_init_process( const struct wine_pthread_functions *functions ); -extern void wine_pthread_init_thread( struct wine_pthread_thread_info *info ); -extern int wine_pthread_create_thread( struct wine_pthread_thread_info *info ); -extern void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ); -extern void *wine_pthread_get_current_teb(void); -extern void DECLSPEC_NORETURN wine_pthread_exit_thread( struct wine_pthread_thread_info *info ); -extern void DECLSPEC_NORETURN wine_pthread_abort_thread( int status ); +struct wine_pthread_functions +{ + void (*init_process)( const struct wine_pthread_callbacks *callbacks, size_t size ); + void (*init_thread)( struct wine_pthread_thread_info *info ); + int (*create_thread)( struct wine_pthread_thread_info *info ); + void (*init_current_teb)( struct wine_pthread_thread_info *info ); + void * (*get_current_teb)(void); + void (* DECLSPEC_NORETURN exit_thread)( struct wine_pthread_thread_info *info ); + void (* DECLSPEC_NORETURN abort_thread)( int status ); +}; + +extern void wine_pthread_get_functions( struct wine_pthread_functions *functions, size_t size ); +extern void wine_pthread_set_functions( const struct wine_pthread_functions *functions, size_t size ); #endif /* __WINE_WINE_PTHREAD_H */ diff --git a/libs/wine/port.c b/libs/wine/port.c index 42ca62bce44..cc7c7ca7fd7 100644 --- a/libs/wine/port.c +++ b/libs/wine/port.c @@ -28,61 +28,23 @@ #include "wine/library.h" #include "wine/pthread.h" -/* Note: the wine_pthread functions are just placeholders, - * they will be overridden by the pthread support code. - */ +static struct wine_pthread_functions pthread_functions; /*********************************************************************** - * wine_pthread_init_process + * wine_pthread_get_functions */ -void wine_pthread_init_process( const struct wine_pthread_functions *functions ) +void wine_pthread_get_functions( struct wine_pthread_functions *functions, size_t size ) { + memcpy( functions, &pthread_functions, min( size, sizeof(pthread_functions) )); } -/*********************************************************************** - * wine_pthread_init_thread - */ -void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) -{ -} /*********************************************************************** - * wine_pthread_create_thread + * wine_pthread_set_functions */ -int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) +void wine_pthread_set_functions( const struct wine_pthread_functions *functions, size_t size ) { - return -1; -} - -/*********************************************************************** - * wine_pthread_init_current_teb - */ -void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) -{ -} - -/*********************************************************************** - * wine_pthread_get_current_teb - */ -void *wine_pthread_get_current_teb(void) -{ - return NULL; -} - -/*********************************************************************** - * wine_pthread_exit_thread - */ -void wine_pthread_exit_thread( struct wine_pthread_thread_info *info ) -{ - exit( info->exit_status ); -} - -/*********************************************************************** - * wine_pthread_abort_thread - */ -void wine_pthread_abort_thread( int status ) -{ - exit( status ); + memcpy( &pthread_functions, functions, min( size, sizeof(pthread_functions) )); } diff --git a/libs/wine/wine.def b/libs/wine/wine.def index 75b5e5e8a0c..d7f1859e9ec 100644 --- a/libs/wine/wine.def +++ b/libs/wine/wine.def @@ -58,13 +58,8 @@ EXPORTS wine_mmap_add_reserved_area wine_mmap_is_in_reserved_area wine_mmap_remove_reserved_area - wine_pthread_abort_thread - wine_pthread_create_thread - wine_pthread_exit_thread - wine_pthread_get_current_teb - wine_pthread_init_current_teb - wine_pthread_init_process - wine_pthread_init_thread + wine_pthread_get_functions + wine_pthread_set_functions wine_set_fs wine_set_gs wine_switch_to_stack diff --git a/libs/wine/wine.map b/libs/wine/wine.map index e45671df66b..4e4104c216b 100644 --- a/libs/wine/wine.map +++ b/libs/wine/wine.map @@ -58,13 +58,8 @@ WINE_1.0 wine_mmap_add_reserved_area; wine_mmap_is_in_reserved_area; wine_mmap_remove_reserved_area; - wine_pthread_abort_thread; - wine_pthread_create_thread; - wine_pthread_exit_thread; - wine_pthread_get_current_teb; - wine_pthread_init_current_teb; - wine_pthread_init_process; - wine_pthread_init_thread; + wine_pthread_get_functions; + wine_pthread_set_functions; wine_set_fs; wine_set_gs; wine_switch_to_stack; diff --git a/loader/kthread.c b/loader/kthread.c index 368410e20cc..4235b10b574 100644 --- a/loader/kthread.c +++ b/loader/kthread.c @@ -75,7 +75,7 @@ struct _pthread_cleanup_buffer; #define PSTR(str) __ASM_NAME(#str) -static struct wine_pthread_functions funcs; +static struct wine_pthread_callbacks funcs; /* thread descriptor */ @@ -200,23 +200,23 @@ static void cleanup_thread( void *ptr ) /*********************************************************************** - * wine_pthread_init_process + * init_process * * Initialization for a newly created process. */ -void wine_pthread_init_process( const struct wine_pthread_functions *functions ) +static void init_process( const struct wine_pthread_callbacks *callbacks, size_t size ) { - memcpy( &funcs, functions, min(functions->size,sizeof(funcs)) ); + memcpy( &funcs, callbacks, min( size, sizeof(funcs) )); funcs.ptr_set_thread_data( &initial_descr ); } /*********************************************************************** - * wine_pthread_init_thread + * init_thread * * Initialization for a newly created thread. */ -void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) +static void init_thread( struct wine_pthread_thread_info *info ) { struct pthread_descr_struct *descr; @@ -240,9 +240,9 @@ void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_create_thread + * create_thread */ -int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) +static int create_thread( struct wine_pthread_thread_info *info ) { if (!info->stack_base) { @@ -291,11 +291,11 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_init_current_teb + * init_current_teb * * Set the current TEB for a new thread. */ -void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) +static void init_current_teb( struct wine_pthread_thread_info *info ) { #ifdef __i386__ /* On the i386, the current thread is in the %fs register */ @@ -319,7 +319,7 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) /* FIXME: On Alpha, the current TEB is not accessible to user-space */ /* __asm__ __volatile__();*/ #else -# error You must implement wine_pthread_init_current_teb for your platform +# error You must implement init_current_teb for your platform #endif /* set pid and tid */ @@ -333,9 +333,9 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_get_current_teb + * get_current_teb */ -void *wine_pthread_get_current_teb(void) +static void *get_current_teb(void) { void *ret; @@ -358,7 +358,7 @@ void *wine_pthread_get_current_teb(void) "ldq $0,0($30)\n\t" "lda $30,-8($30)" : "=r" (ret) ); #else -# error wine_pthread_get_current_teb not defined for this architecture +# error get_current_teb not defined for this architecture #endif /* __i386__ */ return ret; @@ -366,18 +366,18 @@ void *wine_pthread_get_current_teb(void) /*********************************************************************** - * wine_pthread_exit_thread + * exit_thread */ -void wine_pthread_exit_thread( struct wine_pthread_thread_info *info ) +static void DECLSPEC_NORETURN exit_thread( struct wine_pthread_thread_info *info ) { wine_switch_to_stack( cleanup_thread, info, get_temp_stack() ); } /*********************************************************************** - * wine_pthread_abort_thread + * abort_thread */ -void wine_pthread_abort_thread( int status ) +static void DECLSPEC_NORETURN abort_thread( int status ) { #ifdef HAVE__LWP_CREATE _lwp_exit(); @@ -386,6 +386,21 @@ void wine_pthread_abort_thread( int status ) } +/*********************************************************************** + * pthread_functions + */ +const struct wine_pthread_functions pthread_functions = +{ + init_process, + init_thread, + create_thread, + init_current_teb, + get_current_teb, + exit_thread, + abort_thread +}; + + /* Currently this probably works only for glibc2, * which checks for the presence of double-underscore-prepended * pthread primitives, and use them if available. diff --git a/loader/main.c b/loader/main.c index cd45733d8fa..88801987a9b 100644 --- a/loader/main.c +++ b/loader/main.c @@ -41,6 +41,7 @@ int main( int argc, char *argv[] ) wine_main_preload_info[i].size ); } + wine_pthread_set_functions( &pthread_functions, sizeof(pthread_functions) ); wine_init( argc, argv, error, sizeof(error) ); fprintf( stderr, "wine: failed to initialize: %s\n", error ); exit(1); diff --git a/loader/main.h b/loader/main.h index 3647f4ef5dd..6c05da972d2 100644 --- a/loader/main.h +++ b/loader/main.h @@ -22,10 +22,14 @@ #ifndef __WINE_LOADER_MAIN_H #define __WINE_LOADER_MAIN_H +#include "wine/pthread.h" + struct wine_preload_info { void *addr; size_t size; }; +extern const struct wine_pthread_functions pthread_functions; + #endif /* __WINE_LOADER_MAIN_H */ diff --git a/loader/pthread.c b/loader/pthread.c index 148438bae3a..35a88fabc5f 100644 --- a/loader/pthread.c +++ b/loader/pthread.c @@ -38,32 +38,32 @@ #include "wine/library.h" #include "wine/pthread.h" -static struct wine_pthread_functions funcs; +static int init_done; #ifndef __i386__ static pthread_key_t teb_key; #endif /*********************************************************************** - * wine_pthread_init_process + * init_process * * Initialization for a newly created process. */ -void wine_pthread_init_process( const struct wine_pthread_functions *functions ) +static void init_process( const struct wine_pthread_callbacks *callbacks, size_t size ) { - memcpy( &funcs, functions, min(functions->size,sizeof(funcs)) ); + init_done = 1; } /*********************************************************************** - * wine_pthread_init_thread + * init_thread * * Initialization for a newly created thread. */ -void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) +static void init_thread( struct wine_pthread_thread_info *info ) { /* retrieve the stack info (except for main thread) */ - if (funcs.ptr_set_thread_data) + if (init_done) { #ifdef HAVE_PTHREAD_GETATTR_NP pthread_attr_t attr; @@ -84,9 +84,9 @@ void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_create_thread + * create_thread */ -int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) +static int create_thread( struct wine_pthread_thread_info *info ) { pthread_t id; pthread_attr_t attr; @@ -102,11 +102,11 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_init_current_teb + * init_current_teb * * Set the current TEB for a new thread. */ -void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) +static void init_current_teb( struct wine_pthread_thread_info *info ) { #ifdef __i386__ /* On the i386, the current thread is in the %fs register */ @@ -117,7 +117,7 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT ); wine_ldt_init_fs( info->teb_sel, &fs_entry ); #else - if (!funcs.ptr_set_thread_data) /* first thread */ + if (!init_done) /* first thread */ pthread_key_create( &teb_key, NULL ); pthread_setspecific( teb_key, info->teb_base ); #endif @@ -129,9 +129,9 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_get_current_teb + * get_current_teb */ -void *wine_pthread_get_current_teb(void) +static void *get_current_teb(void) { #ifdef __i386__ void *ret; @@ -144,9 +144,9 @@ void *wine_pthread_get_current_teb(void) /*********************************************************************** - * wine_pthread_exit_thread + * exit_thread */ -void wine_pthread_exit_thread( struct wine_pthread_thread_info *info ) +static void DECLSPEC_NORETURN exit_thread( struct wine_pthread_thread_info *info ) { wine_ldt_free_fs( info->teb_sel ); munmap( info->teb_base, info->teb_size ); @@ -155,11 +155,26 @@ void wine_pthread_exit_thread( struct wine_pthread_thread_info *info ) /*********************************************************************** - * wine_pthread_abort_thread + * abort_thread */ -void wine_pthread_abort_thread( int status ) +static void DECLSPEC_NORETURN abort_thread( int status ) { pthread_exit( (void *)status ); } + +/*********************************************************************** + * pthread_functions + */ +const struct wine_pthread_functions pthread_functions = +{ + init_process, + init_thread, + create_thread, + init_current_teb, + get_current_teb, + exit_thread, + abort_thread +}; + #endif /* HAVE_PTHREAD_H */