Commit 93b23d74 authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Run Win32 processes in their own threads.

Process exit sequence adapted.
parent f016752b
...@@ -150,6 +150,7 @@ extern BOOL TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule, ...@@ -150,6 +150,7 @@ extern BOOL TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance, HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
UINT16 cmdShow ); UINT16 cmdShow );
extern void TASK_StartTask( HTASK16 hTask ); extern void TASK_StartTask( HTASK16 hTask );
extern void TASK_KillTask( HTASK16 hTask );
extern void TASK_KillCurrentTask( INT16 exitCode ); extern void TASK_KillCurrentTask( INT16 exitCode );
extern HTASK16 TASK_GetNextTask( HTASK16 hTask ); extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
extern BOOL TASK_Reschedule(void); extern BOOL TASK_Reschedule(void);
......
...@@ -57,7 +57,7 @@ THHOOK *pThhook = &DefaultThhook; ...@@ -57,7 +57,7 @@ THHOOK *pThhook = &DefaultThhook;
static HTASK16 hTaskToKill = 0; static HTASK16 hTaskToKill = 0;
static UINT16 nTaskCount = 0; static UINT16 nTaskCount = 0;
static void TASK_YieldToSystem(TDB*); static void TASK_YieldToSystem( void );
extern BOOL THREAD_InitDone; extern BOOL THREAD_InitDone;
...@@ -240,48 +240,8 @@ static void TASK_CallToStart(void) ...@@ -240,48 +240,8 @@ static void TASK_CallToStart(void)
if (pModule->flags & NE_FFLAGS_WIN32) if (pModule->flags & NE_FFLAGS_WIN32)
{ {
/* FIXME: all this is an ugly hack */ ERR( task, "Called for Win32 task!\n" );
ExitProcess( 1 );
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
LPTHREAD_START_ROUTINE entry = (LPTHREAD_START_ROUTINE)
RVA_PTR(pModule->module32, OptionalHeader.AddressOfEntryPoint);
/* Create 32-bit MODREF */
if ( !PE_CreateModule( pModule->module32, ofs, 0, FALSE ) )
{
ERR( task, "Could not initialize process\n" );
ExitProcess( 1 );
}
/* Initialize Thread-Local Storage */
PE_InitTls( pTask->thdb );
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
AllocConsole();
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 );
TRACE(relay, "(entryproc=%p)\n", entry );
#if 1
ExitProcess( entry(NULL) );
#else
{
DWORD size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
DWORD id;
THDB *thdb;
CreateThread( NULL, size, entry, NULL, 0, &id );
thdb = THREAD_IdToTHDB( id );
while ( thdb->exit_code == 0x103 )
{
WaitEvent16( 0 );
QUEUE_Signal( pTask->hSelf );
}
ExitProcess( thdb->exit_code );
}
#endif
} }
else if (pModule->dos_image) else if (pModule->dos_image)
{ {
...@@ -356,7 +316,7 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance, ...@@ -356,7 +316,7 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
/* Fill the task structure */ /* Fill the task structure */
pTask->nEvents = 1; /* So the task can be started */ pTask->nEvents = 0;
pTask->hSelf = hTask; pTask->hSelf = hTask;
pTask->flags = 0; pTask->flags = 0;
...@@ -498,6 +458,9 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance, ...@@ -498,6 +458,9 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
*/ */
void TASK_StartTask( HTASK16 hTask ) void TASK_StartTask( HTASK16 hTask )
{ {
TDB *pTask = (TDB *)GlobalLock16( hTask );
if ( !pTask ) return;
/* Add the task to the linked list */ /* Add the task to the linked list */
SYSLEVEL_EnterWin16Lock(); SYSLEVEL_EnterWin16Lock();
...@@ -511,15 +474,26 @@ void TASK_StartTask( HTASK16 hTask ) ...@@ -511,15 +474,26 @@ void TASK_StartTask( HTASK16 hTask )
if ( TASK_AddTaskEntryBreakpoint ) if ( TASK_AddTaskEntryBreakpoint )
TASK_AddTaskEntryBreakpoint( hTask ); TASK_AddTaskEntryBreakpoint( hTask );
/* Get the task up and running. If we ourselves are a 16-bit task, /* Get the task up and running. */
we simply Yield(). If we are 32-bit however, we need to signal
the main process somehow (NOT YET IMPLEMENTED!) */ if ( THREAD_IsWin16( pTask->thdb ) )
{
pTask->nEvents++;
/* If we ourselves are a 16-bit task, we simply Yield().
If we are 32-bit however, we need to signal the scheduler. */
if ( THREAD_IsWin16( THREAD_Current() ) ) if ( THREAD_IsWin16( THREAD_Current() ) )
OldYield16(); OldYield16();
else
EVENT_WakeUp();
}
else else
/* wake-up the scheduler waiting in EVENT_WaitNetEvent */ {
EVENT_WakeUp(); /* To start a 32-bit task, we spawn its initial thread. */
SYSDEPS_SpawnThread( pTask->thdb );
}
} }
...@@ -560,37 +534,25 @@ static void TASK_DeleteTask( HTASK16 hTask ) ...@@ -560,37 +534,25 @@ static void TASK_DeleteTask( HTASK16 hTask )
GlobalFreeAll16( hPDB ); GlobalFreeAll16( hPDB );
} }
/*********************************************************************** /***********************************************************************
* TASK_KillCurrentTask * TASK_KillTask
*
* Kill the currently running task. As it's not possible to kill the
* current task like this, it is simply marked for destruction, and will
* be killed when either TASK_Reschedule or this function is called again
* in the context of another task.
*/ */
void TASK_KillCurrentTask( INT16 exitCode ) void TASK_KillTask( HTASK16 hTask )
{ {
TDB* pTask = (TDB*) GlobalLock16( GetCurrentTask() ); TDB *pTask;
NE_MODULE* pModule = NE_GetPtr( pTask->hModule );
if (!pTask) USER_ExitWindows(); /* No current task yet */
if ( !THREAD_IsWin16( THREAD_Current() ) ) /* Enter the Win16Lock to protect global data structures */
SYSLEVEL_EnterWin16Lock();
if ( !hTask ) hTask = GetCurrentTask();
pTask = (TDB *)GlobalLock16( hTask );
if ( !pTask )
{ {
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel); SYSLEVEL_LeaveWin16Lock();
return; return;
} }
/* Enter the Win16Lock to protect global data structures TRACE(task, "Killing task %04x\n", hTask );
NOTE: We never explicitly leave it again. This shouldn't matter
though, as it will be released in TASK_Reschedule and this
task won't ever get scheduled again ... */
SYSLEVEL_EnterWin16Lock();
assert(hCurrentTask == GetCurrentTask());
TRACE(task, "Killing task %04x\n", hCurrentTask );
/* Delete active sockets */ /* Delete active sockets */
...@@ -598,9 +560,12 @@ void TASK_KillCurrentTask( INT16 exitCode ) ...@@ -598,9 +560,12 @@ void TASK_KillCurrentTask( INT16 exitCode )
WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi ); WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi );
#ifdef MZ_SUPPORTED #ifdef MZ_SUPPORTED
{
/* Kill DOS VM task */ /* Kill DOS VM task */
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
if ( pModule->lpDosTask ) if ( pModule->lpDosTask )
MZ_KillModule( pModule->lpDosTask ); MZ_KillModule( pModule->lpDosTask );
}
#endif #endif
/* Perform USER cleanup */ /* Perform USER cleanup */
...@@ -609,13 +574,6 @@ void TASK_KillCurrentTask( INT16 exitCode ) ...@@ -609,13 +574,6 @@ void TASK_KillCurrentTask( INT16 exitCode )
pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0, pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
pTask->hInstance, pTask->hQueue ); pTask->hInstance, pTask->hQueue );
if (hTaskToKill && (hTaskToKill != hCurrentTask))
{
/* If another task is already marked for destruction, */
/* we can kill it now, as we are in another context. */
TASK_DeleteTask( hTaskToKill );
}
if (nTaskCount <= 1) if (nTaskCount <= 1)
{ {
TRACE(task, "this is the last task, exiting\n" ); TRACE(task, "this is the last task, exiting\n" );
...@@ -631,22 +589,71 @@ void TASK_KillCurrentTask( INT16 exitCode ) ...@@ -631,22 +589,71 @@ void TASK_KillCurrentTask( INT16 exitCode )
Callout.PostAppMessage16( PROCESS_Initial()->task, WM_NULL, 0, 0 ); Callout.PostAppMessage16( PROCESS_Initial()->task, WM_NULL, 0, 0 );
/* Remove the task from the list to be sure we never switch back to it */ /* Remove the task from the list to be sure we never switch back to it */
TASK_UnlinkTask( hCurrentTask ); TASK_UnlinkTask( hTask );
if( nTaskCount ) if( nTaskCount )
{ {
TDB* p = (TDB *)GlobalLock16( hFirstTask ); TDB* p = (TDB *)GlobalLock16( hFirstTask );
while( p ) while( p )
{ {
if( p->hYieldTo == hCurrentTask ) p->hYieldTo = 0; if( p->hYieldTo == hTask ) p->hYieldTo = 0;
p = (TDB *)GlobalLock16( p->hNext ); p = (TDB *)GlobalLock16( p->hNext );
} }
} }
hTaskToKill = hCurrentTask;
hLockedTask = 0;
pTask->nEvents = 0; pTask->nEvents = 0;
TASK_YieldToSystem(pTask);
if ( hLockedTask == hTask )
hLockedTask = 0;
if ( hTaskToKill && ( hTaskToKill != hCurrentTask ) )
{
/* If another task is already marked for destruction, */
/* we can kill it now, as we are in another context. */
TASK_DeleteTask( hTaskToKill );
hTaskToKill = 0;
}
/*
* If hTask is not the task currently scheduled by the Win16
* scheduler, we simply delete it; otherwise we mark it for
* destruction. Note that if the current task is a 32-bit
* one, hCurrentTask is *different* from GetCurrentTask()!
*/
if ( hTask == hCurrentTask )
{
assert( hTaskToKill == 0 || hTaskToKill == hCurrentTask );
hTaskToKill = hCurrentTask;
}
else
TASK_DeleteTask( hTask );
SYSLEVEL_LeaveWin16Lock();
}
/***********************************************************************
* TASK_KillCurrentTask
*
* Kill the currently running task. As it's not possible to kill the
* current task like this, it is simply marked for destruction, and will
* be killed when either TASK_Reschedule or this function is called again
* in the context of another task.
*/
void TASK_KillCurrentTask( INT16 exitCode )
{
if ( !THREAD_IsWin16( THREAD_Current() ) )
{
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
return;
}
assert(hCurrentTask == GetCurrentTask());
TRACE(task, "Killing current task %04x\n", hCurrentTask );
TASK_KillTask( 0 );
TASK_YieldToSystem();
/* We should never return from this Yield() */ /* We should never return from this Yield() */
...@@ -824,7 +831,7 @@ BOOL TASK_Reschedule(void) ...@@ -824,7 +831,7 @@ BOOL TASK_Reschedule(void)
* Scheduler interface, this way we ensure that all "unsafe" events are * Scheduler interface, this way we ensure that all "unsafe" events are
* processed outside the scheduler. * processed outside the scheduler.
*/ */
void TASK_YieldToSystem(TDB* pTask) static void TASK_YieldToSystem( void )
{ {
if ( !THREAD_IsWin16( THREAD_Current() ) ) if ( !THREAD_IsWin16( THREAD_Current() ) )
{ {
...@@ -944,7 +951,7 @@ BOOL16 WINAPI WaitEvent16( HTASK16 hTask ) ...@@ -944,7 +951,7 @@ BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
pTask->nEvents--; pTask->nEvents--;
return FALSE; return FALSE;
} }
TASK_YieldToSystem(pTask); TASK_YieldToSystem();
/* When we get back here, we have an event */ /* When we get back here, we have an event */
...@@ -963,6 +970,12 @@ void WINAPI PostEvent16( HTASK16 hTask ) ...@@ -963,6 +970,12 @@ void WINAPI PostEvent16( HTASK16 hTask )
if (!hTask) hTask = GetCurrentTask(); if (!hTask) hTask = GetCurrentTask();
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return; if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
if ( !THREAD_IsWin16( pTask->thdb ) )
{
FIXME( task, "called for Win32 thread (%04x)!\n", pTask->thdb->teb_sel );
return;
}
pTask->nEvents++; pTask->nEvents++;
if ( !THREAD_IsWin16( THREAD_Current() ) ) if ( !THREAD_IsWin16( THREAD_Current() ) )
...@@ -1028,7 +1041,7 @@ void WINAPI OldYield16(void) ...@@ -1028,7 +1041,7 @@ void WINAPI OldYield16(void)
} }
if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */ if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
TASK_YieldToSystem(pCurTask); TASK_YieldToSystem();
if (pCurTask) pCurTask->nEvents--; if (pCurTask) pCurTask->nEvents--;
} }
......
...@@ -288,6 +288,7 @@ BOOL PROCESS_Init(void) ...@@ -288,6 +288,7 @@ BOOL PROCESS_Init(void)
initial_pdb.ring0_threads = 1; initial_pdb.ring0_threads = 1;
initial_pdb.group = &initial_pdb; initial_pdb.group = &initial_pdb;
initial_pdb.priority = 8; /* Normal */ initial_pdb.priority = 8; /* Normal */
initial_pdb.flags = PDB32_WIN16_PROC;
/* Initialize virtual memory management */ /* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE; if (!VIRTUAL_Init()) return FALSE;
...@@ -330,8 +331,11 @@ void PROCESS_Start(void) ...@@ -330,8 +331,11 @@ void PROCESS_Start(void)
LPTHREAD_START_ROUTINE entry; LPTHREAD_START_ROUTINE entry;
THDB *thdb = THREAD_Current(); THDB *thdb = THREAD_Current();
PDB *pdb = thdb->process; PDB *pdb = thdb->process;
NE_MODULE *pModule = (NE_MODULE *)thdb->entry_arg; /* hack */ TDB *pTask = (TDB *)GlobalLock16( pdb->task );
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
#if 0
/* Initialize the critical section */ /* Initialize the critical section */
InitializeCriticalSection( &pdb->crit_section ); InitializeCriticalSection( &pdb->crit_section );
...@@ -347,10 +351,10 @@ void PROCESS_Start(void) ...@@ -347,10 +351,10 @@ void PROCESS_Start(void)
if (!PROCESS_CreateEnvDB()) goto error; if (!PROCESS_CreateEnvDB()) goto error;
#if 0
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW) if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
cmdShow = pdb->env_db->startup_info->wShowWindow; cmdShow = pdb->env_db->startup_info->wShowWindow;
if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error; if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
#endif #endif
/* Map system DLLs into this process (from initial process) */ /* Map system DLLs into this process (from initial process) */
...@@ -358,10 +362,7 @@ void PROCESS_Start(void) ...@@ -358,10 +362,7 @@ void PROCESS_Start(void)
pdb->modref_list = PROCESS_Initial()->modref_list; pdb->modref_list = PROCESS_Initial()->modref_list;
/* Create 32-bit MODREF */ /* Create 32-bit MODREF */
{ if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
}
/* Initialize thread-local storage */ /* Initialize thread-local storage */
...@@ -463,6 +464,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env, ...@@ -463,6 +464,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
goto error; goto error;
info->hThread = server_thandle; info->hThread = server_thandle;
info->dwThreadId = (DWORD)thdb->server_tid; info->dwThreadId = (DWORD)thdb->server_tid;
thdb->startup = PROCESS_Start;
/* Duplicate the standard handles */ /* Duplicate the standard handles */
...@@ -509,20 +511,13 @@ error: ...@@ -509,20 +511,13 @@ error:
*/ */
void WINAPI ExitProcess( DWORD status ) void WINAPI ExitProcess( DWORD status )
{ {
PDB *pdb = PROCESS_Current();
TDB *pTask = (TDB *)GlobalLock16( pdb->task );
if ( pTask ) pTask->nEvents++;
MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, NULL ); MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, NULL );
if ( pTask && pTask->thdb != THREAD_Current() ) if ( THREAD_IsWin16( THREAD_Current() ) )
TerminateProcess( GetCurrentProcess(), status ); TASK_KillCurrentTask( status );
/* FIXME: should kill all running threads of this process */
pdb->exit_code = status;
__RESTORE_ES; /* Necessary for Pietrek's showseh example program */ TASK_KillTask( 0 );
TASK_KillCurrentTask( status ); TerminateProcess( GetCurrentProcess(), status );
} }
......
...@@ -54,13 +54,7 @@ THDB *THREAD_Current(void) ...@@ -54,13 +54,7 @@ THDB *THREAD_Current(void)
*/ */
BOOL THREAD_IsWin16( THDB *thdb ) BOOL THREAD_IsWin16( THDB *thdb )
{ {
if (!thdb || !thdb->process) return !thdb || !(thdb->teb.flags & TEBF_WIN32);
return TRUE;
else
{
TDB* pTask = (TDB*)GlobalLock16( thdb->process->task );
return !pTask || pTask->thdb == thdb;
}
} }
/*********************************************************************** /***********************************************************************
...@@ -188,7 +182,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb, int server_fd ) ...@@ -188,7 +182,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
initial_thdb.process = pdb; initial_thdb.process = pdb;
initial_thdb.teb.except = (void *)-1; initial_thdb.teb.except = (void *)-1;
initial_thdb.teb.self = &initial_thdb.teb; initial_thdb.teb.self = &initial_thdb.teb;
initial_thdb.teb.flags = TEBF_WIN32; initial_thdb.teb.flags = /* TEBF_WIN32 */ 0;
initial_thdb.teb.tls_ptr = initial_thdb.tls_array; initial_thdb.teb.tls_ptr = initial_thdb.tls_array;
initial_thdb.teb.process = pdb; initial_thdb.teb.process = pdb;
initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */ initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */
......
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