Setup the initial thread %fs from a constructor.
diff --git a/scheduler/process.c b/scheduler/process.c
index 8bdf146..5955a10 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -37,12 +37,10 @@
DECLARE_DEBUG_CHANNEL(win32);
-/* The initial process PDB */
-static PDB initial_pdb;
static ENVDB initial_envdb;
static STARTUPINFOA initial_startup;
-static PDB *PROCESS_First = &initial_pdb;
+static PDB *PROCESS_First;
/***********************************************************************
@@ -213,7 +211,7 @@
*
* Free a PDB and all associated storage.
*/
-void PROCESS_FreePDB( PDB *pdb )
+static void PROCESS_FreePDB( PDB *pdb )
{
PDB **pptr = &PROCESS_First;
@@ -263,36 +261,38 @@
BOOL PROCESS_Init( BOOL win32 )
{
struct init_process_request *req;
- TEB *teb;
+ PDB *pdb = PROCESS_Current();
/* Fill the initial process structure */
- initial_pdb.exit_code = STILL_ACTIVE;
- initial_pdb.threads = 1;
- initial_pdb.running_threads = 1;
- initial_pdb.ring0_threads = 1;
- initial_pdb.env_db = &initial_envdb;
- initial_pdb.group = &initial_pdb;
- initial_pdb.priority = 8; /* Normal */
- initial_pdb.flags = win32? 0 : PDB32_WIN16_PROC;
- initial_pdb.winver = 0xffff; /* to be determined */
- initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
+ pdb->exit_code = STILL_ACTIVE;
+ pdb->threads = 1;
+ pdb->running_threads = 1;
+ pdb->ring0_threads = 1;
+ pdb->env_db = &initial_envdb;
+ pdb->group = pdb;
+ pdb->priority = 8; /* Normal */
+ pdb->winver = 0xffff; /* to be determined */
+ pdb->main_queue = INVALID_HANDLE_VALUE16;
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 */
- teb->socket = CLIENT_InitServer();
+ NtCurrentTeb()->socket = CLIENT_InitServer();
if (CLIENT_InitThread()) return FALSE;
- /* Initialize virtual memory management */
- if (!VIRTUAL_Init()) return FALSE;
-
/* Retrieve startup info from the server */
req = get_req_buffer();
req->ldt_copy = ldt_copy;
req->ldt_flags = ldt_flags_copy;
req->ppid = getppid();
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.wShowWindow = req->cmd_show;
initial_envdb.hStdin = initial_startup.hStdInput = req->hstdin;
@@ -304,19 +304,19 @@
if (!SIGNAL_Init()) return FALSE;
/* 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 */
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
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
where to release the idle event for the initial process.
*/
- initial_pdb.idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
- initial_pdb.idle_event = ConvertToGlobalHandle ( initial_pdb.idle_event );
+ pdb->idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
+ pdb->idle_event = ConvertToGlobalHandle ( pdb->idle_event );
/* Copy the parent environment */
if (!ENV_BuildEnvironment()) return FALSE;
@@ -325,7 +325,7 @@
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
/* Initialize the critical sections */
- InitializeCriticalSection( &initial_pdb.crit_section );
+ InitializeCriticalSection( &pdb->crit_section );
InitializeCriticalSection( &initial_envdb.section );
return TRUE;
@@ -467,7 +467,7 @@
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
/* allocate main thread stack */
- if (!THREAD_InitStack( NtCurrentTeb(), pdb,
+ if (!THREAD_InitStack( NtCurrentTeb(),
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
goto error;
@@ -516,7 +516,7 @@
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
/* allocate main thread stack */
- if (!THREAD_InitStack( NtCurrentTeb(), pdb,
+ if (!THREAD_InitStack( NtCurrentTeb(),
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
goto error;
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 3e541ac..9499d75 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -37,6 +37,9 @@
/* TEB of the initial thread */
static TEB initial_teb;
+/* The initial process PDB */
+static PDB initial_pdb;
+
/***********************************************************************
* THREAD_IsWin16
*/
@@ -75,18 +78,15 @@
*
* 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->htask16 = pdb->task;
teb->self = teb;
- teb->tibflags = (pdb->flags & PDB32_WIN16_PROC) ? 0 : TEBF_WIN32;
+ teb->tibflags = TEBF_WIN32;
teb->tls_ptr = teb->tls_array;
- teb->process = pdb;
teb->exit_code = STILL_ACTIVE;
teb->socket = -1;
teb->stack_top = (void *)~0UL;
-
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
@@ -121,7 +121,7 @@
*
* 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 page_size = VIRTUAL_GetPageSize();
@@ -158,7 +158,7 @@
if (!teb)
{
teb = (TEB *)((char *)base + total_size - page_size);
- if (!THREAD_InitTEB( teb, pdb ))
+ if (!THREAD_InitTEB( teb ))
{
VirtualFree( base, 0, MEM_RELEASE );
return NULL;
@@ -202,13 +202,18 @@
*
* 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;
- SYSDEPS_SetCurThread( &initial_teb );
- return &initial_teb;
+ if (!initial_teb.self) /* do it only once */
+ {
+ 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
@@ -218,9 +223,11 @@
{
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 */
TRACE("(%p) succeeded\n", teb);
}