Run Win32 processes in their own threads.
Process exit sequence adapted.
This commit is contained in:
parent
f016752b45
commit
93b23d746d
|
@ -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);
|
||||
|
|
193
loader/task.c
193
loader/task.c
|
@ -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( THREAD_Current() ) )
|
||||
OldYield16();
|
||||
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();
|
||||
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 );
|
||||
if ( THREAD_IsWin16( THREAD_Current() ) )
|
||||
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_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 */
|
||||
|
|
Loading…
Reference in New Issue