Commit 883d3c52 authored by Alexandre Julliard's avatar Alexandre Julliard

Use explicit function pointers for pthread support instead of relying

on ELF symbol overriding.
parent 8a5f8937
......@@ -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 */
......@@ -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"
......
......@@ -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 );
}
......
......@@ -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__ */
......@@ -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 */
......@@ -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
*/
int wine_pthread_create_thread( struct wine_pthread_thread_info *info )
{
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
* wine_pthread_set_functions
*/
void wine_pthread_abort_thread( int status )
void wine_pthread_set_functions( const struct wine_pthread_functions *functions, size_t size )
{
exit( status );
memcpy( &pthread_functions, functions, min( size, sizeof(pthread_functions) ));
}
......
......@@ -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
......@@ -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;
......
......@@ -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.
......
......@@ -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);
......
......@@ -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 */
......@@ -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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment