Setup the initial thread %fs from a constructor.
This commit is contained in:
parent
1ca9be85f6
commit
8c21dfcf0f
|
@ -145,7 +145,7 @@ typedef struct _PDB
|
||||||
#define GPD_USERDATA ( 0)
|
#define GPD_USERDATA ( 0)
|
||||||
|
|
||||||
extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
|
extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
|
||||||
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
|
extern void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
|
||||||
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
|
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
|
||||||
|
|
||||||
/* memory/environ.c */
|
/* memory/environ.c */
|
||||||
|
@ -166,8 +166,6 @@ extern BOOL PROCESS_CreateUnixProcess( LPCSTR filename, LPCSTR cmd_line, LPCSTR
|
||||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||||
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
||||||
LPPROCESS_INFORMATION info );
|
LPPROCESS_INFORMATION info );
|
||||||
extern void PROCESS_FreePDB( PDB *pdb );
|
|
||||||
extern void PROCESS_WalkProcess( void );
|
|
||||||
|
|
||||||
static inline PDB * WINE_UNUSED PROCESS_Current(void)
|
static inline PDB * WINE_UNUSED PROCESS_Current(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -119,9 +119,9 @@ typedef struct _TEB
|
||||||
|
|
||||||
|
|
||||||
/* scheduler/thread.c */
|
/* scheduler/thread.c */
|
||||||
extern TEB *THREAD_Init( struct _PDB *pdb );
|
extern void THREAD_Init(void);
|
||||||
extern TEB *THREAD_Create( struct _PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 );
|
extern TEB *THREAD_Create( struct _PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 );
|
||||||
extern TEB *THREAD_InitStack( TEB *teb, struct _PDB *pdb, DWORD stack_size, BOOL alloc_stack16 );
|
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size, BOOL alloc_stack16 );
|
||||||
extern BOOL THREAD_IsWin16( TEB *thdb );
|
extern BOOL THREAD_IsWin16( TEB *thdb );
|
||||||
extern TEB *THREAD_IdToTEB( DWORD id );
|
extern TEB *THREAD_IdToTEB( DWORD id );
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ void MAIN_EmulatorRun( void )
|
||||||
if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver",
|
if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver",
|
||||||
"x11drv", szGraphicsDriver, sizeof(szGraphicsDriver)))
|
"x11drv", szGraphicsDriver, sizeof(szGraphicsDriver)))
|
||||||
{
|
{
|
||||||
if (!LoadLibraryA( szGraphicsDriver )) return FALSE;
|
if (!LoadLibraryA( szGraphicsDriver )) ExitProcess(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load system DLLs into the initial process (and initialize them) */
|
/* Load system DLLs into the initial process (and initialize them) */
|
||||||
|
@ -109,7 +109,7 @@ int main( int argc, char *argv[] )
|
||||||
/* Initialize everything */
|
/* Initialize everything */
|
||||||
if (!MAIN_MainInit( argc, argv, FALSE )) return 1;
|
if (!MAIN_MainInit( argc, argv, FALSE )) return 1;
|
||||||
|
|
||||||
if (!THREAD_InitStack( NtCurrentTeb(), PROCESS_Current(), 0, TRUE )) return 1;
|
if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) return 1;
|
||||||
SIGNAL_Init(); /* reinitialize signal stack */
|
SIGNAL_Init(); /* reinitialize signal stack */
|
||||||
|
|
||||||
/* Initialize KERNEL */
|
/* Initialize KERNEL */
|
||||||
|
|
|
@ -37,12 +37,10 @@ DECLARE_DEBUG_CHANNEL(relay);
|
||||||
DECLARE_DEBUG_CHANNEL(win32);
|
DECLARE_DEBUG_CHANNEL(win32);
|
||||||
|
|
||||||
|
|
||||||
/* The initial process PDB */
|
|
||||||
static PDB initial_pdb;
|
|
||||||
static ENVDB initial_envdb;
|
static ENVDB initial_envdb;
|
||||||
static STARTUPINFOA initial_startup;
|
static STARTUPINFOA initial_startup;
|
||||||
|
|
||||||
static PDB *PROCESS_First = &initial_pdb;
|
static PDB *PROCESS_First;
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -213,7 +211,7 @@ static BOOL PROCESS_CreateEnvDB(void)
|
||||||
*
|
*
|
||||||
* Free a PDB and all associated storage.
|
* Free a PDB and all associated storage.
|
||||||
*/
|
*/
|
||||||
void PROCESS_FreePDB( PDB *pdb )
|
static void PROCESS_FreePDB( PDB *pdb )
|
||||||
{
|
{
|
||||||
PDB **pptr = &PROCESS_First;
|
PDB **pptr = &PROCESS_First;
|
||||||
|
|
||||||
|
@ -263,36 +261,38 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
|
||||||
BOOL PROCESS_Init( BOOL win32 )
|
BOOL PROCESS_Init( BOOL win32 )
|
||||||
{
|
{
|
||||||
struct init_process_request *req;
|
struct init_process_request *req;
|
||||||
TEB *teb;
|
PDB *pdb = PROCESS_Current();
|
||||||
|
|
||||||
/* Fill the initial process structure */
|
/* Fill the initial process structure */
|
||||||
initial_pdb.exit_code = STILL_ACTIVE;
|
pdb->exit_code = STILL_ACTIVE;
|
||||||
initial_pdb.threads = 1;
|
pdb->threads = 1;
|
||||||
initial_pdb.running_threads = 1;
|
pdb->running_threads = 1;
|
||||||
initial_pdb.ring0_threads = 1;
|
pdb->ring0_threads = 1;
|
||||||
initial_pdb.env_db = &initial_envdb;
|
pdb->env_db = &initial_envdb;
|
||||||
initial_pdb.group = &initial_pdb;
|
pdb->group = pdb;
|
||||||
initial_pdb.priority = 8; /* Normal */
|
pdb->priority = 8; /* Normal */
|
||||||
initial_pdb.flags = win32? 0 : PDB32_WIN16_PROC;
|
pdb->winver = 0xffff; /* to be determined */
|
||||||
initial_pdb.winver = 0xffff; /* to be determined */
|
pdb->main_queue = INVALID_HANDLE_VALUE16;
|
||||||
initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
|
|
||||||
initial_envdb.startup_info = &initial_startup;
|
initial_envdb.startup_info = &initial_startup;
|
||||||
teb = THREAD_Init( &initial_pdb );
|
PROCESS_First = pdb;
|
||||||
|
|
||||||
|
if (!win32)
|
||||||
|
{
|
||||||
|
pdb->flags = PDB32_WIN16_PROC;
|
||||||
|
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup the server connection */
|
/* Setup the server connection */
|
||||||
teb->socket = CLIENT_InitServer();
|
NtCurrentTeb()->socket = CLIENT_InitServer();
|
||||||
if (CLIENT_InitThread()) return FALSE;
|
if (CLIENT_InitThread()) return FALSE;
|
||||||
|
|
||||||
/* Initialize virtual memory management */
|
|
||||||
if (!VIRTUAL_Init()) return FALSE;
|
|
||||||
|
|
||||||
/* Retrieve startup info from the server */
|
/* Retrieve startup info from the server */
|
||||||
req = get_req_buffer();
|
req = get_req_buffer();
|
||||||
req->ldt_copy = ldt_copy;
|
req->ldt_copy = ldt_copy;
|
||||||
req->ldt_flags = ldt_flags_copy;
|
req->ldt_flags = ldt_flags_copy;
|
||||||
req->ppid = getppid();
|
req->ppid = getppid();
|
||||||
if (server_call( REQ_INIT_PROCESS )) return FALSE;
|
if (server_call( REQ_INIT_PROCESS )) return FALSE;
|
||||||
initial_pdb.exe_file = req->exe_file;
|
pdb->exe_file = req->exe_file;
|
||||||
initial_startup.dwFlags = req->start_flags;
|
initial_startup.dwFlags = req->start_flags;
|
||||||
initial_startup.wShowWindow = req->cmd_show;
|
initial_startup.wShowWindow = req->cmd_show;
|
||||||
initial_envdb.hStdin = initial_startup.hStdInput = req->hstdin;
|
initial_envdb.hStdin = initial_startup.hStdInput = req->hstdin;
|
||||||
|
@ -304,19 +304,19 @@ BOOL PROCESS_Init( BOOL win32 )
|
||||||
if (!SIGNAL_Init()) return FALSE;
|
if (!SIGNAL_Init()) return FALSE;
|
||||||
|
|
||||||
/* Remember TEB selector of initial process for emergency use */
|
/* Remember TEB selector of initial process for emergency use */
|
||||||
SYSLEVEL_EmergencyTeb = teb->teb_sel;
|
SYSLEVEL_EmergencyTeb = NtCurrentTeb()->teb_sel;
|
||||||
|
|
||||||
/* Create the system and process heaps */
|
/* Create the system and process heaps */
|
||||||
if (!HEAP_CreateSystemHeap()) return FALSE;
|
if (!HEAP_CreateSystemHeap()) return FALSE;
|
||||||
initial_pdb.heap = HeapCreate( HEAP_GROWABLE, 0, 0 );
|
pdb->heap = HeapCreate( HEAP_GROWABLE, 0, 0 );
|
||||||
|
|
||||||
/* Create the idle event for the initial process
|
/* Create the idle event for the initial process
|
||||||
FIXME 1: Shouldn't we call UserSignalProc for the initial process too?
|
FIXME 1: Shouldn't we call UserSignalProc for the initial process too?
|
||||||
FIXME 2: It seems to me that the initial pdb becomes never freed, so I don't now
|
FIXME 2: It seems to me that the initial pdb becomes never freed, so I don't now
|
||||||
where to release the idle event for the initial process.
|
where to release the idle event for the initial process.
|
||||||
*/
|
*/
|
||||||
initial_pdb.idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
|
pdb->idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
|
||||||
initial_pdb.idle_event = ConvertToGlobalHandle ( initial_pdb.idle_event );
|
pdb->idle_event = ConvertToGlobalHandle ( pdb->idle_event );
|
||||||
|
|
||||||
/* Copy the parent environment */
|
/* Copy the parent environment */
|
||||||
if (!ENV_BuildEnvironment()) return FALSE;
|
if (!ENV_BuildEnvironment()) return FALSE;
|
||||||
|
@ -325,7 +325,7 @@ BOOL PROCESS_Init( BOOL win32 )
|
||||||
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
|
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
|
||||||
|
|
||||||
/* Initialize the critical sections */
|
/* Initialize the critical sections */
|
||||||
InitializeCriticalSection( &initial_pdb.crit_section );
|
InitializeCriticalSection( &pdb->crit_section );
|
||||||
InitializeCriticalSection( &initial_envdb.section );
|
InitializeCriticalSection( &initial_envdb.section );
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -467,7 +467,7 @@ void PROCESS_Init32( HFILE hFile, LPCSTR filename, LPCSTR cmd_line )
|
||||||
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
|
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
|
||||||
|
|
||||||
/* allocate main thread stack */
|
/* allocate main thread stack */
|
||||||
if (!THREAD_InitStack( NtCurrentTeb(), pdb,
|
if (!THREAD_InitStack( NtCurrentTeb(),
|
||||||
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
|
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -516,7 +516,7 @@ void PROCESS_InitWinelib( int argc, char *argv[] )
|
||||||
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
|
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
|
||||||
|
|
||||||
/* allocate main thread stack */
|
/* allocate main thread stack */
|
||||||
if (!THREAD_InitStack( NtCurrentTeb(), pdb,
|
if (!THREAD_InitStack( NtCurrentTeb(),
|
||||||
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
|
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,9 @@ DEFAULT_DEBUG_CHANNEL(thread);
|
||||||
/* TEB of the initial thread */
|
/* TEB of the initial thread */
|
||||||
static TEB initial_teb;
|
static TEB initial_teb;
|
||||||
|
|
||||||
|
/* The initial process PDB */
|
||||||
|
static PDB initial_pdb;
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* THREAD_IsWin16
|
* THREAD_IsWin16
|
||||||
*/
|
*/
|
||||||
|
@ -75,18 +78,15 @@ TEB *THREAD_IdToTEB( DWORD id )
|
||||||
*
|
*
|
||||||
* Initialization of a newly created TEB.
|
* Initialization of a newly created TEB.
|
||||||
*/
|
*/
|
||||||
static BOOL THREAD_InitTEB( TEB *teb, PDB *pdb )
|
static BOOL THREAD_InitTEB( TEB *teb )
|
||||||
{
|
{
|
||||||
teb->except = (void *)~0UL;
|
teb->except = (void *)~0UL;
|
||||||
teb->htask16 = pdb->task;
|
|
||||||
teb->self = teb;
|
teb->self = teb;
|
||||||
teb->tibflags = (pdb->flags & PDB32_WIN16_PROC) ? 0 : TEBF_WIN32;
|
teb->tibflags = TEBF_WIN32;
|
||||||
teb->tls_ptr = teb->tls_array;
|
teb->tls_ptr = teb->tls_array;
|
||||||
teb->process = pdb;
|
|
||||||
teb->exit_code = STILL_ACTIVE;
|
teb->exit_code = STILL_ACTIVE;
|
||||||
teb->socket = -1;
|
teb->socket = -1;
|
||||||
teb->stack_top = (void *)~0UL;
|
teb->stack_top = (void *)~0UL;
|
||||||
|
|
||||||
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
||||||
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
|
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
|
||||||
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
|
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
|
||||||
|
@ -121,7 +121,7 @@ static void CALLBACK THREAD_FreeTEB( TEB *teb )
|
||||||
*
|
*
|
||||||
* Allocate the stack of a thread.
|
* Allocate the stack of a thread.
|
||||||
*/
|
*/
|
||||||
TEB *THREAD_InitStack( TEB *teb, PDB *pdb, DWORD stack_size, BOOL alloc_stack16 )
|
TEB *THREAD_InitStack( TEB *teb, DWORD stack_size, BOOL alloc_stack16 )
|
||||||
{
|
{
|
||||||
DWORD old_prot, total_size;
|
DWORD old_prot, total_size;
|
||||||
DWORD page_size = VIRTUAL_GetPageSize();
|
DWORD page_size = VIRTUAL_GetPageSize();
|
||||||
|
@ -158,7 +158,7 @@ TEB *THREAD_InitStack( TEB *teb, PDB *pdb, DWORD stack_size, BOOL alloc_stack16
|
||||||
if (!teb)
|
if (!teb)
|
||||||
{
|
{
|
||||||
teb = (TEB *)((char *)base + total_size - page_size);
|
teb = (TEB *)((char *)base + total_size - page_size);
|
||||||
if (!THREAD_InitTEB( teb, pdb ))
|
if (!THREAD_InitTEB( teb ))
|
||||||
{
|
{
|
||||||
VirtualFree( base, 0, MEM_RELEASE );
|
VirtualFree( base, 0, MEM_RELEASE );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -202,13 +202,18 @@ error:
|
||||||
*
|
*
|
||||||
* NOTES: The first allocated TEB on NT is at 0x7ffde000.
|
* NOTES: The first allocated TEB on NT is at 0x7ffde000.
|
||||||
*/
|
*/
|
||||||
TEB *THREAD_Init( struct _PDB *pdb )
|
void THREAD_Init(void)
|
||||||
{
|
{
|
||||||
if (!THREAD_InitTEB( &initial_teb, pdb )) return NULL;
|
if (!initial_teb.self) /* do it only once */
|
||||||
SYSDEPS_SetCurThread( &initial_teb );
|
{
|
||||||
return &initial_teb;
|
THREAD_InitTEB( &initial_teb );
|
||||||
|
assert( initial_teb.teb_sel );
|
||||||
|
initial_teb.process = &initial_pdb;
|
||||||
|
SYSDEPS_SetCurThread( &initial_teb );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECL_GLOBAL_CONSTRUCTOR(thread_init) { THREAD_Init(); }
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* THREAD_Create
|
* THREAD_Create
|
||||||
|
@ -218,9 +223,11 @@ TEB *THREAD_Create( PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 )
|
||||||
{
|
{
|
||||||
TEB *teb;
|
TEB *teb;
|
||||||
|
|
||||||
if ((teb = THREAD_InitStack( NULL, pdb, stack_size, alloc_stack16 )))
|
if ((teb = THREAD_InitStack( NULL, stack_size, alloc_stack16 )))
|
||||||
{
|
{
|
||||||
teb->socket = fd;
|
teb->tibflags = (pdb->flags & PDB32_WIN16_PROC) ? 0 : TEBF_WIN32;
|
||||||
|
teb->process = pdb;
|
||||||
|
teb->socket = fd;
|
||||||
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
||||||
TRACE("(%p) succeeded\n", teb);
|
TRACE("(%p) succeeded\n", teb);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue