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) ...@@ -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 /* The same as for wine_pthread_mutex_init, we postpone initialization
until condition is really used.*/ until condition is really used.*/
...@@ -362,7 +362,7 @@ int wine_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_ ...@@ -362,7 +362,7 @@ int wine_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_
return 0; 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; wine_cond_detail *detail = ((wine_cond)cond)->cond;
...@@ -375,7 +375,7 @@ int wine_pthread_cond_destroy(pthread_cond_t *cond) ...@@ -375,7 +375,7 @@ int wine_pthread_cond_destroy(pthread_cond_t *cond)
return 0; return 0;
} }
int wine_pthread_cond_signal(pthread_cond_t *cond) static int wine_pthread_cond_signal(pthread_cond_t *cond)
{ {
int have_waiters; int have_waiters;
wine_cond_detail *detail; wine_cond_detail *detail;
...@@ -394,7 +394,7 @@ int wine_pthread_cond_signal(pthread_cond_t *cond) ...@@ -394,7 +394,7 @@ int wine_pthread_cond_signal(pthread_cond_t *cond)
return 0; 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; int have_waiters = 0;
wine_cond_detail *detail; wine_cond_detail *detail;
...@@ -438,7 +438,7 @@ int wine_pthread_cond_broadcast(pthread_cond_t *cond) ...@@ -438,7 +438,7 @@ int wine_pthread_cond_broadcast(pthread_cond_t *cond)
return 0; 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; wine_cond_detail *detail;
int last_waiter; int last_waiter;
...@@ -474,8 +474,8 @@ int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) ...@@ -474,8 +474,8 @@ int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
return 0; return 0;
} }
int wine_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, static int wine_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime) const struct timespec *abstime)
{ {
DWORD ms = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; DWORD ms = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000;
int last_waiter; int last_waiter;
...@@ -539,9 +539,8 @@ static void wine_set_thread_data( void *data ) ...@@ -539,9 +539,8 @@ static void wine_set_thread_data( void *data )
kernel_get_thread_data()->pthread_data = 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_get_thread_data, /* ptr_get_thread_data */
wine_set_thread_data, /* ptr_set_thread_data */ wine_set_thread_data, /* ptr_set_thread_data */
wine_pthread_self, /* ptr_pthread_self */ wine_pthread_self, /* ptr_pthread_self */
...@@ -571,9 +570,12 @@ static const struct wine_pthread_functions functions = ...@@ -571,9 +570,12 @@ static const struct wine_pthread_functions functions =
wine_pthread_cond_timedwait /* ptr_pthread_cond_timedwait */ wine_pthread_cond_timedwait /* ptr_pthread_cond_timedwait */
}; };
static struct wine_pthread_functions pthread_functions;
void PTHREAD_Init(void) 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 */ #endif /* HAVE_PTHREAD_H */
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/exception.h" #include "wine/exception.h"
#include "wine/library.h" #include "wine/library.h"
#include "wine/pthread.h"
#include "wine/server.h" #include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
......
...@@ -83,6 +83,8 @@ struct cmsg_fd ...@@ -83,6 +83,8 @@ struct cmsg_fd
time_t server_start_time = 0; /* time of server startup */ 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 sigset_t block_set; /* signals to block during server calls */
static int fd_socket = -1; /* socket to exchange file descriptors with the server */ static int fd_socket = -1; /* socket to exchange file descriptors with the server */
...@@ -148,7 +150,7 @@ void server_exit_thread( int status ) ...@@ -148,7 +150,7 @@ void server_exit_thread( int status )
close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->wait_fd[1] );
close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->reply_fd );
close( ntdll_get_thread_data()->request_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 ) ...@@ -162,7 +164,7 @@ void server_abort_thread( int status )
close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->wait_fd[1] );
close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->reply_fd );
close( ntdll_get_thread_data()->request_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; ...@@ -53,6 +53,7 @@ static RTL_BITMAP tls_bitmap;
static RTL_BITMAP tls_expansion_bitmap; static RTL_BITMAP tls_expansion_bitmap;
static LIST_ENTRY tls_links; static LIST_ENTRY tls_links;
struct wine_pthread_functions pthread_functions = { NULL };
/*********************************************************************** /***********************************************************************
* init_teb * init_teb
...@@ -136,8 +137,9 @@ void thread_init(void) ...@@ -136,8 +137,9 @@ void thread_init(void)
thread_info.stack_size = 0; thread_info.stack_size = 0;
thread_info.teb_base = teb; thread_info.teb_base = teb;
thread_info.teb_sel = thread_data->teb_sel; thread_info.teb_sel = thread_data->teb_sel;
wine_pthread_init_current_teb( &thread_info ); wine_pthread_get_functions( &pthread_functions, sizeof(pthread_functions) );
wine_pthread_init_thread( &thread_info ); pthread_functions.init_current_teb( &thread_info );
pthread_functions.init_thread( &thread_info );
debug_info.str_pos = debug_info.strings; debug_info.str_pos = debug_info.strings;
debug_info.out_pos = debug_info.output; debug_info.out_pos = debug_info.output;
...@@ -197,10 +199,10 @@ static void start_thread( struct wine_pthread_thread_info *info ) ...@@ -197,10 +199,10 @@ static void start_thread( struct wine_pthread_thread_info *info )
debug_info.out_pos = debug_info.output; debug_info.out_pos = debug_info.output;
thread_data->debug_info = &debug_info; thread_data->debug_info = &debug_info;
wine_pthread_init_current_teb( info ); pthread_functions.init_current_teb( info );
SIGNAL_Init(); SIGNAL_Init();
server_init_thread( info->pid, info->tid, func ); 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 */ /* allocate a memory view for the stack */
size = info->stack_size; size = info->stack_size;
...@@ -305,7 +307,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * ...@@ -305,7 +307,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
info->entry_point = start; info->entry_point = start;
info->entry_arg = param; 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; status = STATUS_NO_MEMORY;
goto error; goto error;
...@@ -673,7 +675,7 @@ __ASM_GLOBAL_FUNC( NtCurrentTeb, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" ); ...@@ -673,7 +675,7 @@ __ASM_GLOBAL_FUNC( NtCurrentTeb, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" );
TEB * WINAPI NtCurrentTeb(void) TEB * WINAPI NtCurrentTeb(void)
{ {
return wine_pthread_get_current_teb(); return pthread_functions.get_current_teb();
} }
#endif /* __i386__ */ #endif /* __i386__ */
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#ifndef __WINE_WINE_PTHREAD_H #ifndef __WINE_WINE_PTHREAD_H
#define __WINE_WINE_PTHREAD_H #define __WINE_WINE_PTHREAD_H
struct wine_pthread_functions; struct wine_pthread_callbacks;
#ifdef HAVE_PTHREAD_H #ifdef HAVE_PTHREAD_H
...@@ -35,9 +35,8 @@ typedef void *pthread_rwlock_t; ...@@ -35,9 +35,8 @@ typedef void *pthread_rwlock_t;
typedef void *pthread_rwlockattr_t; typedef void *pthread_rwlockattr_t;
#endif #endif
struct wine_pthread_functions struct wine_pthread_callbacks
{ {
size_t size;
void * (*ptr_get_thread_data)(void); void * (*ptr_get_thread_data)(void);
void (*ptr_set_thread_data)(void *data); void (*ptr_set_thread_data)(void *data);
pthread_t (*ptr_pthread_self)(void); pthread_t (*ptr_pthread_self)(void);
...@@ -97,12 +96,18 @@ struct wine_pthread_thread_info ...@@ -97,12 +96,18 @@ struct wine_pthread_thread_info
int exit_status; /* thread exit status when calling wine_pthread_exit_thread */ int exit_status; /* thread exit status when calling wine_pthread_exit_thread */
}; };
extern void wine_pthread_init_process( const struct wine_pthread_functions *functions ); struct wine_pthread_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 ); void (*init_process)( const struct wine_pthread_callbacks *callbacks, size_t size );
extern void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ); void (*init_thread)( struct wine_pthread_thread_info *info );
extern void *wine_pthread_get_current_teb(void); int (*create_thread)( struct wine_pthread_thread_info *info );
extern void DECLSPEC_NORETURN wine_pthread_exit_thread( struct wine_pthread_thread_info *info ); void (*init_current_teb)( struct wine_pthread_thread_info *info );
extern void DECLSPEC_NORETURN wine_pthread_abort_thread( int status ); 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 */ #endif /* __WINE_WINE_PTHREAD_H */
...@@ -28,61 +28,23 @@ ...@@ -28,61 +28,23 @@
#include "wine/library.h" #include "wine/library.h"
#include "wine/pthread.h" #include "wine/pthread.h"
/* Note: the wine_pthread functions are just placeholders, static struct wine_pthread_functions pthread_functions;
* they will be overridden by the pthread support code.
*/
/*********************************************************************** /***********************************************************************
* 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 ...@@ -58,13 +58,8 @@ EXPORTS
wine_mmap_add_reserved_area wine_mmap_add_reserved_area
wine_mmap_is_in_reserved_area wine_mmap_is_in_reserved_area
wine_mmap_remove_reserved_area wine_mmap_remove_reserved_area
wine_pthread_abort_thread wine_pthread_get_functions
wine_pthread_create_thread wine_pthread_set_functions
wine_pthread_exit_thread
wine_pthread_get_current_teb
wine_pthread_init_current_teb
wine_pthread_init_process
wine_pthread_init_thread
wine_set_fs wine_set_fs
wine_set_gs wine_set_gs
wine_switch_to_stack wine_switch_to_stack
...@@ -58,13 +58,8 @@ WINE_1.0 ...@@ -58,13 +58,8 @@ WINE_1.0
wine_mmap_add_reserved_area; wine_mmap_add_reserved_area;
wine_mmap_is_in_reserved_area; wine_mmap_is_in_reserved_area;
wine_mmap_remove_reserved_area; wine_mmap_remove_reserved_area;
wine_pthread_abort_thread; wine_pthread_get_functions;
wine_pthread_create_thread; wine_pthread_set_functions;
wine_pthread_exit_thread;
wine_pthread_get_current_teb;
wine_pthread_init_current_teb;
wine_pthread_init_process;
wine_pthread_init_thread;
wine_set_fs; wine_set_fs;
wine_set_gs; wine_set_gs;
wine_switch_to_stack; wine_switch_to_stack;
......
...@@ -75,7 +75,7 @@ struct _pthread_cleanup_buffer; ...@@ -75,7 +75,7 @@ struct _pthread_cleanup_buffer;
#define PSTR(str) __ASM_NAME(#str) #define PSTR(str) __ASM_NAME(#str)
static struct wine_pthread_functions funcs; static struct wine_pthread_callbacks funcs;
/* thread descriptor */ /* thread descriptor */
...@@ -200,23 +200,23 @@ static void cleanup_thread( void *ptr ) ...@@ -200,23 +200,23 @@ static void cleanup_thread( void *ptr )
/*********************************************************************** /***********************************************************************
* wine_pthread_init_process * init_process
* *
* Initialization for a newly created 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 ); funcs.ptr_set_thread_data( &initial_descr );
} }
/*********************************************************************** /***********************************************************************
* wine_pthread_init_thread * init_thread
* *
* Initialization for a newly created 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; struct pthread_descr_struct *descr;
...@@ -240,9 +240,9 @@ void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) ...@@ -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) if (!info->stack_base)
{ {
...@@ -291,11 +291,11 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) ...@@ -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. * 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__ #ifdef __i386__
/* On the i386, the current thread is in the %fs register */ /* 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 ) ...@@ -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 */ /* FIXME: On Alpha, the current TEB is not accessible to user-space */
/* __asm__ __volatile__();*/ /* __asm__ __volatile__();*/
#else #else
# error You must implement wine_pthread_init_current_teb for your platform # error You must implement init_current_teb for your platform
#endif #endif
/* set pid and tid */ /* set pid and tid */
...@@ -333,9 +333,9 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) ...@@ -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; void *ret;
...@@ -358,7 +358,7 @@ void *wine_pthread_get_current_teb(void) ...@@ -358,7 +358,7 @@ void *wine_pthread_get_current_teb(void)
"ldq $0,0($30)\n\t" "ldq $0,0($30)\n\t"
"lda $30,-8($30)" : "=r" (ret) ); "lda $30,-8($30)" : "=r" (ret) );
#else #else
# error wine_pthread_get_current_teb not defined for this architecture # error get_current_teb not defined for this architecture
#endif /* __i386__ */ #endif /* __i386__ */
return ret; return ret;
...@@ -366,18 +366,18 @@ void *wine_pthread_get_current_teb(void) ...@@ -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_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 #ifdef HAVE__LWP_CREATE
_lwp_exit(); _lwp_exit();
...@@ -386,6 +386,21 @@ void wine_pthread_abort_thread( int status ) ...@@ -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, /* Currently this probably works only for glibc2,
* which checks for the presence of double-underscore-prepended * which checks for the presence of double-underscore-prepended
* pthread primitives, and use them if available. * pthread primitives, and use them if available.
......
...@@ -41,6 +41,7 @@ int main( int argc, char *argv[] ) ...@@ -41,6 +41,7 @@ int main( int argc, char *argv[] )
wine_main_preload_info[i].size ); wine_main_preload_info[i].size );
} }
wine_pthread_set_functions( &pthread_functions, sizeof(pthread_functions) );
wine_init( argc, argv, error, sizeof(error) ); wine_init( argc, argv, error, sizeof(error) );
fprintf( stderr, "wine: failed to initialize: %s\n", error ); fprintf( stderr, "wine: failed to initialize: %s\n", error );
exit(1); exit(1);
......
...@@ -22,10 +22,14 @@ ...@@ -22,10 +22,14 @@
#ifndef __WINE_LOADER_MAIN_H #ifndef __WINE_LOADER_MAIN_H
#define __WINE_LOADER_MAIN_H #define __WINE_LOADER_MAIN_H
#include "wine/pthread.h"
struct wine_preload_info struct wine_preload_info
{ {
void *addr; void *addr;
size_t size; size_t size;
}; };
extern const struct wine_pthread_functions pthread_functions;
#endif /* __WINE_LOADER_MAIN_H */ #endif /* __WINE_LOADER_MAIN_H */
...@@ -38,32 +38,32 @@ ...@@ -38,32 +38,32 @@
#include "wine/library.h" #include "wine/library.h"
#include "wine/pthread.h" #include "wine/pthread.h"
static struct wine_pthread_functions funcs; static int init_done;
#ifndef __i386__ #ifndef __i386__
static pthread_key_t teb_key; static pthread_key_t teb_key;
#endif #endif
/*********************************************************************** /***********************************************************************
* wine_pthread_init_process * init_process
* *
* Initialization for a newly created 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. * 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) */ /* retrieve the stack info (except for main thread) */
if (funcs.ptr_set_thread_data) if (init_done)
{ {
#ifdef HAVE_PTHREAD_GETATTR_NP #ifdef HAVE_PTHREAD_GETATTR_NP
pthread_attr_t attr; pthread_attr_t attr;
...@@ -84,9 +84,9 @@ void wine_pthread_init_thread( struct wine_pthread_thread_info *info ) ...@@ -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_t id;
pthread_attr_t attr; pthread_attr_t attr;
...@@ -102,11 +102,11 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info ) ...@@ -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. * 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__ #ifdef __i386__
/* On the i386, the current thread is in the %fs register */ /* 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 ) ...@@ -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_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
wine_ldt_init_fs( info->teb_sel, &fs_entry ); wine_ldt_init_fs( info->teb_sel, &fs_entry );
#else #else
if (!funcs.ptr_set_thread_data) /* first thread */ if (!init_done) /* first thread */
pthread_key_create( &teb_key, NULL ); pthread_key_create( &teb_key, NULL );
pthread_setspecific( teb_key, info->teb_base ); pthread_setspecific( teb_key, info->teb_base );
#endif #endif
...@@ -129,9 +129,9 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) ...@@ -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__ #ifdef __i386__
void *ret; void *ret;
...@@ -144,9 +144,9 @@ void *wine_pthread_get_current_teb(void) ...@@ -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 ); wine_ldt_free_fs( info->teb_sel );
munmap( info->teb_base, info->teb_size ); munmap( info->teb_base, info->teb_size );
...@@ -155,11 +155,26 @@ void wine_pthread_exit_thread( struct wine_pthread_thread_info *info ) ...@@ -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_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 */ #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