Commit ab29aa21 authored by Alexandre Julliard's avatar Alexandre Julliard

Moved the ntdll per-thread data out of the TEB into a private

structure stored in TEB.SystemReserved2.
parent 0f079d78
......@@ -35,9 +35,9 @@
#include "wine/library.h"
#include "wine/unicode.h"
#include "ntstatus.h"
#include "thread.h"
#include "winbase.h"
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
#include "excpt.h"
#include "ntdll_misc.h"
......@@ -57,7 +57,7 @@ static WINE_EXCEPTION_FILTER(page_fault)
/* get the debug info pointer for the current thread */
static inline struct debug_info *get_info(void)
{
return NtCurrentTeb()->debug_info;
return ntdll_get_thread_data()->debug_info;
}
/* allocate some tmp space for a string */
......@@ -74,7 +74,7 @@ static void *gimme1(int n)
/* release extra space that we requested in gimme1() */
static inline void release( void *ptr )
{
struct debug_info *info = NtCurrentTeb()->debug_info;
struct debug_info *info = get_info();
info->str_pos = ptr;
}
......
......@@ -100,4 +100,29 @@ extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst,
extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, int dstlen,
const char* defchar, int *used );
struct debug_info
{
char *str_pos; /* current position in strings buffer */
char *out_pos; /* current position in output buffer */
char strings[1024]; /* buffer for temporary strings */
char output[1024]; /* current output line */
};
struct ntdll_thread_data
{
DWORD teb_sel; /* selector to TEB */
struct debug_info *debug_info; /* info for debugstr functions */
int request_fd; /* fd for sending server requests */
int reply_fd; /* fd for receiving server replies */
int wait_fd[2]; /* fd for sleeping server requests */
void *vm86_ptr; /* data for vm86 mode */
void *pad[3]; /* change this if you add fields! */
};
static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
{
return (struct ntdll_thread_data *)NtCurrentTeb()->SystemReserved2;
}
#endif
......@@ -54,7 +54,6 @@
#endif
#include "ntstatus.h"
#include "thread.h"
#include "wine/library.h"
#include "wine/pthread.h"
#include "wine/server.h"
......@@ -144,10 +143,10 @@ void wine_server_exit_thread( int status )
info.teb_size = size;
sigprocmask( SIG_BLOCK, &block_set, NULL );
close( NtCurrentTeb()->wait_fd[0] );
close( NtCurrentTeb()->wait_fd[1] );
close( NtCurrentTeb()->reply_fd );
close( NtCurrentTeb()->request_fd );
close( ntdll_get_thread_data()->wait_fd[0] );
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 );
}
......@@ -158,10 +157,10 @@ void wine_server_exit_thread( int status )
void server_abort_thread( int status )
{
sigprocmask( SIG_BLOCK, &block_set, NULL );
close( NtCurrentTeb()->wait_fd[0] );
close( NtCurrentTeb()->wait_fd[1] );
close( NtCurrentTeb()->reply_fd );
close( NtCurrentTeb()->request_fd );
close( ntdll_get_thread_data()->wait_fd[0] );
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 );
}
......@@ -204,7 +203,7 @@ static void send_request( const struct __server_request_info *req )
if (!req->u.req.request_header.request_size)
{
if ((ret = write( NtCurrentTeb()->request_fd, &req->u.req,
if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req,
sizeof(req->u.req) )) == sizeof(req->u.req)) return;
}
......@@ -219,7 +218,7 @@ static void send_request( const struct __server_request_info *req )
vec[i+1].iov_base = (void *)req->data[i].ptr;
vec[i+1].iov_len = req->data[i].size;
}
if ((ret = writev( NtCurrentTeb()->request_fd, vec, i+1 )) ==
if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) ==
req->u.req.request_header.request_size + sizeof(req->u.req)) return;
}
......@@ -240,7 +239,7 @@ static void read_reply_data( void *buffer, size_t size )
for (;;)
{
if ((ret = read( NtCurrentTeb()->reply_fd, buffer, size )) > 0)
if ((ret = read( ntdll_get_thread_data()->reply_fd, buffer, size )) > 0)
{
if (!(size -= ret)) return;
buffer = (char *)buffer + ret;
......@@ -866,7 +865,7 @@ void server_init_process(void)
sigaddset( &block_set, SIGCHLD );
/* receive the first thread request fd on the main socket */
NtCurrentTeb()->request_fd = receive_fd( &dummy_handle );
ntdll_get_thread_data()->request_fd = receive_fd( &dummy_handle );
}
......@@ -877,7 +876,6 @@ void server_init_process(void)
*/
void server_init_thread( int unix_pid, int unix_tid, void *entry_point )
{
TEB *teb = NtCurrentTeb();
int version, ret;
int reply_pipe[2];
struct sigaction sig_act;
......@@ -896,28 +894,28 @@ void server_init_thread( int unix_pid, int unix_tid, void *entry_point )
/* create the server->client communication pipes */
if (pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
if (pipe( teb->wait_fd ) == -1) server_protocol_perror( "pipe" );
if (pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
wine_server_send_fd( reply_pipe[1] );
wine_server_send_fd( teb->wait_fd[1] );
teb->reply_fd = reply_pipe[0];
wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
ntdll_get_thread_data()->reply_fd = reply_pipe[0];
close( reply_pipe[1] );
/* set close on exec flag */
fcntl( teb->reply_fd, F_SETFD, 1 );
fcntl( teb->wait_fd[0], F_SETFD, 1 );
fcntl( teb->wait_fd[1], F_SETFD, 1 );
fcntl( ntdll_get_thread_data()->reply_fd, F_SETFD, 1 );
fcntl( ntdll_get_thread_data()->wait_fd[0], F_SETFD, 1 );
fcntl( ntdll_get_thread_data()->wait_fd[1], F_SETFD, 1 );
SERVER_START_REQ( init_thread )
{
req->unix_pid = unix_pid;
req->unix_tid = unix_tid;
req->teb = teb;
req->teb = NtCurrentTeb();
req->entry = entry_point;
req->reply_fd = reply_pipe[1];
req->wait_fd = teb->wait_fd[1];
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
ret = wine_server_call( req );
teb->ClientId.UniqueProcess = (HANDLE)reply->pid;
teb->ClientId.UniqueThread = (HANDLE)reply->tid;
NtCurrentTeb()->ClientId.UniqueProcess = (HANDLE)reply->pid;
NtCurrentTeb()->ClientId.UniqueThread = (HANDLE)reply->tid;
version = reply->version;
}
SERVER_END_REQ;
......
......@@ -584,7 +584,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
{
BOOL check_pending = TRUE;
struct vm86plus_struct *vm86 =
(struct vm86plus_struct*)(NtCurrentTeb()->vm86_ptr);
(struct vm86plus_struct*)(ntdll_get_thread_data()->vm86_ptr);
/*
* In order to prevent a race when SIGUSR2 occurs while
......@@ -594,7 +594,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
while (check_pending && NtCurrentTeb()->vm86_pending)
{
check_pending = FALSE;
NtCurrentTeb()->vm86_ptr = NULL;
ntdll_get_thread_data()->vm86_ptr = NULL;
/*
* If VIF is set, throw exception.
......@@ -620,7 +620,7 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
check_pending = TRUE;
}
NtCurrentTeb()->vm86_ptr = vm86;
ntdll_get_thread_data()->vm86_ptr = vm86;
}
/*
......@@ -645,8 +645,9 @@ static void *init_handler( const SIGCONTEXT *sigcontext )
{
void *stack = (void *)ESP_sig(sigcontext);
TEB *teb = get_current_teb();
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
wine_set_fs( teb->teb_sel );
wine_set_fs( thread_data->teb_sel );
/* now restore a proper %gs for the fault handler */
if (!wine_ldt_is_system(CS_sig(sigcontext)) ||
......@@ -949,7 +950,7 @@ static void WINAPI raise_vm86_sti_exception( EXCEPTION_RECORD *rec, CONTEXT *con
/* merge_vm86_pending_flags merges the vm86_pending flag in safely */
NtCurrentTeb()->vm86_pending |= VIP_MASK;
if (NtCurrentTeb()->vm86_ptr)
if (ntdll_get_thread_data()->vm86_ptr)
{
if (((char*)context->Eip >= (char*)vm86_return) &&
((char*)context->Eip <= (char*)vm86_return_end) &&
......@@ -1268,7 +1269,6 @@ BOOL SIGNAL_Init(void)
void __wine_enter_vm86( CONTEXT *context )
{
EXCEPTION_RECORD rec;
TEB *teb = NtCurrentTeb();
int res;
struct vm86plus_struct vm86;
......@@ -1277,10 +1277,10 @@ void __wine_enter_vm86( CONTEXT *context )
{
restore_vm86_context( context, &vm86 );
teb->vm86_ptr = &vm86;
ntdll_get_thread_data()->vm86_ptr = &vm86;
merge_vm86_pending_flags( &rec );
res = vm86_enter( &teb->vm86_ptr ); /* uses and clears teb->vm86_ptr */
res = vm86_enter( &ntdll_get_thread_data()->vm86_ptr ); /* uses and clears teb->vm86_ptr */
if (res < 0)
{
errno = -res;
......@@ -1323,7 +1323,7 @@ void __wine_enter_vm86( CONTEXT *context )
case VM86_STI: /* sti/popf/iret instruction enabled virtual interrupts */
context->EFlags |= VIF_MASK;
context->EFlags &= ~VIP_MASK;
teb->vm86_pending = 0;
NtCurrentTeb()->vm86_pending = 0;
rec.ExceptionCode = EXCEPTION_VM86_STI;
break;
case VM86_PICRETURN: /* return due to pending PIC request */
......
......@@ -616,7 +616,7 @@ static int wait_reply( void *cookie )
for (;;)
{
int ret;
ret = read( NtCurrentTeb()->wait_fd[0], &reply, sizeof(reply) );
ret = read( ntdll_get_thread_data()->wait_fd[0], &reply, sizeof(reply) );
if (ret == sizeof(reply))
{
if (!reply.cookie) break; /* thread got killed */
......@@ -626,7 +626,7 @@ static int wait_reply( void *cookie )
/* and now put the wrong one back in the pipe */
for (;;)
{
ret = write( NtCurrentTeb()->wait_fd[1], &reply, sizeof(reply) );
ret = write( ntdll_get_thread_data()->wait_fd[1], &reply, sizeof(reply) );
if (ret == sizeof(reply)) break;
if (ret >= 0) server_protocol_error( "partial wakeup write %d\n", ret );
if (errno == EINTR) continue;
......
......@@ -59,11 +59,13 @@ static LIST_ENTRY tls_links;
static TEB *alloc_teb( ULONG *size )
{
TEB *teb;
struct ntdll_thread_data *thread_data;
*size = SIGNAL_STACK_SIZE + sizeof(TEB);
teb = wine_anon_mmap( NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
if (teb == (TEB *)-1) return NULL;
if (!(teb->teb_sel = wine_ldt_alloc_fs()))
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
if (!(thread_data->teb_sel = wine_ldt_alloc_fs()))
{
munmap( teb, *size );
return NULL;
......@@ -85,9 +87,10 @@ static inline void free_teb( TEB *teb )
{
ULONG size = 0;
void *addr = teb;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
wine_ldt_free_fs( teb->teb_sel );
wine_ldt_free_fs( thread_data->teb_sel );
munmap( teb, SIGNAL_STACK_SIZE + sizeof(TEB) );
}
......@@ -104,6 +107,7 @@ void thread_init(void)
TEB *teb;
void *addr;
ULONG size;
struct ntdll_thread_data *thread_data;
struct wine_pthread_thread_info thread_info;
static struct debug_info debug_info; /* debug info for initial thread */
......@@ -121,18 +125,19 @@ void thread_init(void)
InitializeListHead( &tls_links );
teb = alloc_teb( &size );
teb->request_fd = -1;
teb->reply_fd = -1;
teb->wait_fd[0] = -1;
teb->wait_fd[1] = -1;
teb->debug_info = &debug_info;
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->request_fd = -1;
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
thread_data->debug_info = &debug_info;
InsertHeadList( &tls_links, &teb->TlsLinks );
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;
thread_info.teb_sel = thread_data->teb_sel;
wine_pthread_init_current_teb( &thread_info );
wine_pthread_init_thread( &thread_info );
......@@ -167,6 +172,7 @@ void thread_init(void)
static void start_thread( struct wine_pthread_thread_info *info )
{
TEB *teb = info->teb_base;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
struct startup_info *startup_info = (struct startup_info *)info;
PRTL_THREAD_START_ROUTINE func = startup_info->entry_point;
void *arg = startup_info->entry_arg;
......@@ -175,7 +181,7 @@ static void start_thread( struct wine_pthread_thread_info *info )
debug_info.str_pos = debug_info.strings;
debug_info.out_pos = debug_info.output;
teb->debug_info = &debug_info;
thread_data->debug_info = &debug_info;
wine_pthread_init_current_teb( info );
SIGNAL_Init();
......@@ -214,6 +220,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
PRTL_THREAD_START_ROUTINE start, void *param,
HANDLE *handle_ptr, CLIENT_ID *id )
{
struct ntdll_thread_data *thread_data;
struct startup_info *info = NULL;
HANDLE handle = 0;
TEB *teb = NULL;
......@@ -262,16 +269,17 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
teb->ClientId.UniqueThread = (HANDLE)tid;
teb->request_fd = request_pipe[1];
teb->reply_fd = -1;
teb->wait_fd[0] = -1;
teb->wait_fd[1] = -1;
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->request_fd = request_pipe[1];
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
info->pthread_info.teb_base = teb;
NtAllocateVirtualMemory( NtCurrentProcess(), &info->pthread_info.teb_base, 0, &size,
MEM_SYSTEM, PAGE_EXECUTE_READWRITE );
info->pthread_info.teb_size = size;
info->pthread_info.teb_sel = teb->teb_sel;
info->pthread_info.teb_sel = thread_data->teb_sel;
if (!stack_reserve || !stack_commit)
{
......
......@@ -28,30 +28,6 @@
#define WINE_NO_TEB
#include <winternl.h>
struct tagSYSLEVEL;
struct debug_info
{
char *str_pos; /* current position in strings buffer */
char *out_pos; /* current position in output buffer */
char strings[1024]; /* buffer for temporary strings */
char output[1024]; /* current output line */
};
/* Thread exception block
flags in the comment:
1-- win95 field
d-- win95 debug version
-2- nt field
--3 wine special
--n wine unused
!-- or -!- likely or observed collision
more problems (collected from mailing list):
psapi.dll 0x10/0x30 (expects nt fields)
ie4 0x40
PESHiELD 0x23/0x30 (win95)
*/
#ifndef WINE_TEB_DEFINED
#define WINE_TEB_DEFINED
typedef struct _TEB
......@@ -68,44 +44,45 @@ typedef struct _TEB
PVOID Win32ThreadInfo; /* 040 */
ULONG Win32ClientInfo[0x1f]; /* 044 */
PVOID WOW32Reserved; /* 0c0 */
ULONG CurrentLocale; /* -2- C4 */
DWORD pad5[48]; /* --n C8 */
DWORD delta_priority; /* 1-n 188 Priority delta */
DWORD unknown4[7]; /* d-n 18c Unknown */
void *create_data; /* d-n 1a8 Pointer to creation structure */
DWORD suspend_count; /* d-n 1ac SuspendThread() counter */
DWORD unknown5[6]; /* --n 1b0 Unknown */
DWORD sys_count[4]; /* --3 1c8 Syslevel mutex entry counters */
struct tagSYSLEVEL *sys_mutex[4]; /* --3 1d8 Syslevel mutex pointers */
DWORD unknown6[5]; /* --n 1e8 Unknown */
ULONG CurrentLocale; /* 0c4 */
ULONG FpSoftwareStatusRegister; /* 0c8 */
PVOID SystemReserved1[54]; /* 0cc */
PVOID Spare1; /* 1a4 */
LONG ExceptionCode; /* 1a8 */
BYTE SpareBytes1[40]; /* 1ac */
PVOID SystemReserved2[10]; /* 1d4 */
/* The following are Wine-specific fields (NT: GDI stuff) */
DWORD unused_1fc; /* --3 1fc */
UINT code_page; /* --3 200 Thread code page */
DWORD teb_sel; /* --3 204 Selector to TEB */
DWORD gs_sel; /* --3 208 %gs selector for this thread */
int request_fd; /* --3 20c fd for sending server requests */
int reply_fd; /* --3 210 fd for receiving server replies */
int wait_fd[2]; /* --3 214 fd for sleeping server requests */
struct debug_info *debug_info; /* --3 21c Info for debugstr functions */
void *pthread_data; /* --3 220 Data for pthread emulation */
DWORD num_async_io; /* --3 224 number of pending async I/O in the server */
void *driver_data; /* --3 228 Graphics driver private data */
DWORD dpmi_vif; /* --3 22c Protected mode virtual interrupt flag */
DWORD vm86_pending; /* --3 230 Data for vm86 mode */
void *vm86_ptr; /* --3 234 Data for vm86 mode */
WORD stack_sel; /* --3 238 16-bit stack selector */
WORD htask16; /* --3 23a Win16 task handle */
/* The following are Wine-specific fields (NT: GdiTebBatch) */
DWORD gs_sel; /* 1fc %gs selector for this thread */
DWORD num_async_io; /* 200 number of pending async I/O in the server */
DWORD dpmi_vif; /* 204 protected mode virtual interrupt flag */
DWORD vm86_pending; /* 208 data for vm86 mode */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
DWORD pad6[308]; /* 20c */
/* the following are nt specific fields */
DWORD pad6[622]; /* --n 23c */
ULONG LastStatusValue; /* -2- bf4 */
UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */
WCHAR StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */
PVOID DeallocationStack; /* -2- e0c Base of the stack */
LPVOID TlsSlots[64]; /* -2- e10 Thread local storage */
LIST_ENTRY TlsLinks; /* -2- f10 */
ULONG gdiRgn; /* 6dc */
ULONG gdiPen; /* 6e0 */
ULONG gdiBrush; /* 6e4 */
CLIENT_ID RealClientId; /* 6e8 */
HANDLE GdiCachedProcessHandle; /* 6f0 */
ULONG GdiClientPID; /* 6f4 */
ULONG GdiClientTID; /* 6f8 */
PVOID GdiThreadLocaleInfo; /* 6fc */
PVOID UserReserved[5]; /* 700 */
PVOID glDispachTable[280]; /* 714 */
ULONG glReserved1[26]; /* b74 */
PVOID glReserved2; /* bdc */
PVOID glSectionInfo; /* be0 */
PVOID glSection; /* be4 */
PVOID glTable; /* be8 */
PVOID glCurrentRC; /* bec */
PVOID glContext; /* bf0 */
ULONG LastStatusValue; /* bf4 */
UNICODE_STRING StaticUnicodeString; /* bf8 */
WCHAR StaticUnicodeBuffer[261]; /* c00 */
PVOID DeallocationStack; /* e0c */
PVOID TlsSlots[64]; /* e10 */
LIST_ENTRY TlsLinks; /* f10 */
PVOID Vdm; /* f18 */
PVOID ReservedForNtRpc; /* f1c */
PVOID DbgSsReserved[2]; /* f20 */
......@@ -137,7 +114,4 @@ typedef struct
WCHAR curdir_buffer[MAX_PATH];
} WIN16_SUBSYSTEM_TIB;
/* scheduler/thread.c */
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
#endif /* __WINE_THREAD_H */
......@@ -228,15 +228,15 @@ typedef struct _TEB
ULONG CountOfOwnedCriticalSections;/* 038 */
PVOID CsrClientThread; /* 03c */
PVOID Win32ThreadInfo; /* 040 */
ULONG Win32ClientInfo[31]; /* 044 */
ULONG Win32ClientInfo[31]; /* 044 used for user32 private data in Wine */
PVOID WOW32Reserved; /* 0c0 */
ULONG CurrentLocale; /* 0c4 */
ULONG FpSoftwareStatusRegister; /* 0c8 */
PVOID SystemReserved1[54]; /* 0cc */
PVOID SystemReserved1[54]; /* 0cc used for kernel32 private data in Wine */
PVOID Spare1; /* 1a4 */
LONG ExceptionCode; /* 1a8 */
BYTE SpareBytes1[40]; /* 1ac */
PVOID SystemReserved2[10]; /* 1d4 */
PVOID SystemReserved2[10]; /* 1d4 used for ntdll private data in Wine */
GDI_TEB_BATCH GdiTebBatch; /* 1fc */
ULONG gdiRgn; /* 6dc */
ULONG gdiPen; /* 6e0 */
......@@ -271,7 +271,7 @@ typedef struct _TEB
ULONG Spare2; /* f74 */
ULONG Spare3; /* f78 */
ULONG Spare4; /* f7c */
PVOID ReservedForOle; /* f80 Windows 2000 only */
PVOID ReservedForOle; /* f80 */
ULONG WaitingOnLoaderLock; /* f84 */
PVOID Reserved5[3]; /* f88 */
PVOID *TlsExpansionSlots; /* f94 */
......
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