Commit f1ef8a4d authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Add platform-specific versions of the thread data structure.

parent 6effc483
...@@ -529,6 +529,29 @@ enum i386_trap_code ...@@ -529,6 +529,29 @@ enum i386_trap_code
#endif #endif
}; };
struct x86_thread_data
{
DWORD dr0; /* 1bc Debug registers */
DWORD dr1; /* 1c0 */
DWORD dr2; /* 1c4 */
DWORD dr3; /* 1c8 */
DWORD dr6; /* 1cc */
DWORD dr7; /* 1d0 */
DWORD fs; /* 1d4 TEB selector */
DWORD gs; /* 1d8 libc selector; update winebuild if you move this! */
void *vm86_ptr; /* 1dc data for vm86 mode */
int __pad[7]; /* 1e0 space for ntdll_thread_data (FIXME) */
WINE_VM86_TEB_INFO vm86; /* 1fc vm86 private data */
void *exit_frame; /* 204 exit frame pointer */
};
C_ASSERT( offsetof( TEB, SpareBytes1 ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
static inline struct x86_thread_data *x86_thread_data(void)
{
return (struct x86_thread_data *)NtCurrentTeb()->SpareBytes1;
}
/* Exception record for handling exceptions happening inside exception handlers */ /* Exception record for handling exceptions happening inside exception handlers */
typedef struct typedef struct
{ {
...@@ -839,7 +862,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec ) ...@@ -839,7 +862,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
{ {
BOOL check_pending = TRUE; BOOL check_pending = TRUE;
struct vm86plus_struct *vm86 = struct vm86plus_struct *vm86 =
(struct vm86plus_struct*)(ntdll_get_thread_data()->vm86_ptr); (struct vm86plus_struct*)x86_thread_data()->vm86_ptr;
/* /*
* In order to prevent a race when SIGUSR2 occurs while * In order to prevent a race when SIGUSR2 occurs while
...@@ -849,7 +872,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec ) ...@@ -849,7 +872,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
while (check_pending && get_vm86_teb_info()->vm86_pending) while (check_pending && get_vm86_teb_info()->vm86_pending)
{ {
check_pending = FALSE; check_pending = FALSE;
ntdll_get_thread_data()->vm86_ptr = NULL; x86_thread_data()->vm86_ptr = NULL;
/* /*
* If VIF is set, throw exception. * If VIF is set, throw exception.
...@@ -875,7 +898,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec ) ...@@ -875,7 +898,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
check_pending = TRUE; check_pending = TRUE;
} }
ntdll_get_thread_data()->vm86_ptr = vm86; x86_thread_data()->vm86_ptr = vm86;
} }
/* /*
...@@ -908,11 +931,11 @@ static void (*libc_sigacthandler)( int signal, siginfo_t *siginfo, void *context ...@@ -908,11 +931,11 @@ static void (*libc_sigacthandler)( int signal, siginfo_t *siginfo, void *context
static void wine_sigacthandler( int signal, siginfo_t *siginfo, void *sigcontext ) static void wine_sigacthandler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
struct ntdll_thread_data *thread_data; struct x86_thread_data *thread_data;
__asm__ __volatile__("mov %ss,%ax; mov %ax,%ds; mov %ax,%es"); __asm__ __volatile__("mov %ss,%ax; mov %ax,%ds; mov %ax,%es");
thread_data = (struct ntdll_thread_data *)get_current_teb()->SpareBytes1; thread_data = (struct x86_thread_data *)get_current_teb()->SystemReserved2;
wine_set_fs( thread_data->fs ); wine_set_fs( thread_data->fs );
wine_set_gs( thread_data->gs ); wine_set_gs( thread_data->gs );
...@@ -974,7 +997,7 @@ static inline void *init_handler( const ucontext_t *sigcontext, WORD *fs, WORD * ...@@ -974,7 +997,7 @@ static inline void *init_handler( const ucontext_t *sigcontext, WORD *fs, WORD *
#ifndef __sun /* see above for Solaris handling */ #ifndef __sun /* see above for Solaris handling */
{ {
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
wine_set_fs( thread_data->fs ); wine_set_fs( thread_data->fs );
wine_set_gs( thread_data->gs ); wine_set_gs( thread_data->gs );
} }
...@@ -1099,7 +1122,6 @@ static void fpux_to_fpu( FLOATING_SAVE_AREA *fpu, const XMM_SAVE_AREA32 *fpux ) ...@@ -1099,7 +1122,6 @@ static void fpux_to_fpu( FLOATING_SAVE_AREA *fpu, const XMM_SAVE_AREA32 *fpux )
*/ */
static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext, WORD fs, WORD gs ) static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext, WORD fs, WORD gs )
{ {
struct ntdll_thread_data * const regs = ntdll_get_thread_data();
FLOATING_SAVE_AREA *fpu = FPU_sig(sigcontext); FLOATING_SAVE_AREA *fpu = FPU_sig(sigcontext);
XMM_SAVE_AREA32 *fpux = FPUX_sig(sigcontext); XMM_SAVE_AREA32 *fpux = FPUX_sig(sigcontext);
...@@ -1121,12 +1143,12 @@ static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext, ...@@ -1121,12 +1143,12 @@ static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext,
context->SegFs = fs; context->SegFs = fs;
context->SegGs = gs; context->SegGs = gs;
context->SegSs = LOWORD(SS_sig(sigcontext)); context->SegSs = LOWORD(SS_sig(sigcontext));
context->Dr0 = regs->dr0; context->Dr0 = x86_thread_data()->dr0;
context->Dr1 = regs->dr1; context->Dr1 = x86_thread_data()->dr1;
context->Dr2 = regs->dr2; context->Dr2 = x86_thread_data()->dr2;
context->Dr3 = regs->dr3; context->Dr3 = x86_thread_data()->dr3;
context->Dr6 = regs->dr6; context->Dr6 = x86_thread_data()->dr6;
context->Dr7 = regs->dr7; context->Dr7 = x86_thread_data()->dr7;
if (fpu) if (fpu)
{ {
...@@ -1151,16 +1173,15 @@ static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext, ...@@ -1151,16 +1173,15 @@ static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext,
*/ */
static inline void restore_context( const CONTEXT *context, ucontext_t *sigcontext ) static inline void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
{ {
struct ntdll_thread_data * const regs = ntdll_get_thread_data();
FLOATING_SAVE_AREA *fpu = FPU_sig(sigcontext); FLOATING_SAVE_AREA *fpu = FPU_sig(sigcontext);
XMM_SAVE_AREA32 *fpux = FPUX_sig(sigcontext); XMM_SAVE_AREA32 *fpux = FPUX_sig(sigcontext);
regs->dr0 = context->Dr0; x86_thread_data()->dr0 = context->Dr0;
regs->dr1 = context->Dr1; x86_thread_data()->dr1 = context->Dr1;
regs->dr2 = context->Dr2; x86_thread_data()->dr2 = context->Dr2;
regs->dr3 = context->Dr3; x86_thread_data()->dr3 = context->Dr3;
regs->dr6 = context->Dr6; x86_thread_data()->dr6 = context->Dr6;
regs->dr7 = context->Dr7; x86_thread_data()->dr7 = context->Dr7;
EAX_sig(sigcontext) = context->Eax; EAX_sig(sigcontext) = context->Eax;
EBX_sig(sigcontext) = context->Ebx; EBX_sig(sigcontext) = context->Ebx;
ECX_sig(sigcontext) = context->Ecx; ECX_sig(sigcontext) = context->Ecx;
...@@ -1239,12 +1260,12 @@ static void set_cpu_context( const CONTEXT *context ) ...@@ -1239,12 +1260,12 @@ static void set_cpu_context( const CONTEXT *context )
if (flags & CONTEXT_DEBUG_REGISTERS) if (flags & CONTEXT_DEBUG_REGISTERS)
{ {
ntdll_get_thread_data()->dr0 = context->Dr0; x86_thread_data()->dr0 = context->Dr0;
ntdll_get_thread_data()->dr1 = context->Dr1; x86_thread_data()->dr1 = context->Dr1;
ntdll_get_thread_data()->dr2 = context->Dr2; x86_thread_data()->dr2 = context->Dr2;
ntdll_get_thread_data()->dr3 = context->Dr3; x86_thread_data()->dr3 = context->Dr3;
ntdll_get_thread_data()->dr6 = context->Dr6; x86_thread_data()->dr6 = context->Dr6;
ntdll_get_thread_data()->dr7 = context->Dr7; x86_thread_data()->dr7 = context->Dr7;
} }
if (flags & CONTEXT_FULL) if (flags & CONTEXT_FULL)
{ {
...@@ -1471,12 +1492,12 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) ...@@ -1471,12 +1492,12 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
/* debug registers require a server call */ /* debug registers require a server call */
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))) if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
self = (ntdll_get_thread_data()->dr0 == context->Dr0 && self = (x86_thread_data()->dr0 == context->Dr0 &&
ntdll_get_thread_data()->dr1 == context->Dr1 && x86_thread_data()->dr1 == context->Dr1 &&
ntdll_get_thread_data()->dr2 == context->Dr2 && x86_thread_data()->dr2 == context->Dr2 &&
ntdll_get_thread_data()->dr3 == context->Dr3 && x86_thread_data()->dr3 == context->Dr3 &&
ntdll_get_thread_data()->dr6 == context->Dr6 && x86_thread_data()->dr6 == context->Dr6 &&
ntdll_get_thread_data()->dr7 == context->Dr7); x86_thread_data()->dr7 == context->Dr7);
if (!self) ret = set_thread_context( handle, context, &self ); if (!self) ret = set_thread_context( handle, context, &self );
...@@ -1516,12 +1537,12 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) ...@@ -1516,12 +1537,12 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
/* update the cached version of the debug registers */ /* update the cached version of the debug registers */
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))
{ {
ntdll_get_thread_data()->dr0 = context->Dr0; x86_thread_data()->dr0 = context->Dr0;
ntdll_get_thread_data()->dr1 = context->Dr1; x86_thread_data()->dr1 = context->Dr1;
ntdll_get_thread_data()->dr2 = context->Dr2; x86_thread_data()->dr2 = context->Dr2;
ntdll_get_thread_data()->dr3 = context->Dr3; x86_thread_data()->dr3 = context->Dr3;
ntdll_get_thread_data()->dr6 = context->Dr6; x86_thread_data()->dr6 = context->Dr6;
ntdll_get_thread_data()->dr7 = context->Dr7; x86_thread_data()->dr7 = context->Dr7;
} }
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
...@@ -1626,7 +1647,7 @@ static inline BOOL check_invalid_gs( CONTEXT *context ) ...@@ -1626,7 +1647,7 @@ static inline BOOL check_invalid_gs( CONTEXT *context )
{ {
unsigned int prefix_count = 0; unsigned int prefix_count = 0;
const BYTE *instr = (BYTE *)context->Eip; const BYTE *instr = (BYTE *)context->Eip;
WORD system_gs = ntdll_get_thread_data()->gs; WORD system_gs = x86_thread_data()->gs;
if (context->SegGs == system_gs) return FALSE; if (context->SegGs == system_gs) return FALSE;
if (!wine_ldt_is_system( context->SegCs )) return FALSE; if (!wine_ldt_is_system( context->SegCs )) return FALSE;
...@@ -2015,7 +2036,7 @@ static void WINAPI raise_trap_exception( EXCEPTION_RECORD *rec, CONTEXT *context ...@@ -2015,7 +2036,7 @@ static void WINAPI raise_trap_exception( EXCEPTION_RECORD *rec, CONTEXT *context
* single step interrupt. try to avoid as much overhead as possible * single step interrupt. try to avoid as much overhead as possible
* and only do a server call if there is any hw bp enabled. */ * and only do a server call if there is any hw bp enabled. */
if( !(context->EFlags & 0x100) || (ntdll_get_thread_data()->dr7 & 0xff) ) if( !(context->EFlags & 0x100) || (x86_thread_data()->dr7 & 0xff) )
{ {
/* (possible) hardware breakpoint, fetch the debug registers */ /* (possible) hardware breakpoint, fetch the debug registers */
DWORD saved_flags = context->ContextFlags; DWORD saved_flags = context->ContextFlags;
...@@ -2055,7 +2076,7 @@ static void WINAPI raise_vm86_sti_exception( EXCEPTION_RECORD *rec, CONTEXT *con ...@@ -2055,7 +2076,7 @@ static void WINAPI raise_vm86_sti_exception( EXCEPTION_RECORD *rec, CONTEXT *con
/* merge_vm86_pending_flags merges the vm86_pending flag in safely */ /* merge_vm86_pending_flags merges the vm86_pending flag in safely */
get_vm86_teb_info()->vm86_pending |= VIP_FLAG; get_vm86_teb_info()->vm86_pending |= VIP_FLAG;
if (ntdll_get_thread_data()->vm86_ptr) if (x86_thread_data()->vm86_ptr)
{ {
if (((char*)context->Eip >= (char*)vm86_return) && if (((char*)context->Eip >= (char*)vm86_return) &&
((char*)context->Eip <= (char*)vm86_return_end) && ((char*)context->Eip <= (char*)vm86_return_end) &&
...@@ -2378,7 +2399,7 @@ static void ldt_unlock(void) ...@@ -2378,7 +2399,7 @@ static void ldt_unlock(void)
NTSTATUS signal_alloc_thread( TEB **teb ) NTSTATUS signal_alloc_thread( TEB **teb )
{ {
static size_t sigstack_zero_bits; static size_t sigstack_zero_bits;
struct ntdll_thread_data *thread_data; struct x86_thread_data *thread_data;
SIZE_T size; SIZE_T size;
void *addr = NULL; void *addr = NULL;
NTSTATUS status; NTSTATUS status;
...@@ -2400,7 +2421,7 @@ NTSTATUS signal_alloc_thread( TEB **teb ) ...@@ -2400,7 +2421,7 @@ NTSTATUS signal_alloc_thread( TEB **teb )
*teb = addr; *teb = addr;
(*teb)->Tib.Self = &(*teb)->Tib; (*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL; (*teb)->Tib.ExceptionList = (void *)~0UL;
thread_data = (struct ntdll_thread_data *)(*teb)->SpareBytes1; thread_data = (struct x86_thread_data *)(*teb)->SystemReserved2;
if (!(thread_data->fs = wine_ldt_alloc_fs())) if (!(thread_data->fs = wine_ldt_alloc_fs()))
{ {
size = 0; size = 0;
...@@ -2418,7 +2439,7 @@ NTSTATUS signal_alloc_thread( TEB **teb ) ...@@ -2418,7 +2439,7 @@ NTSTATUS signal_alloc_thread( TEB **teb )
void signal_free_thread( TEB *teb ) void signal_free_thread( TEB *teb )
{ {
SIZE_T size; SIZE_T size;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
if (thread_data) wine_ldt_free_fs( thread_data->fs ); if (thread_data) wine_ldt_free_fs( thread_data->fs );
if (teb->DeallocationStack) if (teb->DeallocationStack)
...@@ -2437,7 +2458,7 @@ void signal_free_thread( TEB *teb ) ...@@ -2437,7 +2458,7 @@ void signal_free_thread( TEB *teb )
void signal_init_thread( TEB *teb ) void signal_init_thread( TEB *teb )
{ {
const WORD fpu_cw = 0x27f; const WORD fpu_cw = 0x27f;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemReserved2;
LDT_ENTRY fs_entry; LDT_ENTRY fs_entry;
stack_t ss; stack_t ss;
...@@ -2537,10 +2558,10 @@ void __wine_enter_vm86( CONTEXT *context ) ...@@ -2537,10 +2558,10 @@ void __wine_enter_vm86( CONTEXT *context )
{ {
restore_vm86_context( context, &vm86 ); restore_vm86_context( context, &vm86 );
ntdll_get_thread_data()->vm86_ptr = &vm86; x86_thread_data()->vm86_ptr = &vm86;
merge_vm86_pending_flags( &rec ); merge_vm86_pending_flags( &rec );
res = vm86_enter( &ntdll_get_thread_data()->vm86_ptr ); /* uses and clears teb->vm86_ptr */ res = vm86_enter( &x86_thread_data()->vm86_ptr ); /* uses and clears teb->vm86_ptr */
if (res < 0) if (res < 0)
{ {
errno = -res; errno = -res;
...@@ -2775,7 +2796,7 @@ __ASM_GLOBAL_FUNC(call_thread_func_wrapper, ...@@ -2775,7 +2796,7 @@ __ASM_GLOBAL_FUNC(call_thread_func_wrapper,
*/ */
void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame ) void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame )
{ {
ntdll_get_thread_data()->exit_frame = frame; x86_thread_data()->exit_frame = frame;
__TRY __TRY
{ {
call_thread_func_wrapper( entry, arg ); call_thread_func_wrapper( entry, arg );
...@@ -2793,8 +2814,8 @@ void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame ) ...@@ -2793,8 +2814,8 @@ void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame )
*/ */
void WINAPI RtlExitUserThread( ULONG status ) void WINAPI RtlExitUserThread( ULONG status )
{ {
if (!ntdll_get_thread_data()->exit_frame) exit_thread( status ); if (!x86_thread_data()->exit_frame) exit_thread( status );
call_thread_exit_func( status, exit_thread, ntdll_get_thread_data()->exit_frame ); call_thread_exit_func( status, exit_thread, x86_thread_data()->exit_frame );
} }
/*********************************************************************** /***********************************************************************
...@@ -2802,8 +2823,8 @@ void WINAPI RtlExitUserThread( ULONG status ) ...@@ -2802,8 +2823,8 @@ void WINAPI RtlExitUserThread( ULONG status )
*/ */
void abort_thread( int status ) void abort_thread( int status )
{ {
if (!ntdll_get_thread_data()->exit_frame) terminate_thread( status ); if (!x86_thread_data()->exit_frame) terminate_thread( status );
call_thread_exit_func( status, terminate_thread, ntdll_get_thread_data()->exit_frame ); call_thread_exit_func( status, terminate_thread, x86_thread_data()->exit_frame );
} }
/********************************************************************** /**********************************************************************
......
...@@ -308,6 +308,18 @@ typedef int (*wine_signal_handler)(unsigned int sig); ...@@ -308,6 +308,18 @@ typedef int (*wine_signal_handler)(unsigned int sig);
static wine_signal_handler handlers[256]; static wine_signal_handler handlers[256];
struct amd64_thread_data
{
void *exit_frame; /* exit frame pointer */
};
C_ASSERT( sizeof(struct amd64_thread_data) <= sizeof(((TEB *)0)->SpareBytes1) );
static inline struct amd64_thread_data *amd64_thread_data(void)
{
return (struct amd64_thread_data *)NtCurrentTeb()->SpareBytes1;
}
/*********************************************************************** /***********************************************************************
* Dynamic unwind table * Dynamic unwind table
*/ */
...@@ -3992,7 +4004,7 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ...@@ -3992,7 +4004,7 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
*/ */
void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame ) void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame )
{ {
ntdll_get_thread_data()->exit_frame = frame; amd64_thread_data()->exit_frame = frame;
__TRY __TRY
{ {
RtlExitUserThread( entry( arg )); RtlExitUserThread( entry( arg ));
...@@ -4041,8 +4053,8 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func, ...@@ -4041,8 +4053,8 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
*/ */
void WINAPI RtlExitUserThread( ULONG status ) void WINAPI RtlExitUserThread( ULONG status )
{ {
if (!ntdll_get_thread_data()->exit_frame) exit_thread( status ); if (!amd64_thread_data()->exit_frame) exit_thread( status );
call_thread_exit_func( status, exit_thread, ntdll_get_thread_data()->exit_frame ); call_thread_exit_func( status, exit_thread, amd64_thread_data()->exit_frame );
} }
/*********************************************************************** /***********************************************************************
...@@ -4050,8 +4062,8 @@ void WINAPI RtlExitUserThread( ULONG status ) ...@@ -4050,8 +4062,8 @@ void WINAPI RtlExitUserThread( ULONG status )
*/ */
void abort_thread( int status ) void abort_thread( int status )
{ {
if (!ntdll_get_thread_data()->exit_frame) terminate_thread( status ); if (!amd64_thread_data()->exit_frame) terminate_thread( status );
call_thread_exit_func( status, terminate_thread, ntdll_get_thread_data()->exit_frame ); call_thread_exit_func( status, terminate_thread, amd64_thread_data()->exit_frame );
} }
/********************************************************************** /**********************************************************************
......
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