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 =
|
||||
{
|
||||
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 */
|
||||
|
|
|
@ -36,7 +36,6 @@ C_SRCS = \
|
|||
signal_sparc.c \
|
||||
string.c \
|
||||
sync.c \
|
||||
sysdeps.c \
|
||||
version.c \
|
||||
thread.c \
|
||||
time.c \
|
||||
|
|
|
@ -52,7 +52,7 @@ extern void thread_init(void);
|
|||
|
||||
/* server support */
|
||||
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_perror( const char *err );
|
||||
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.
|
||||
*/
|
||||
void server_init_thread(void)
|
||||
void server_init_thread( int unix_pid, int unix_tid )
|
||||
{
|
||||
TEB *teb = NtCurrentTeb();
|
||||
int version, ret;
|
||||
|
@ -700,8 +700,8 @@ void server_init_thread(void)
|
|||
|
||||
SERVER_START_REQ( init_thread )
|
||||
{
|
||||
req->unix_pid = getpid();
|
||||
req->unix_tid = SYSDEPS_GetUnixTid();
|
||||
req->unix_pid = unix_pid;
|
||||
req->unix_tid = unix_tid;
|
||||
req->teb = teb;
|
||||
req->entry = teb->entry_point;
|
||||
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;
|
||||
void *addr;
|
||||
ULONG size;
|
||||
struct wine_pthread_thread_info thread_info;
|
||||
static struct debug_info debug_info; /* debug info for initial thread */
|
||||
|
||||
debug_info.str_pos = debug_info.strings;
|
||||
|
@ -118,11 +119,16 @@ void thread_init(void)
|
|||
teb->debug_info = &debug_info;
|
||||
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 */
|
||||
server_init_process();
|
||||
server_init_thread();
|
||||
server_init_thread( thread_info.pid, thread_info.tid );
|
||||
|
||||
/* create a memory view for the TEB */
|
||||
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;
|
||||
teb->debug_info = &debug_info;
|
||||
|
||||
SYSDEPS_SetCurThread( teb );
|
||||
wine_pthread_init_thread( info );
|
||||
SIGNAL_Init();
|
||||
server_init_thread();
|
||||
server_init_thread( info->pid, info->tid );
|
||||
|
||||
/* allocate a memory view for the stack */
|
||||
size = info->stack_size;
|
||||
|
@ -540,3 +546,18 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
|
|||
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 */
|
||||
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 */
|
||||
|
|
|
@ -37,6 +37,7 @@ typedef void *pthread_rwlockattr_t;
|
|||
|
||||
struct wine_pthread_functions
|
||||
{
|
||||
size_t size;
|
||||
void * (*ptr_get_thread_data)(void);
|
||||
void (*ptr_set_thread_data)(void *data);
|
||||
pthread_t (*ptr_pthread_self)(void);
|
||||
|
@ -85,18 +86,21 @@ struct wine_pthread_functions
|
|||
/* thread information used to creating and exiting threads */
|
||||
struct wine_pthread_thread_info
|
||||
{
|
||||
void *stack_base;
|
||||
size_t stack_size;
|
||||
void *teb_base;
|
||||
size_t teb_size;
|
||||
unsigned short teb_sel;
|
||||
void (*entry)( struct wine_pthread_thread_info *info );
|
||||
int exit_status;
|
||||
void *stack_base; /* base address of the stack */
|
||||
size_t stack_size; /* size of the stack */
|
||||
void *teb_base; /* base address of the TEB */
|
||||
size_t teb_size; /* size of the TEB (possibly including signal stack) */
|
||||
unsigned short teb_sel; /* selector to use for TEB */
|
||||
int pid; /* Unix process id */
|
||||
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_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 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 );
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void wine_pthread_init_process( const struct wine_pthread_functions *functions )
|
|||
/***********************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* wine_pthread_get_current_teb
|
||||
*/
|
||||
void *wine_pthread_get_current_teb(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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 )
|
||||
{
|
||||
memcpy( &funcs, functions, sizeof(funcs) );
|
||||
memcpy( &funcs, functions, min(functions->size,sizeof(funcs)) );
|
||||
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.
|
||||
*/
|
||||
void wine_pthread_init_thread(void)
|
||||
void wine_pthread_init_thread( struct wine_pthread_thread_info *info )
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,25 @@
|
|||
#include "wine/library.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
|
||||
*
|
||||
|
@ -45,6 +64,7 @@
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
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_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_setstack( &attr, info->stack_base, info->stack_size );
|
||||
if (pthread_create( &id, &attr, (void * (*)(void *))info->entry, info )) return -1;
|
||||
return 0;
|
||||
pthread_attr_setstacksize( &attr, info->stack_size );
|
||||
if (pthread_create( &id, &attr, (void * (*)(void *))info->entry, info )) ret = -1;
|
||||
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 );
|
||||
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 );
|
||||
}
|
||||
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 )
|
||||
{
|
||||
pthread_detach( pthread_self() ); /* no one will be joining with us */
|
||||
pthread_exit( (void *)status );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue