Moved the remaining SYSDEPS_* functions to the wine_pthread interface.

Let the pthread library allocate the stack itself.
This commit is contained in:
Alexandre Julliard 2003-11-09 01:25:23 +00:00
parent 8d0ac5574e
commit 50fba7ffec
11 changed files with 173 additions and 169 deletions

View File

@ -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 */

View File

@ -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 \

View File

@ -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 );

View File

@ -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];

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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 */

View File

@ -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 );

View File

@ -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
*/ */

View File

@ -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
*/ */

View File

@ -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 );
} }