Merged THDB and TEB structures. Made SetLastError(), GetCurrentThreadId() and PROCESS_Current() inline.
diff --git a/scheduler/thread.c b/scheduler/thread.c index d86295a..85efaf9 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c
@@ -8,6 +8,7 @@ #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/mman.h> #include <unistd.h> #include "wine/winbase16.h" #include "thread.h" @@ -28,40 +29,40 @@ DEFAULT_DEBUG_CHANNEL(thread) -/* THDB of the initial thread */ -static THDB initial_thdb; +/* TEB of the initial thread */ +static TEB initial_teb; /* Global thread list (FIXME: not thread-safe) */ -THDB *THREAD_First = &initial_thdb; +TEB *THREAD_First = &initial_teb; /*********************************************************************** * THREAD_IsWin16 */ -BOOL THREAD_IsWin16( THDB *thdb ) +BOOL THREAD_IsWin16( TEB *teb ) { - return !thdb || !(thdb->teb.flags & TEBF_WIN32); + return !teb || !(teb->flags & TEBF_WIN32); } /*********************************************************************** - * THREAD_IdToTHDB + * THREAD_IdToTEB * - * Convert a thread id to a THDB, making sure it is valid. + * Convert a thread id to a TEB, making sure it is valid. */ -THDB *THREAD_IdToTHDB( DWORD id ) +TEB *THREAD_IdToTEB( DWORD id ) { - THDB *thdb = THREAD_First; + TEB *teb = THREAD_First; - if (!id) return THREAD_Current(); - while (thdb) + if (!id) return NtCurrentTeb(); + while (teb) { - if ((DWORD)thdb->teb.tid == id) return thdb; - thdb = thdb->next; + if ((DWORD)teb->tid == id) return teb; + teb = teb->next; } /* Allow task handles to be used; convert to main thread */ if ( IsTask16( id ) ) { TDB *pTask = (TDB *)GlobalLock16( id ); - if (pTask) return pTask->thdb; + if (pTask) return pTask->teb; } SetLastError( ERROR_INVALID_PARAMETER ); return NULL; @@ -69,12 +70,12 @@ /*********************************************************************** - * THREAD_InitTHDB + * THREAD_InitTEB * - * Initialization of a newly created THDB. + * Initialization of a newly created TEB. */ -static BOOL THREAD_InitTHDB( THDB *thdb, DWORD stack_size, BOOL alloc_stack16, - LPSECURITY_ATTRIBUTES sa ) +static BOOL THREAD_InitTEB( TEB *teb, DWORD stack_size, BOOL alloc_stack16, + LPSECURITY_ATTRIBUTES sa ) { DWORD old_prot; @@ -92,71 +93,71 @@ stack_size = 1024 * 1024; if (stack_size >= 16*1024*1024) WARN("Thread stack size is %ld MB.\n",stack_size/1024/1024); - thdb->stack_base = VirtualAlloc(NULL, stack_size + SIGNAL_STACK_SIZE + - (alloc_stack16 ? 0x10000 : 0), - MEM_COMMIT, PAGE_EXECUTE_READWRITE ); - if (!thdb->stack_base) goto error; + teb->stack_base = VirtualAlloc(NULL, stack_size + SIGNAL_STACK_SIZE + + (alloc_stack16 ? 0x10000 : 0), + MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if (!teb->stack_base) goto error; /* Set a guard page at the bottom of the stack */ - VirtualProtect( thdb->stack_base, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, - &old_prot ); - thdb->teb.stack_top = (char *)thdb->stack_base + stack_size; - thdb->teb.stack_low = thdb->stack_base; - thdb->signal_stack = thdb->teb.stack_top; /* start of signal stack */ + VirtualProtect( teb->stack_base, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot ); + teb->stack_top = (char *)teb->stack_base + stack_size; + teb->stack_low = teb->stack_base; + teb->signal_stack = teb->stack_top; /* start of signal stack */ /* Allocate the 16-bit stack selector */ if (alloc_stack16) { - thdb->teb.stack_sel = SELECTOR_AllocBlock( thdb->teb.stack_top, - 0x10000, SEGMENT_DATA, - FALSE, FALSE ); - if (!thdb->teb.stack_sel) goto error; - thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( thdb->teb.stack_sel, - 0x10000 - sizeof(STACK16FRAME) ); - thdb->signal_stack = (char *)thdb->signal_stack + 0x10000; + teb->stack_sel = SELECTOR_AllocBlock( teb->stack_top, 0x10000, SEGMENT_DATA, + FALSE, FALSE ); + if (!teb->stack_sel) goto error; + teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( teb->stack_sel, + 0x10000 - sizeof(STACK16FRAME) ); + teb->signal_stack = (char *)teb->signal_stack + 0x10000; } /* Create the thread event */ - if (!(thdb->event = CreateEventA( NULL, FALSE, FALSE, NULL ))) goto error; - thdb->event = ConvertToGlobalHandle( thdb->event ); + if (!(teb->event = CreateEventA( NULL, FALSE, FALSE, NULL ))) goto error; + teb->event = ConvertToGlobalHandle( teb->event ); return TRUE; error: - if (thdb->event) CloseHandle( thdb->event ); - if (thdb->teb.stack_sel) SELECTOR_FreeBlock( thdb->teb.stack_sel, 1 ); - if (thdb->stack_base) VirtualFree( thdb->stack_base, 0, MEM_RELEASE ); + if (teb->event) CloseHandle( teb->event ); + if (teb->stack_sel) SELECTOR_FreeBlock( teb->stack_sel, 1 ); + if (teb->stack_base) VirtualFree( teb->stack_base, 0, MEM_RELEASE ); return FALSE; } /*********************************************************************** - * THREAD_FreeTHDB + * THREAD_FreeTEB * * Free data structures associated with a thread. * Must be called from the context of another thread. */ -void CALLBACK THREAD_FreeTHDB( ULONG_PTR arg ) +void CALLBACK THREAD_FreeTEB( ULONG_PTR arg ) { - THDB *thdb = (THDB *)arg; - THDB **pptr = &THREAD_First; + TEB *teb = (TEB *)arg; + TEB **pptr = &THREAD_First; - TRACE("(%p) called\n", thdb ); - SERVICE_Delete( thdb->cleanup ); + TRACE("(%p) called\n", teb ); + SERVICE_Delete( teb->cleanup ); PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 ); - CloseHandle( thdb->event ); - while (*pptr && (*pptr != thdb)) pptr = &(*pptr)->next; - if (*pptr) *pptr = thdb->next; + CloseHandle( teb->event ); + while (*pptr && (*pptr != teb)) pptr = &(*pptr)->next; + if (*pptr) *pptr = teb->next; /* Free the associated memory */ - if (thdb->teb.stack_sel) SELECTOR_FreeBlock( thdb->teb.stack_sel, 1 ); - SELECTOR_FreeBlock( thdb->teb_sel, 1 ); - close( thdb->socket ); - VirtualFree( thdb->stack_base, 0, MEM_RELEASE ); - HeapFree( SystemHeap, HEAP_NO_SERIALIZE, thdb ); + if (teb->stack_sel) SELECTOR_FreeBlock( teb->stack_sel, 1 ); + SELECTOR_FreeBlock( teb->teb_sel, 1 ); + close( teb->socket ); + if (teb->buffer) + munmap( teb->buffer, (char *)teb->buffer_end - (char *)teb->buffer ); + VirtualFree( teb->stack_base, 0, MEM_RELEASE ); + HeapFree( SystemHeap, 0, teb ); } @@ -165,39 +166,38 @@ * * Create the initial thread. */ -THDB *THREAD_CreateInitialThread( PDB *pdb, int server_fd ) +TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd ) { - initial_thdb.process = pdb; - initial_thdb.teb.except = (void *)-1; - initial_thdb.teb.self = &initial_thdb.teb; - initial_thdb.teb.flags = /* TEBF_WIN32 */ 0; - initial_thdb.teb.tls_ptr = initial_thdb.tls_array; - initial_thdb.teb.process = pdb; - initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */ - initial_thdb.socket = server_fd; + initial_teb.except = (void *)-1; + initial_teb.self = &initial_teb; + initial_teb.flags = /* TEBF_WIN32 */ 0; + initial_teb.tls_ptr = initial_teb.tls_array; + initial_teb.process = pdb; + initial_teb.exit_code = 0x103; /* STILL_ACTIVE */ + initial_teb.socket = server_fd; /* Allocate the TEB selector (%fs register) */ - if (!(initial_thdb.teb_sel = SELECTOR_AllocBlock( &initial_thdb.teb, 0x1000, - SEGMENT_DATA, TRUE, FALSE ))) + if (!(initial_teb.teb_sel = SELECTOR_AllocBlock( &initial_teb, 0x1000, + SEGMENT_DATA, TRUE, FALSE ))) { MESSAGE("Could not allocate fs register for initial thread\n" ); return NULL; } - SYSDEPS_SetCurThread( &initial_thdb ); + SYSDEPS_SetCurThread( &initial_teb ); /* Now proceed with normal initialization */ if (CLIENT_InitThread()) return NULL; - if (!THREAD_InitTHDB( &initial_thdb, 0, TRUE, NULL )) return NULL; - return &initial_thdb; + if (!THREAD_InitTEB( &initial_teb, 0, TRUE, NULL )) return NULL; + return &initial_teb; } /*********************************************************************** * THREAD_Create */ -THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16, +TEB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16, LPSECURITY_ATTRIBUTES sa, int *server_handle ) { struct new_thread_request request; @@ -205,24 +205,21 @@ int fd[2]; HANDLE cleanup_object; - THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) ); - if (!thdb) return NULL; - thdb->process = pdb; - thdb->teb.except = (void *)-1; - thdb->teb.htask16 = pdb->task; - thdb->teb.self = &thdb->teb; - thdb->teb.flags = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32; - thdb->teb.tls_ptr = thdb->tls_array; - thdb->teb.process = pdb; - thdb->exit_code = 0x103; /* STILL_ACTIVE */ - thdb->flags = flags; - thdb->socket = -1; + TEB *teb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(TEB) ); + if (!teb) return NULL; + teb->except = (void *)-1; + teb->htask16 = pdb->task; + teb->self = teb; + teb->flags = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32; + teb->tls_ptr = teb->tls_array; + teb->process = pdb; + teb->exit_code = 0x103; /* STILL_ACTIVE */ + teb->socket = -1; /* Allocate the TEB selector (%fs register) */ - thdb->teb_sel = SELECTOR_AllocBlock( &thdb->teb, 0x1000, SEGMENT_DATA, - TRUE, FALSE ); - if (!thdb->teb_sel) goto error; + teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE ); + if (!teb->teb_sel) goto error; /* Create the socket pair for server communication */ @@ -231,38 +228,38 @@ SetLastError( ERROR_TOO_MANY_OPEN_FILES ); /* FIXME */ goto error; } - thdb->socket = fd[0]; + teb->socket = fd[0]; fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */ /* Create the thread on the server side */ - request.pid = thdb->process->server_pid; - request.suspend = ((thdb->flags & CREATE_SUSPENDED) != 0); + request.pid = teb->process->server_pid; + request.suspend = ((flags & CREATE_SUSPENDED) != 0); request.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle); CLIENT_SendRequest( REQ_NEW_THREAD, fd[1], 1, &request, sizeof(request) ); if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error; - thdb->teb.tid = reply.tid; + teb->tid = reply.tid; *server_handle = reply.handle; /* Do the rest of the initialization */ - if (!THREAD_InitTHDB( thdb, stack_size, alloc_stack16, sa )) goto error; - thdb->next = THREAD_First; - THREAD_First = thdb; + if (!THREAD_InitTEB( teb, stack_size, alloc_stack16, sa )) goto error; + teb->next = THREAD_First; + THREAD_First = teb; /* Install cleanup handler */ if ( !DuplicateHandle( GetCurrentProcess(), *server_handle, GetCurrentProcess(), &cleanup_object, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) goto error; - thdb->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTHDB, (ULONG_PTR)thdb ); + teb->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTEB, (ULONG_PTR)teb ); - return thdb; + return teb; error: if (reply.handle != -1) CloseHandle( reply.handle ); - if (thdb->teb_sel) SELECTOR_FreeBlock( thdb->teb_sel, 1 ); - HeapFree( SystemHeap, 0, thdb ); - if (thdb->socket != -1) close( thdb->socket ); + if (teb->teb_sel) SELECTOR_FreeBlock( teb->teb_sel, 1 ); + if (teb->socket != -1) close( teb->socket ); + HeapFree( SystemHeap, 0, teb ); return NULL; } @@ -274,15 +271,14 @@ */ static void THREAD_Start(void) { - THDB *thdb = THREAD_Current(); - LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point; + LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)NtCurrentTeb()->entry_point; PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 ); PE_InitTls(); MODULE_DllThreadAttach( NULL ); - if (thdb->process->flags & PDB32_DEBUGGED) DEBUG_SendCreateThreadEvent( func ); + if (NtCurrentTeb()->process->flags & PDB32_DEBUGGED) DEBUG_SendCreateThreadEvent( func ); - ExitThread( func( thdb->entry_arg ) ); + ExitThread( func( NtCurrentTeb()->entry_arg ) ); } @@ -294,18 +290,18 @@ DWORD flags, LPDWORD id ) { int handle = -1; - THDB *thread = THREAD_Create( PROCESS_Current(), flags, stack, TRUE, sa, &handle ); - if (!thread) return INVALID_HANDLE_VALUE; - thread->teb.flags |= TEBF_WIN32; - thread->entry_point = start; - thread->entry_arg = param; - thread->startup = THREAD_Start; - if (SYSDEPS_SpawnThread( thread ) == -1) + TEB *teb = THREAD_Create( PROCESS_Current(), flags, stack, TRUE, sa, &handle ); + if (!teb) return INVALID_HANDLE_VALUE; + teb->flags |= TEBF_WIN32; + teb->entry_point = start; + teb->entry_arg = param; + teb->startup = THREAD_Start; + if (SYSDEPS_SpawnThread( teb ) == -1) { CloseHandle( handle ); return INVALID_HANDLE_VALUE; } - if (id) *id = (DWORD)thread->teb.tid; + if (id) *id = (DWORD)teb->tid; return handle; } @@ -335,18 +331,6 @@ } -/*********************************************************************** - * GetCurrentThreadId [KERNEL32.201] Returns thread identifier. - * - * RETURNS - * Thread identifier of calling thread - */ -DWORD WINAPI GetCurrentThreadId(void) -{ - return (DWORD)CURRENT()->tid; -} - - /********************************************************************** * GetLastError [KERNEL.148] [KERNEL32.227] Returns last-error code. * @@ -355,25 +339,7 @@ */ DWORD WINAPI GetLastError(void) { - THDB *thread = THREAD_Current(); - DWORD ret = thread->last_error; - TRACE("0x%lx\n",ret); - return ret; -} - - -/********************************************************************** - * SetLastError [KERNEL.147] [KERNEL32.497] Sets the last-error code. - * - * RETURNS - * None. - */ -void WINAPI SetLastError( - DWORD error) /* [in] Per-thread error code */ -{ - THDB *thread = THREAD_Current(); - TRACE("%p error=0x%lx\n",thread,error); - thread->last_error = error; + return NtCurrentTeb()->last_error; } @@ -414,24 +380,24 @@ */ DWORD WINAPI TlsAlloc( void ) { - THDB *thread = THREAD_Current(); + PDB *process = PROCESS_Current(); DWORD i, mask, ret = 0; - DWORD *bits = thread->process->tls_bits; - EnterCriticalSection( &thread->process->crit_section ); + DWORD *bits = process->tls_bits; + EnterCriticalSection( &process->crit_section ); if (*bits == 0xffffffff) { bits++; ret = 32; if (*bits == 0xffffffff) { - LeaveCriticalSection( &thread->process->crit_section ); + LeaveCriticalSection( &process->crit_section ); SetLastError( ERROR_NO_MORE_ITEMS ); return 0xffffffff; } } for (i = 0, mask = 1; i < 32; i++, mask <<= 1) if (!(*bits & mask)) break; *bits |= mask; - LeaveCriticalSection( &thread->process->crit_section ); + LeaveCriticalSection( &process->crit_section ); return ret + i; } @@ -448,27 +414,27 @@ BOOL WINAPI TlsFree( DWORD index) /* [in] TLS Index to free */ { + PDB *process = PROCESS_Current(); DWORD mask; - THDB *thread = THREAD_Current(); - DWORD *bits = thread->process->tls_bits; + DWORD *bits = process->tls_bits; if (index >= 64) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - EnterCriticalSection( &thread->process->crit_section ); + EnterCriticalSection( &process->crit_section ); if (index >= 32) bits++; mask = (1 << (index & 31)); if (!(*bits & mask)) /* already free? */ { - LeaveCriticalSection( &thread->process->crit_section ); + LeaveCriticalSection( &process->crit_section ); SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } *bits &= ~mask; - thread->tls_array[index] = 0; + NtCurrentTeb()->tls_array[index] = 0; /* FIXME: should zero all other thread values */ - LeaveCriticalSection( &thread->process->crit_section ); + LeaveCriticalSection( &process->crit_section ); return TRUE; } @@ -483,14 +449,13 @@ LPVOID WINAPI TlsGetValue( DWORD index) /* [in] TLS index to retrieve value for */ { - THDB *thread = THREAD_Current(); if (index >= 64) { SetLastError( ERROR_INVALID_PARAMETER ); return NULL; } SetLastError( ERROR_SUCCESS ); - return thread->tls_array[index]; + return NtCurrentTeb()->tls_array[index]; } @@ -505,13 +470,12 @@ DWORD index, /* [in] TLS index to set value for */ LPVOID value) /* [in] Value to be stored */ { - THDB *thread = THREAD_Current(); if (index >= 64) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - thread->tls_array[index] = value; + NtCurrentTeb()->tls_array[index] = value; return TRUE; } @@ -849,3 +813,29 @@ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } + + +/********************************************************************** + * SetLastError [KERNEL.147] [KERNEL32.497] Sets the last-error code. + * + * RETURNS + * None. + */ +#undef SetLastError +void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */ +{ + NtCurrentTeb()->last_error = error; +} + + +/*********************************************************************** + * GetCurrentThreadId [KERNEL32.201] Returns thread identifier. + * + * RETURNS + * Thread identifier of calling thread + */ +#undef GetCurrentThreadId +DWORD WINAPI GetCurrentThreadId(void) +{ + return (DWORD)NtCurrentTeb()->tid; +}