Use explicit function pointers for pthread support instead of relying
on ELF symbol overriding.
This commit is contained in:
parent
8a5f893712
commit
883d3c52d3
|
@ -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
|
||||
* 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) ));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue