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,
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
UINT16 cmdShow );
extern void TASK_StartTask( HTASK16 hTask );
extern void TASK_KillTask( HTASK16 hTask );
extern void TASK_KillCurrentTask( INT16 exitCode );
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
extern BOOL TASK_Reschedule(void);
......
......@@ -57,7 +57,7 @@ THHOOK *pThhook = &DefaultThhook;
static HTASK16 hTaskToKill = 0;
static UINT16 nTaskCount = 0;
static void TASK_YieldToSystem(TDB*);
static void TASK_YieldToSystem( void );
extern BOOL THREAD_InitDone;
......@@ -240,48 +240,8 @@ static void TASK_CallToStart(void)
if (pModule->flags & NE_FFLAGS_WIN32)
{
/* FIXME: all this is an ugly hack */
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
ERR( task, "Called for Win32 task!\n" );
ExitProcess( 1 );
}
else if (pModule->dos_image)
{
......@@ -356,7 +316,7 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
/* Fill the task structure */
pTask->nEvents = 1; /* So the task can be started */
pTask->nEvents = 0;
pTask->hSelf = hTask;
pTask->flags = 0;
......@@ -498,6 +458,9 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
*/
void TASK_StartTask( HTASK16 hTask )
{
TDB *pTask = (TDB *)GlobalLock16( hTask );
if ( !pTask ) return;
/* Add the task to the linked list */
SYSLEVEL_EnterWin16Lock();
......@@ -511,15 +474,26 @@ void TASK_StartTask( HTASK16 hTask )
if ( TASK_AddTaskEntryBreakpoint )
TASK_AddTaskEntryBreakpoint( hTask );
/* Get the task up and running. If we ourselves are a 16-bit task,
we simply Yield(). If we are 32-bit however, we need to signal
the main process somehow (NOT YET IMPLEMENTED!) */
/* Get the task up and running. */
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() ) )
OldYield16();
if ( THREAD_IsWin16( THREAD_Current() ) )
OldYield16();
else
EVENT_WakeUp();
}
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 )
GlobalFreeAll16( hPDB );
}
/***********************************************************************
* 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.
* TASK_KillTask
*/
void TASK_KillCurrentTask( INT16 exitCode )
void TASK_KillTask( HTASK16 hTask )
{
TDB* pTask = (TDB*) GlobalLock16( GetCurrentTask() );
NE_MODULE* pModule = NE_GetPtr( pTask->hModule );
if (!pTask) USER_ExitWindows(); /* No current task yet */
TDB *pTask;
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;
}
/* Enter the Win16Lock to protect global data structures
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 );
TRACE(task, "Killing task %04x\n", hTask );
/* Delete active sockets */
......@@ -598,9 +560,12 @@ void TASK_KillCurrentTask( INT16 exitCode )
WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi );
#ifdef MZ_SUPPORTED
{
/* Kill DOS VM task */
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
if ( pModule->lpDosTask )
MZ_KillModule( pModule->lpDosTask );
}
#endif
/* Perform USER cleanup */
......@@ -609,13 +574,6 @@ void TASK_KillCurrentTask( INT16 exitCode )
pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
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)
{
TRACE(task, "this is the last task, exiting\n" );
......@@ -631,22 +589,71 @@ void TASK_KillCurrentTask( INT16 exitCode )
Callout.PostAppMessage16( PROCESS_Initial()->task, WM_NULL, 0, 0 );
/* Remove the task from the list to be sure we never switch back to it */
TASK_UnlinkTask( hCurrentTask );
TASK_UnlinkTask( hTask );
if( nTaskCount )
{
TDB* p = (TDB *)GlobalLock16( hFirstTask );
while( p )
{
if( p->hYieldTo == hCurrentTask ) p->hYieldTo = 0;
if( p->hYieldTo == hTask ) p->hYieldTo = 0;
p = (TDB *)GlobalLock16( p->hNext );
}
}
hTaskToKill = hCurrentTask;
hLockedTask = 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() */
......@@ -824,7 +831,7 @@ BOOL TASK_Reschedule(void)
* Scheduler interface, this way we ensure that all "unsafe" events are
* processed outside the scheduler.
*/
void TASK_YieldToSystem(TDB* pTask)
static void TASK_YieldToSystem( void )
{
if ( !THREAD_IsWin16( THREAD_Current() ) )
{
......@@ -944,7 +951,7 @@ BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
pTask->nEvents--;
return FALSE;
}
TASK_YieldToSystem(pTask);
TASK_YieldToSystem();
/* When we get back here, we have an event */
......@@ -963,6 +970,12 @@ void WINAPI PostEvent16( HTASK16 hTask )
if (!hTask) hTask = GetCurrentTask();
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++;
if ( !THREAD_IsWin16( THREAD_Current() ) )
......@@ -1028,7 +1041,7 @@ void WINAPI OldYield16(void)
}
if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
TASK_YieldToSystem(pCurTask);
TASK_YieldToSystem();
if (pCurTask) pCurTask->nEvents--;
}
......
......@@ -288,6 +288,7 @@ BOOL PROCESS_Init(void)
initial_pdb.ring0_threads = 1;
initial_pdb.group = &initial_pdb;
initial_pdb.priority = 8; /* Normal */
initial_pdb.flags = PDB32_WIN16_PROC;
/* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE;
......@@ -330,8 +331,11 @@ void PROCESS_Start(void)
LPTHREAD_START_ROUTINE entry;
THDB *thdb = THREAD_Current();
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 */
InitializeCriticalSection( &pdb->crit_section );
......@@ -347,10 +351,10 @@ void PROCESS_Start(void)
if (!PROCESS_CreateEnvDB()) goto error;
#if 0
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
cmdShow = pdb->env_db->startup_info->wShowWindow;
if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
#endif
/* Map system DLLs into this process (from initial process) */
......@@ -358,10 +362,7 @@ void PROCESS_Start(void)
pdb->modref_list = PROCESS_Initial()->modref_list;
/* Create 32-bit MODREF */
{
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
}
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
/* Initialize thread-local storage */
......@@ -463,6 +464,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
goto error;
info->hThread = server_thandle;
info->dwThreadId = (DWORD)thdb->server_tid;
thdb->startup = PROCESS_Start;
/* Duplicate the standard handles */
......@@ -509,20 +511,13 @@ error:
*/
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 );
if ( pTask && pTask->thdb != THREAD_Current() )
TerminateProcess( GetCurrentProcess(), status );
/* FIXME: should kill all running threads of this process */
pdb->exit_code = status;
if ( THREAD_IsWin16( THREAD_Current() ) )
TASK_KillCurrentTask( status );
__RESTORE_ES; /* Necessary for Pietrek's showseh example program */
TASK_KillCurrentTask( status );
TASK_KillTask( 0 );
TerminateProcess( GetCurrentProcess(), status );
}
......
......@@ -54,13 +54,7 @@ THDB *THREAD_Current(void)
*/
BOOL THREAD_IsWin16( THDB *thdb )
{
if (!thdb || !thdb->process)
return TRUE;
else
{
TDB* pTask = (TDB*)GlobalLock16( thdb->process->task );
return !pTask || pTask->thdb == thdb;
}
return !thdb || !(thdb->teb.flags & TEBF_WIN32);
}
/***********************************************************************
......@@ -188,7 +182,7 @@ THDB *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;
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 */
......
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