Moved the remaining SYSDEPS_* functions to the wine_pthread interface.
Let the pthread library allocate the stack itself.
This commit is contained in:
parent
8d0ac5574e
commit
50fba7ffec
|
@ -551,6 +551,7 @@ static void wine_set_thread_data( void *data )
|
||||||
|
|
||||||
static const struct wine_pthread_functions functions =
|
static const struct wine_pthread_functions functions =
|
||||||
{
|
{
|
||||||
|
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 */
|
||||||
|
|
|
@ -36,7 +36,6 @@ C_SRCS = \
|
||||||
signal_sparc.c \
|
signal_sparc.c \
|
||||||
string.c \
|
string.c \
|
||||||
sync.c \
|
sync.c \
|
||||||
sysdeps.c \
|
|
||||||
version.c \
|
version.c \
|
||||||
thread.c \
|
thread.c \
|
||||||
time.c \
|
time.c \
|
||||||
|
|
|
@ -52,7 +52,7 @@ extern void thread_init(void);
|
||||||
|
|
||||||
/* server support */
|
/* server support */
|
||||||
extern void server_init_process(void);
|
extern void server_init_process(void);
|
||||||
extern void server_init_thread(void);
|
extern void server_init_thread( int unix_pid, int unix_tid );
|
||||||
extern void DECLSPEC_NORETURN server_protocol_error( const char *err, ... );
|
extern void DECLSPEC_NORETURN server_protocol_error( const char *err, ... );
|
||||||
extern void DECLSPEC_NORETURN server_protocol_perror( const char *err );
|
extern void DECLSPEC_NORETURN server_protocol_perror( const char *err );
|
||||||
extern void DECLSPEC_NORETURN server_abort_thread( int status );
|
extern void DECLSPEC_NORETURN server_abort_thread( int status );
|
||||||
|
|
|
@ -666,7 +666,7 @@ void server_init_process(void)
|
||||||
*
|
*
|
||||||
* Send an init thread request. Return 0 if OK.
|
* Send an init thread request. Return 0 if OK.
|
||||||
*/
|
*/
|
||||||
void server_init_thread(void)
|
void server_init_thread( int unix_pid, int unix_tid )
|
||||||
{
|
{
|
||||||
TEB *teb = NtCurrentTeb();
|
TEB *teb = NtCurrentTeb();
|
||||||
int version, ret;
|
int version, ret;
|
||||||
|
@ -700,8 +700,8 @@ void server_init_thread(void)
|
||||||
|
|
||||||
SERVER_START_REQ( init_thread )
|
SERVER_START_REQ( init_thread )
|
||||||
{
|
{
|
||||||
req->unix_pid = getpid();
|
req->unix_pid = unix_pid;
|
||||||
req->unix_tid = SYSDEPS_GetUnixTid();
|
req->unix_tid = unix_tid;
|
||||||
req->teb = teb;
|
req->teb = teb;
|
||||||
req->entry = teb->entry_point;
|
req->entry = teb->entry_point;
|
||||||
req->reply_fd = reply_pipe[1];
|
req->reply_fd = reply_pipe[1];
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
* System-dependent scheduler support
|
|
||||||
*
|
|
||||||
* Copyright 1998 Alexandre Julliard
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "wine/port.h"
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
# include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SYSCALL_H
|
|
||||||
# include <sys/syscall.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_LWP_H
|
|
||||||
# include <sys/lwp.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UCONTEXT_H
|
|
||||||
# include <ucontext.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_MMAN_H
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SCHED_H
|
|
||||||
#include <sched.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ntstatus.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "wine/pthread.h"
|
|
||||||
#include "wine/server.h"
|
|
||||||
#include "winbase.h"
|
|
||||||
#include "wine/library.h"
|
|
||||||
#include "wine/debug.h"
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(thread);
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* SYSDEPS_SetCurThread
|
|
||||||
*
|
|
||||||
* Make 'thread' the current thread.
|
|
||||||
*/
|
|
||||||
void SYSDEPS_SetCurThread( TEB *teb )
|
|
||||||
{
|
|
||||||
#if defined(__i386__)
|
|
||||||
/* On the i386, the current thread is in the %fs register */
|
|
||||||
LDT_ENTRY fs_entry;
|
|
||||||
|
|
||||||
wine_ldt_set_base( &fs_entry, teb );
|
|
||||||
wine_ldt_set_limit( &fs_entry, 0xfff );
|
|
||||||
wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
|
|
||||||
wine_ldt_init_fs( teb->teb_sel, &fs_entry );
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
/* On PowerPC, the current TEB is in the gpr13 register */
|
|
||||||
# ifdef __APPLE__
|
|
||||||
__asm__ __volatile__("mr r13, %0" : : "r" (teb));
|
|
||||||
# else
|
|
||||||
__asm__ __volatile__("mr 2, %0" : : "r" (teb));
|
|
||||||
# endif
|
|
||||||
#elif defined(HAVE__LWP_CREATE)
|
|
||||||
/* On non-i386 Solaris, we use the LWP private pointer */
|
|
||||||
_lwp_setprivate( teb );
|
|
||||||
#endif
|
|
||||||
wine_pthread_init_thread();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* SYSDEPS_GetUnixTid
|
|
||||||
*
|
|
||||||
* Get the Unix tid of the current thread.
|
|
||||||
*/
|
|
||||||
int SYSDEPS_GetUnixTid(void)
|
|
||||||
{
|
|
||||||
#ifdef HAVE__LWP_SELF
|
|
||||||
return _lwp_self();
|
|
||||||
#elif defined(__linux__) && defined(__i386__)
|
|
||||||
int ret;
|
|
||||||
__asm__("int $0x80" : "=a" (ret) : "0" (224) /* SYS_gettid */);
|
|
||||||
if (ret < 0) ret = -1;
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* NtCurrentTeb (NTDLL.@)
|
|
||||||
*
|
|
||||||
* This will crash and burn if called before threading is initialized
|
|
||||||
*/
|
|
||||||
#if defined(__i386__) && defined(__GNUC__)
|
|
||||||
__ASM_GLOBAL_FUNC( NtCurrentTeb, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" );
|
|
||||||
#elif defined(__i386__) && defined(_MSC_VER)
|
|
||||||
/* Nothing needs to be done. MS C "magically" exports the inline version from winnt.h */
|
|
||||||
#elif defined(HAVE__LWP_CREATE)
|
|
||||||
/***********************************************************************
|
|
||||||
* NtCurrentTeb (NTDLL.@)
|
|
||||||
*/
|
|
||||||
struct _TEB * WINAPI NtCurrentTeb(void)
|
|
||||||
{
|
|
||||||
extern void *_lwp_getprivate(void);
|
|
||||||
return (struct _TEB *)_lwp_getprivate();
|
|
||||||
}
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
# ifdef __APPLE__
|
|
||||||
__ASM_GLOBAL_FUNC( NtCurrentTeb, "\n\tmr r3,r13\n\tblr" );
|
|
||||||
# else
|
|
||||||
__ASM_GLOBAL_FUNC( NtCurrentTeb, "\n\tmr 3,2\n\tblr" );
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# error NtCurrentTeb not defined for this architecture
|
|
||||||
#endif /* __i386__ */
|
|
|
@ -95,6 +95,7 @@ void thread_init(void)
|
||||||
TEB *teb;
|
TEB *teb;
|
||||||
void *addr;
|
void *addr;
|
||||||
ULONG size;
|
ULONG size;
|
||||||
|
struct wine_pthread_thread_info thread_info;
|
||||||
static struct debug_info debug_info; /* debug info for initial thread */
|
static struct debug_info debug_info; /* debug info for initial thread */
|
||||||
|
|
||||||
debug_info.str_pos = debug_info.strings;
|
debug_info.str_pos = debug_info.strings;
|
||||||
|
@ -118,11 +119,16 @@ void thread_init(void)
|
||||||
teb->debug_info = &debug_info;
|
teb->debug_info = &debug_info;
|
||||||
InsertHeadList( &tls_links, &teb->TlsLinks );
|
InsertHeadList( &tls_links, &teb->TlsLinks );
|
||||||
|
|
||||||
SYSDEPS_SetCurThread( teb );
|
thread_info.stack_base = NULL;
|
||||||
|
thread_info.stack_size = 0;
|
||||||
|
thread_info.teb_base = teb;
|
||||||
|
thread_info.teb_size = size;
|
||||||
|
thread_info.teb_sel = teb->teb_sel;
|
||||||
|
wine_pthread_init_thread( &thread_info );
|
||||||
|
|
||||||
/* setup the server connection */
|
/* setup the server connection */
|
||||||
server_init_process();
|
server_init_process();
|
||||||
server_init_thread();
|
server_init_thread( thread_info.pid, thread_info.tid );
|
||||||
|
|
||||||
/* create a memory view for the TEB */
|
/* create a memory view for the TEB */
|
||||||
NtAllocateVirtualMemory( GetCurrentProcess(), &addr, teb, &size,
|
NtAllocateVirtualMemory( GetCurrentProcess(), &addr, teb, &size,
|
||||||
|
@ -153,9 +159,9 @@ static void start_thread( struct wine_pthread_thread_info *info )
|
||||||
debug_info.out_pos = debug_info.output;
|
debug_info.out_pos = debug_info.output;
|
||||||
teb->debug_info = &debug_info;
|
teb->debug_info = &debug_info;
|
||||||
|
|
||||||
SYSDEPS_SetCurThread( teb );
|
wine_pthread_init_thread( info );
|
||||||
SIGNAL_Init();
|
SIGNAL_Init();
|
||||||
server_init_thread();
|
server_init_thread( info->pid, info->tid );
|
||||||
|
|
||||||
/* allocate a memory view for the stack */
|
/* allocate a memory view for the stack */
|
||||||
size = info->stack_size;
|
size = info->stack_size;
|
||||||
|
@ -540,3 +546,18 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* NtCurrentTeb (NTDLL.@)
|
||||||
|
*/
|
||||||
|
#if defined(__i386__) && defined(__GNUC__)
|
||||||
|
__ASM_GLOBAL_FUNC( NtCurrentTeb, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" );
|
||||||
|
#elif defined(__i386__) && defined(_MSC_VER)
|
||||||
|
/* Nothing needs to be done. MS C "magically" exports the inline version from winnt.h */
|
||||||
|
#else
|
||||||
|
TEB * WINAPI NtCurrentTeb(void)
|
||||||
|
{
|
||||||
|
return wine_pthread_get_current_teb();
|
||||||
|
}
|
||||||
|
#endif /* __i386__ */
|
||||||
|
|
|
@ -143,8 +143,4 @@ typedef struct _TEB
|
||||||
/* scheduler/thread.c */
|
/* scheduler/thread.c */
|
||||||
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
|
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
|
||||||
|
|
||||||
/* scheduler/sysdeps.c */
|
|
||||||
extern void SYSDEPS_SetCurThread( TEB *teb );
|
|
||||||
extern int SYSDEPS_GetUnixTid(void);
|
|
||||||
|
|
||||||
#endif /* __WINE_THREAD_H */
|
#endif /* __WINE_THREAD_H */
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef void *pthread_rwlockattr_t;
|
||||||
|
|
||||||
struct wine_pthread_functions
|
struct wine_pthread_functions
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
|
@ -85,18 +86,21 @@ struct wine_pthread_functions
|
||||||
/* thread information used to creating and exiting threads */
|
/* thread information used to creating and exiting threads */
|
||||||
struct wine_pthread_thread_info
|
struct wine_pthread_thread_info
|
||||||
{
|
{
|
||||||
void *stack_base;
|
void *stack_base; /* base address of the stack */
|
||||||
size_t stack_size;
|
size_t stack_size; /* size of the stack */
|
||||||
void *teb_base;
|
void *teb_base; /* base address of the TEB */
|
||||||
size_t teb_size;
|
size_t teb_size; /* size of the TEB (possibly including signal stack) */
|
||||||
unsigned short teb_sel;
|
unsigned short teb_sel; /* selector to use for TEB */
|
||||||
void (*entry)( struct wine_pthread_thread_info *info );
|
int pid; /* Unix process id */
|
||||||
int exit_status;
|
int tid; /* Unix thread id */
|
||||||
|
void (*entry)( struct wine_pthread_thread_info *info ); /* thread entry point */
|
||||||
|
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_process( const struct wine_pthread_functions *functions );
|
||||||
extern void wine_pthread_init_thread(void);
|
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 int wine_pthread_create_thread( 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_exit_thread( struct wine_pthread_thread_info *info );
|
||||||
extern void DECLSPEC_NORETURN wine_pthread_abort_thread( int status );
|
extern void DECLSPEC_NORETURN wine_pthread_abort_thread( int status );
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_pthread_init_thread
|
* wine_pthread_init_thread
|
||||||
*/
|
*/
|
||||||
void wine_pthread_init_thread(void)
|
void wine_pthread_init_thread( struct wine_pthread_thread_info *info )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,14 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info )
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* wine_pthread_get_current_teb
|
||||||
|
*/
|
||||||
|
void *wine_pthread_get_current_teb(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_pthread_exit_thread
|
* wine_pthread_exit_thread
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -206,7 +206,7 @@ static void cleanup_thread( void *ptr )
|
||||||
*/
|
*/
|
||||||
void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
||||||
{
|
{
|
||||||
memcpy( &funcs, functions, sizeof(funcs) );
|
memcpy( &funcs, functions, min(functions->size,sizeof(funcs)) );
|
||||||
funcs.ptr_set_thread_data( &initial_descr );
|
funcs.ptr_set_thread_data( &initial_descr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,10 +216,38 @@ void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
||||||
*
|
*
|
||||||
* Initialization for a newly created thread.
|
* Initialization for a newly created thread.
|
||||||
*/
|
*/
|
||||||
void wine_pthread_init_thread(void)
|
void wine_pthread_init_thread( struct wine_pthread_thread_info *info )
|
||||||
{
|
{
|
||||||
struct pthread_descr_struct *descr;
|
struct pthread_descr_struct *descr;
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
/* On the i386, the current thread is in the %fs register */
|
||||||
|
LDT_ENTRY fs_entry;
|
||||||
|
|
||||||
|
wine_ldt_set_base( &fs_entry, info->teb_base );
|
||||||
|
wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
|
||||||
|
wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
|
||||||
|
wine_ldt_init_fs( info->teb_sel, &fs_entry );
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
/* On PowerPC, the current TEB is in the gpr13 register */
|
||||||
|
# ifdef __APPLE__
|
||||||
|
__asm__ __volatile__("mr r13, %0" : : "r" (info->teb_base));
|
||||||
|
# else
|
||||||
|
__asm__ __volatile__("mr 2, %0" : : "r" (info->teb_base));
|
||||||
|
# endif
|
||||||
|
#elif defined(HAVE__LWP_CREATE)
|
||||||
|
/* On non-i386 Solaris, we use the LWP private pointer */
|
||||||
|
_lwp_setprivate( info->teb_base );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set pid and tid */
|
||||||
|
info->pid = getpid();
|
||||||
|
#ifdef HAVE__LWP_SELF
|
||||||
|
info->tid = _lwp_self();
|
||||||
|
#else
|
||||||
|
info->tid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (funcs.ptr_set_thread_data)
|
if (funcs.ptr_set_thread_data)
|
||||||
{
|
{
|
||||||
descr = calloc( 1, sizeof(*descr) );
|
descr = calloc( 1, sizeof(*descr) );
|
||||||
|
@ -290,6 +318,31 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* wine_pthread_get_current_teb
|
||||||
|
*/
|
||||||
|
void *wine_pthread_get_current_teb(void)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
__asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret) );
|
||||||
|
#elif defined(HAVE__LWP_CREATE)
|
||||||
|
ret = _lwp_getprivate();
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
# ifdef __APPLE__
|
||||||
|
__asm__( "mr %0,r13" : "=r" (ret) );
|
||||||
|
# else
|
||||||
|
__asm__( "mr %0,2" : "=r" (ret) );
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# error wine_pthread_get_current_teb not defined for this architecture
|
||||||
|
#endif /* __i386__ */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_pthread_exit_thread
|
* wine_pthread_exit_thread
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,6 +38,25 @@
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
#include "wine/pthread.h"
|
#include "wine/pthread.h"
|
||||||
|
|
||||||
|
static struct wine_pthread_functions funcs;
|
||||||
|
|
||||||
|
#ifndef __i386__
|
||||||
|
static pthread_key_t teb_key;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int gettid(void)
|
||||||
|
{
|
||||||
|
#if defined(__linux__) && defined(__i386__)
|
||||||
|
int ret;
|
||||||
|
__asm__("int $0x80" : "=a" (ret) : "0" (224) /* SYS_gettid */);
|
||||||
|
if (ret < 0) ret = -1;
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return -1; /* FIXME */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_pthread_init_process
|
* wine_pthread_init_process
|
||||||
*
|
*
|
||||||
|
@ -45,6 +64,7 @@
|
||||||
*/
|
*/
|
||||||
void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
||||||
{
|
{
|
||||||
|
memcpy( &funcs, functions, min(functions->size,sizeof(funcs)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,8 +73,33 @@ void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
||||||
*
|
*
|
||||||
* Initialization for a newly created thread.
|
* Initialization for a newly created thread.
|
||||||
*/
|
*/
|
||||||
void wine_pthread_init_thread(void)
|
void wine_pthread_init_thread( struct wine_pthread_thread_info *info )
|
||||||
{
|
{
|
||||||
|
#ifdef __i386__
|
||||||
|
/* On the i386, the current thread is in the %fs register */
|
||||||
|
LDT_ENTRY fs_entry;
|
||||||
|
|
||||||
|
wine_ldt_set_base( &fs_entry, info->teb_base );
|
||||||
|
wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
|
||||||
|
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 */
|
||||||
|
pthread_key_create( &teb_key, NULL );
|
||||||
|
pthread_setspecific( teb_key, info->teb_base );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* retrieve the stack info (except for main thread) */
|
||||||
|
if (funcs.ptr_set_thread_data)
|
||||||
|
{
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_getattr_np( pthread_self(), &attr );
|
||||||
|
pthread_attr_getstack( &attr, &info->stack_base, &info->stack_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set pid and tid */
|
||||||
|
info->pid = getpid();
|
||||||
|
info->tid = gettid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,17 +110,28 @@ int wine_pthread_create_thread( struct wine_pthread_thread_info *info )
|
||||||
{
|
{
|
||||||
pthread_t id;
|
pthread_t id;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!info->stack_base)
|
|
||||||
{
|
|
||||||
info->stack_base = wine_anon_mmap( NULL, info->stack_size,
|
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
|
|
||||||
if (info->stack_base == (void *)-1) return -1;
|
|
||||||
}
|
|
||||||
pthread_attr_init( &attr );
|
pthread_attr_init( &attr );
|
||||||
pthread_attr_setstack( &attr, info->stack_base, info->stack_size );
|
pthread_attr_setstacksize( &attr, info->stack_size );
|
||||||
if (pthread_create( &id, &attr, (void * (*)(void *))info->entry, info )) return -1;
|
if (pthread_create( &id, &attr, (void * (*)(void *))info->entry, info )) ret = -1;
|
||||||
return 0;
|
pthread_attr_destroy( &attr );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* wine_pthread_get_current_teb
|
||||||
|
*/
|
||||||
|
void *wine_pthread_get_current_teb(void)
|
||||||
|
{
|
||||||
|
#ifdef __i386__
|
||||||
|
void *ret;
|
||||||
|
__asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret) );
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return pthread_getspecific( teb_key );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +159,6 @@ void wine_pthread_exit_thread( struct wine_pthread_thread_info *info )
|
||||||
{
|
{
|
||||||
pthread_join( free_info->self, &ptr );
|
pthread_join( free_info->self, &ptr );
|
||||||
wine_ldt_free_fs( free_info->thread_info.teb_sel );
|
wine_ldt_free_fs( free_info->thread_info.teb_sel );
|
||||||
munmap( free_info->thread_info.stack_base, free_info->thread_info.stack_size );
|
|
||||||
munmap( free_info->thread_info.teb_base, free_info->thread_info.teb_size );
|
munmap( free_info->thread_info.teb_base, free_info->thread_info.teb_size );
|
||||||
}
|
}
|
||||||
pthread_exit( (void *)info->exit_status );
|
pthread_exit( (void *)info->exit_status );
|
||||||
|
@ -115,6 +170,7 @@ void wine_pthread_exit_thread( struct wine_pthread_thread_info *info )
|
||||||
*/
|
*/
|
||||||
void wine_pthread_abort_thread( int status )
|
void wine_pthread_abort_thread( int status )
|
||||||
{
|
{
|
||||||
|
pthread_detach( pthread_self() ); /* no one will be joining with us */
|
||||||
pthread_exit( (void *)status );
|
pthread_exit( (void *)status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue