Commit 3e7497f2 authored by Alexandre Julliard's avatar Alexandre Julliard

Unified 16-bit and 32-bit scheduling a bit more.

parent 1af1c67d
......@@ -150,7 +150,8 @@ extern HTASK TASK_SpawnTask( struct _NE_MODULE *pModule, WORD cmdShow,
LPCSTR cmdline, BYTE len, HANDLE *hThread );
extern void TASK_ExitTask(void);
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
extern void TASK_Reschedule(void);
extern TDB *TASK_GetPtr( HTASK16 hTask );
extern TDB *TASK_GetCurrent(void);
extern void TASK_InstallTHHook( THHOOK *pNewThook );
extern void TASK_CallTaskSignalProc( UINT16 uCode, HANDLE16 hTaskOrModule );
......
......@@ -69,12 +69,31 @@ void TASK_InstallTHHook( THHOOK *pNewThhook )
*/
HTASK16 TASK_GetNextTask( HTASK16 hTask )
{
TDB* pTask = (TDB*)GlobalLock16(hTask);
TDB* pTask = TASK_GetPtr( hTask );
if (pTask->hNext) return pTask->hNext;
return (hFirstTask != hTask) ? hFirstTask : 0;
}
/***********************************************************************
* TASK_GetPtr
*/
TDB *TASK_GetPtr( HTASK16 hTask )
{
return GlobalLock16( hTask );
}
/***********************************************************************
* TASK_GetCurrent
*/
TDB *TASK_GetCurrent(void)
{
return TASK_GetPtr( GetCurrentTask() );
}
/***********************************************************************
* TASK_LinkTask
*/
......@@ -83,11 +102,11 @@ static void TASK_LinkTask( HTASK16 hTask )
HTASK16 *prevTask;
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
if (!(pTask = TASK_GetPtr( hTask ))) return;
prevTask = &hFirstTask;
while (*prevTask)
{
TDB *prevTaskPtr = (TDB *)GlobalLock16( *prevTask );
TDB *prevTaskPtr = TASK_GetPtr( *prevTask );
if (prevTaskPtr->priority >= pTask->priority) break;
prevTask = &prevTaskPtr->hNext;
}
......@@ -108,12 +127,12 @@ static void TASK_UnlinkTask( HTASK16 hTask )
prevTask = &hFirstTask;
while (*prevTask && (*prevTask != hTask))
{
pTask = (TDB *)GlobalLock16( *prevTask );
pTask = TASK_GetPtr( *prevTask );
prevTask = &pTask->hNext;
}
if (*prevTask)
{
pTask = (TDB *)GlobalLock16( *prevTask );
pTask = TASK_GetPtr( *prevTask );
*prevTask = pTask->hNext;
pTask->hNext = 0;
nTaskCount--;
......@@ -152,13 +171,13 @@ static void TASK_CreateThunks( HGLOBAL16 handle, WORD offset, WORD count )
*
* Allocate a thunk for MakeProcInstance().
*/
static SEGPTR TASK_AllocThunk( HTASK16 hTask )
static SEGPTR TASK_AllocThunk(void)
{
TDB *pTask;
THUNKS *pThunk;
WORD sel, base;
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
sel = pTask->hCSAlias;
pThunk = &pTask->thunks;
base = (int)pThunk - (int)pTask;
......@@ -187,13 +206,13 @@ static SEGPTR TASK_AllocThunk( HTASK16 hTask )
*
* Free a MakeProcInstance() thunk.
*/
static BOOL TASK_FreeThunk( HTASK16 hTask, SEGPTR thunk )
static BOOL TASK_FreeThunk( SEGPTR thunk )
{
TDB *pTask;
THUNKS *pThunk;
WORD sel, base;
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
sel = pTask->hCSAlias;
pThunk = &pTask->thunks;
base = (int)pThunk - (int)pTask;
......@@ -228,7 +247,7 @@ static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cm
hTask = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB) );
if (!hTask) return NULL;
pTask = (TDB *)GlobalLock16( hTask );
pTask = TASK_GetPtr( hTask );
FarSetOwner16( hTask, pModule->self );
/* Fill the task structure */
......@@ -340,7 +359,7 @@ static void TASK_DeleteTask( HTASK16 hTask )
TDB *pTask;
HGLOBAL16 hPDB;
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
if (!(pTask = TASK_GetPtr( hTask ))) return;
hPDB = pTask->hPDB;
pTask->magic = 0xdead; /* invalidate signature */
......@@ -439,7 +458,7 @@ void TASK_ExitTask(void)
/* Enter the Win16Lock to protect global data structures */
_EnterWin16Lock();
pTask = (TDB *)GlobalLock16( GetCurrentTask() );
pTask = TASK_GetCurrent();
if ( !pTask )
{
_LeaveWin16Lock();
......@@ -466,11 +485,11 @@ void TASK_ExitTask(void)
if( nTaskCount )
{
TDB* p = (TDB *)GlobalLock16( hFirstTask );
TDB* p = TASK_GetPtr( hFirstTask );
while( p )
{
if( p->hYieldTo == pTask->hSelf ) p->hYieldTo = 0;
p = (TDB *)GlobalLock16( p->hNext );
p = TASK_GetPtr( p->hNext );
}
}
......@@ -481,180 +500,10 @@ void TASK_ExitTask(void)
TASK_DeleteTask( pTask->hSelf );
/* ... schedule another one ... */
TASK_Reschedule();
/* ... and completely release the Win16Lock, just in case. */
ReleaseThunkLock( &lockCount );
}
/***********************************************************************
* TASK_Reschedule
*
* This is where all the magic of task-switching happens!
*
* 16-bit Windows performs non-preemptive (cooperative) multitasking.
* This means that each 16-bit task runs until it voluntarily yields
* control, at which point the scheduler gets active and selects the
* next task to run.
*
* In Wine, all processes, even 16-bit ones, are scheduled preemptively
* by the standard scheduler of the underlying OS. As many 16-bit apps
* *rely* on the behaviour of the Windows scheduler, however, we have
* to simulate that behaviour.
*
* This is achieved as follows: every 16-bit task is at time (except
* during task creation and deletion) in one of two states: either it
* is the one currently running, then the global variable hCurrentTask
* contains its task handle, or it is not currently running, then it
* is blocked on a special scheduler event, a global handle which
* is stored in the task struct.
*
* When the current task yields control, this routine gets called. Its
* purpose is to determine the next task to be active, signal the
* scheduler event of that task, and then put the current task to sleep
* waiting for *its* scheduler event to get signalled again.
*
* This routine can get called in a few other special situations as well:
*
* - On creation of a 16-bit task, the Unix process executing the task
* calls TASK_Reschedule once it has completed its initialization.
* At this point, the task needs to be blocked until its scheduler
* event is signalled the first time (this will be done by the parent
* process to get the task up and running).
*
* - When the task currently running terminates itself, this routine gets
* called and has to schedule another task, *without* blocking the
* terminating task.
*
* - When a 32-bit thread posts an event for a 16-bit task, it might be
* the case that *no* 16-bit task is currently running. In this case
* the task that has now an event pending is to be scheduled.
*
*/
void TASK_Reschedule(void)
{
TDB *pOldTask = NULL, *pNewTask = NULL;
HTASK16 hOldTask = 0, hNewTask = 0;
enum { MODE_YIELD, MODE_SLEEP, MODE_WAKEUP } mode;
DWORD lockCount;
_EnterWin16Lock();
/* Check what we need to do */
hOldTask = GetCurrentTask();
pOldTask = (TDB *)GlobalLock16( hOldTask );
TRACE( "entered with hCurrentTask %04x by hTask %04x (pid %ld)\n",
hCurrentTask, hOldTask, (long) getpid() );
if ( pOldTask && THREAD_IsWin16( NtCurrentTeb() ) )
{
/* We are called by an active (non-deleted) 16-bit task */
/* If we don't even have a current task, or else the current
task has yielded, we'll need to schedule a new task and
(possibly) put the calling task to sleep. Otherwise, we
only block the caller. */
if ( !hCurrentTask || hCurrentTask == hOldTask )
mode = MODE_YIELD;
else
mode = MODE_SLEEP;
}
else
{
/* We are called by a deleted 16-bit task or a 32-bit thread */
/* The only situation where we need to do something is if we
now do not have a current task. Then, we'll need to wake up
some task that has events pending. */
if ( !hCurrentTask || hCurrentTask == hOldTask )
mode = MODE_WAKEUP;
else
{
/* nothing to do */
_LeaveWin16Lock();
return;
}
}
/* Find a task to yield to: check for DirectedYield() */
if ( mode == MODE_YIELD && pOldTask && pOldTask->hYieldTo )
{
hNewTask = pOldTask->hYieldTo;
pNewTask = (TDB *)GlobalLock16( hNewTask );
if( !pNewTask || !pNewTask->nEvents || !pNewTask->teb) hNewTask = 0;
pOldTask->hYieldTo = 0;
}
/* Find a task to yield to: check for pending events */
if ( (mode == MODE_YIELD || mode == MODE_WAKEUP) && !hNewTask )
{
hNewTask = hFirstTask;
while (hNewTask)
{
pNewTask = (TDB *)GlobalLock16( hNewTask );
TRACE( "\ttask = %04x, events = %i\n", hNewTask, pNewTask->nEvents );
if (pNewTask->nEvents) break;
hNewTask = pNewTask->hNext;
}
if (hLockedTask && (hNewTask != hLockedTask)) hNewTask = 0;
}
/* If we are still the task with highest priority, just return ... */
if ( mode == MODE_YIELD && hNewTask && hNewTask == hCurrentTask )
{
TRACE("returning to the current task (%04x)\n", hCurrentTask );
_LeaveWin16Lock();
/* Allow Win32 threads to thunk down even while a Win16 task is
in a tight PeekMessage() or Yield() loop ... */
ReleaseThunkLock( &lockCount );
RestoreThunkLock( lockCount );
return;
}
/* If no task to yield to found, suspend 16-bit scheduler ... */
if ( mode == MODE_YIELD && !hNewTask )
{
TRACE("No currently active task\n");
hCurrentTask = 0;
}
/* If we found a task to wake up, do it ... */
if ( (mode == MODE_YIELD || mode == MODE_WAKEUP) && hNewTask )
{
TRACE("Switching to task %04x (%.8s)\n",
hNewTask, pNewTask->module_name );
pNewTask->priority++;
TASK_UnlinkTask( hNewTask );
TASK_LinkTask( hNewTask );
pNewTask->priority--;
hCurrentTask = hNewTask;
NtSetEvent( pNewTask->hEvent, NULL );
/* This is set just in case some app reads it ... */
pNewTask->ss_sp = pNewTask->teb->cur_stack;
}
/* If we need to put the current task to sleep, do it ... */
if ( (mode == MODE_YIELD || mode == MODE_SLEEP) && hOldTask != hCurrentTask )
{
NtResetEvent( pOldTask->hEvent, NULL );
ReleaseThunkLock( &lockCount );
SYSLEVEL_CheckNotLevel( 1 );
WaitForSingleObject( pOldTask->hEvent, INFINITE );
RestoreThunkLock( lockCount );
}
_LeaveWin16Lock();
}
/***********************************************************************
* InitTask (KERNEL.91)
......@@ -668,7 +517,7 @@ void WINAPI InitTask16( CONTEXT86 *context )
SEGPTR ptr;
context->Eax = 0;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return;
if (!(pTask = TASK_GetCurrent())) return;
/* Note: we need to trust that BX/CX contain the stack/heap sizes,
as some apps, notably Visual Basic apps, *modify* the heap/stack
......@@ -728,7 +577,7 @@ BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
TDB *pTask;
if (!hTask) hTask = GetCurrentTask();
pTask = (TDB *)GlobalLock16( hTask );
pTask = TASK_GetPtr( hTask );
if ( !THREAD_IsWin16( NtCurrentTeb() ) )
{
......@@ -741,11 +590,20 @@ BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
pTask->nEvents--;
return FALSE;
}
TASK_Reschedule();
/* When we get back here, we have an event */
if (pTask->teb == NtCurrentTeb())
{
DWORD lockCount;
NtResetEvent( pTask->hEvent, NULL );
ReleaseThunkLock( &lockCount );
SYSLEVEL_CheckNotLevel( 1 );
WaitForSingleObject( pTask->hEvent, INFINITE );
RestoreThunkLock( lockCount );
if (pTask->nEvents > 0) pTask->nEvents--;
}
else FIXME("for other task %04x cur=%04x\n",pTask->hSelf,GetCurrentTask());
if (pTask->nEvents > 0) pTask->nEvents--;
return TRUE;
}
......@@ -758,7 +616,7 @@ void WINAPI PostEvent16( HTASK16 hTask )
TDB *pTask;
if (!hTask) hTask = GetCurrentTask();
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
if (!(pTask = TASK_GetPtr( hTask ))) return;
if ( !THREAD_IsWin16( pTask->teb ) )
{
......@@ -768,9 +626,7 @@ void WINAPI PostEvent16( HTASK16 hTask )
pTask->nEvents++;
/* If we are a 32-bit task, we might need to wake up the 16-bit scheduler */
if ( !THREAD_IsWin16( NtCurrentTeb() ) )
TASK_Reschedule();
if (pTask->nEvents == 1) NtSetEvent( pTask->hEvent, NULL );
}
......@@ -783,14 +639,14 @@ void WINAPI SetPriority16( HTASK16 hTask, INT16 delta )
INT16 newpriority;
if (!hTask) hTask = GetCurrentTask();
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
if (!(pTask = TASK_GetPtr( hTask ))) return;
newpriority = pTask->priority + delta;
if (newpriority < -32) newpriority = -32;
else if (newpriority > 15) newpriority = 15;
pTask->priority = newpriority + 1;
TASK_UnlinkTask( hTask );
TASK_LinkTask( hTask );
TASK_UnlinkTask( pTask->hSelf );
TASK_LinkTask( pTask->hSelf );
pTask->priority--;
}
......@@ -820,17 +676,10 @@ HTASK16 WINAPI IsTaskLocked16(void)
*/
void WINAPI OldYield16(void)
{
TDB *pCurTask = (TDB *)GlobalLock16( GetCurrentTask() );
if ( !THREAD_IsWin16( NtCurrentTeb() ) )
{
FIXME("called for Win32 thread (%04x)!\n", NtCurrentTeb()->teb_sel);
return;
}
DWORD count;
if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
TASK_Reschedule();
if (pCurTask) pCurTask->nEvents--;
ReleaseThunkLock(&count);
RestoreThunkLock(count);
}
/***********************************************************************
......@@ -849,7 +698,7 @@ void WINAPI WIN32_OldYield16(void)
*/
void WINAPI DirectedYield16( HTASK16 hTask )
{
TDB *pCurTask = (TDB *)GlobalLock16( GetCurrentTask() );
TDB *pCurTask = TASK_GetCurrent();
if ( !THREAD_IsWin16( NtCurrentTeb() ) )
{
......@@ -870,7 +719,7 @@ void WINAPI DirectedYield16( HTASK16 hTask )
*/
void WINAPI Yield16(void)
{
TDB *pCurTask = (TDB *)GlobalLock16( GetCurrentTask() );
TDB *pCurTask = TASK_GetCurrent();
if (pCurTask) pCurTask->hYieldTo = 0;
if (pCurTask && pCurTask->hQueue && Callout.UserYield16) Callout.UserYield16();
......@@ -938,7 +787,7 @@ FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
if (NE_GetPtr(FarGetOwner16(hInstance))->flags & NE_FFLAGS_LIBMODULE)
return func;
thunkaddr = TASK_AllocThunk( GetCurrentTask() );
thunkaddr = TASK_AllocThunk();
if (!thunkaddr) return (FARPROC16)0;
thunk = MapSL( thunkaddr );
lfunc = MapSL( (SEGPTR)func );
......@@ -967,7 +816,7 @@ FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
void WINAPI FreeProcInstance16( FARPROC16 func )
{
TRACE("(%08lx)\n", (DWORD)func );
TASK_FreeThunk( GetCurrentTask(), (SEGPTR)func );
TASK_FreeThunk( (SEGPTR)func );
}
/**********************************************************************
......@@ -1103,7 +952,7 @@ HQUEUE16 WINAPI SetTaskQueue16( HTASK16 hTask, HQUEUE16 hQueue )
TDB *pTask;
if (!hTask) hTask = GetCurrentTask();
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
if (!(pTask = TASK_GetPtr( hTask ))) return 0;
hPrev = pTask->hQueue;
pTask->hQueue = hQueue;
......@@ -1120,7 +969,7 @@ HQUEUE16 WINAPI GetTaskQueue16( HTASK16 hTask )
TDB *pTask;
if (!hTask) hTask = GetCurrentTask();
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
if (!(pTask = TASK_GetPtr( hTask ))) return 0;
return pTask->hQueue;
}
......@@ -1154,7 +1003,7 @@ HQUEUE16 WINAPI GetThreadQueue16( DWORD thread )
else if ( HIWORD(thread) )
teb = THREAD_IdToTEB( thread );
else if ( IsTask16( (HTASK16)thread ) )
teb = ((TDB *)GlobalLock16( (HANDLE16)thread ))->teb;
teb = (TASK_GetPtr( (HANDLE16)thread ))->teb;
return (HQUEUE16)(teb? teb->queue : 0);
}
......@@ -1170,7 +1019,7 @@ VOID WINAPI SetFastQueue16( DWORD thread, HANDLE hQueue )
else if ( HIWORD(thread) )
teb = THREAD_IdToTEB( thread );
else if ( IsTask16( (HTASK16)thread ) )
teb = ((TDB *)GlobalLock16( (HANDLE16)thread ))->teb;
teb = (TASK_GetPtr( (HANDLE16)thread ))->teb;
if ( teb ) teb->queue = (HQUEUE16) hQueue;
}
......@@ -1213,7 +1062,7 @@ void WINAPI SwitchStackTo16( WORD seg, WORD ptr, WORD top )
INSTANCEDATA *pData;
UINT16 copySize;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return;
if (!(pTask = TASK_GetCurrent())) return;
if (!(pData = (INSTANCEDATA *)GlobalLock16( seg ))) return;
TRACE("old=%04x:%04x new=%04x:%04x\n",
SELECTOROF( pTask->teb->cur_stack ),
......@@ -1333,7 +1182,7 @@ DWORD WINAPI GetCurrentPDB16(void)
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
return MAKELONG(pTask->hPDB, 0); /* FIXME */
}
......@@ -1367,7 +1216,7 @@ WORD WINAPI GetExeVersion16(void)
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
return pTask->version;
}
......@@ -1378,7 +1227,7 @@ WORD WINAPI GetExeVersion16(void)
UINT16 WINAPI SetErrorMode16( UINT16 mode )
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
pTask->error_mode = mode;
return SetErrorMode( mode );
}
......@@ -1403,7 +1252,7 @@ HINSTANCE16 WINAPI GetTaskDS16(void)
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
return GlobalHandleToSel16(pTask->hInstance);
}
......@@ -1415,7 +1264,7 @@ WORD WINAPI GetDummyModuleHandleDS16(void)
TDB *pTask;
WORD selector;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
if (!(pTask->flags & TDBF_WIN32)) return 0;
selector = GlobalHandleToSel16( pTask->hModule );
CURRENT_DS = selector;
......@@ -1430,7 +1279,7 @@ BOOL16 WINAPI IsTask16( HTASK16 hTask )
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return FALSE;
if (!(pTask = TASK_GetPtr( hTask ))) return FALSE;
if (GlobalSize16( hTask ) < sizeof(TDB)) return FALSE;
return (pTask->magic == TDB_MAGIC);
}
......@@ -1454,7 +1303,7 @@ FARPROC16 WINAPI SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
FARPROC16 oldProc;
if (!hTask) hTask = GetCurrentTask();
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return NULL;
if (!(pTask = TASK_GetPtr( hTask ))) return NULL;
oldProc = pTask->userhandler;
pTask->userhandler = proc;
return oldProc;
......@@ -1468,7 +1317,7 @@ extern WORD CALLBACK TASK_CallTo16_word_wwwww(FARPROC16,WORD,WORD,WORD,WORD,WORD
/* ### stop build ### */
void TASK_CallTaskSignalProc( UINT16 uCode, HANDLE16 hTaskOrModule )
{
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
TDB *pTask = TASK_GetCurrent();
if ( !pTask || !pTask->userhandler ) return;
TASK_CallTo16_word_wwwww( pTask->userhandler,
......@@ -1491,7 +1340,7 @@ WORD WINAPI SetSigHandler16( FARPROC16 newhandler, FARPROC16* oldhandler,
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
if (!(pTask = TASK_GetCurrent())) return 0;
if (oldmode) *oldmode = pTask->signal_flags;
pTask->signal_flags = newmode;
if (oldhandler) *oldhandler = pTask->sighandler;
......@@ -1511,7 +1360,7 @@ VOID WINAPI GlobalNotify16( FARPROC16 proc )
{
TDB *pTask;
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return;
if (!(pTask = TASK_GetCurrent())) return;
pTask->discardhandler = proc;
}
......@@ -1534,7 +1383,7 @@ static inline HMODULE16 GetExePtrHelper( HANDLE16 handle, HTASK16 *hTask )
*hTask = hFirstTask;
while (*hTask)
{
TDB *pTask = (TDB *)GlobalLock16( *hTask );
TDB *pTask = TASK_GetPtr( *hTask );
if ((*hTask == handle) ||
(pTask->hInstance == handle) ||
(pTask->hQueue == handle) ||
......@@ -1553,7 +1402,7 @@ static inline HMODULE16 GetExePtrHelper( HANDLE16 handle, HTASK16 *hTask )
*hTask = hFirstTask;
while (*hTask)
{
TDB *pTask = (TDB *)GlobalLock16( *hTask );
TDB *pTask = TASK_GetPtr( *hTask );
if ((*hTask == owner) ||
(pTask->hInstance == owner) ||
(pTask->hQueue == owner) ||
......@@ -1608,7 +1457,7 @@ BOOL16 WINAPI TaskNext16( TASKENTRY *lpte )
/* make sure that task and hInstance are valid (skip initial Wine task !) */
while (1) {
pTask = (TDB *)GlobalLock16( lpte->hNext );
pTask = TASK_GetPtr( lpte->hNext );
if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
if (pTask->hInstance)
break;
......@@ -1650,7 +1499,7 @@ typedef INT (WINAPI *MessageBoxA_funcptr)(HWND hWnd, LPCSTR text, LPCSTR title,
*/
void WINAPI FatalAppExit16( UINT16 action, LPCSTR str )
{
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
TDB *pTask = TASK_GetCurrent();
if (!pTask || !(pTask->error_mode & SEM_NOGPFAULTERRORBOX))
{
......@@ -1721,7 +1570,7 @@ DWORD WINAPI GetAppCompatFlags( HTASK hTask )
TDB *pTask;
if (!hTask) hTask = GetCurrentTask();
if (!(pTask=(TDB *)GlobalLock16( (HTASK16)hTask ))) return 0;
if (!(pTask=TASK_GetPtr( (HTASK16)hTask ))) return 0;
if (GlobalSize16(hTask) < sizeof(TDB)) return 0;
return pTask->compat_flags;
}
......@@ -839,13 +839,7 @@ static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue,
iWndsLocks = WIN_SuspendWndsLock();
/* force destination task to run next, if 16 bit threads */
if ( THREAD_IsWin16(NtCurrentTeb()) && THREAD_IsWin16(destQ->teb) )
DirectedYield16( destQ->teb->htask16 );
/* wait for the result, note that 16-bit apps almost always get out of
* DirectedYield() with SMSG_HAVE_RESULT flag already set */
/* wait for the result */
while ( TRUE )
{
/*
......@@ -964,10 +958,6 @@ BOOL WINAPI ReplyMessage( LRESULT result )
/* tell the sending task that its reply is ready */
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
/* switch directly to sending task (16 bit thread only) */
if ( THREAD_IsWin16( NtCurrentTeb() ) && THREAD_IsWin16( senderQ->teb ) )
DirectedYield16( senderQ->teb->htask16 );
ret = TRUE;
}
......@@ -1134,9 +1124,6 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
if (IsTaskLocked16()) flags |= PM_NOYIELD;
/* Never yield on Win32 threads */
if (!THREAD_IsWin16(NtCurrentTeb())) flags |= PM_NOYIELD;
iWndsLocks = WIN_SuspendWndsLock();
while(1)
......@@ -1258,12 +1245,14 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
/* Check for timer messages, but yield first */
#if 0 /* FIXME */
if (!(flags & PM_NOYIELD))
{
UserYield16();
while ( QUEUE_ReceiveMessage( msgQueue ) )
;
}
#endif
if (QUEUE_TestWakeBit(msgQueue, mask & QS_TIMER))
{
......@@ -1272,8 +1261,9 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
if (peek)
{
#if 0 /* FIXME */
if (!(flags & PM_NOYIELD)) UserYield16();
#endif
QUEUE_Unlock( msgQueue );
WIN_RestoreWndsLock(iWndsLocks);
return FALSE;
......@@ -2083,64 +2073,11 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
msgQueue->wakeMask = dwWakeMask;
LeaveCriticalSection( &msgQueue->cSection );
if (THREAD_IsWin16(NtCurrentTeb()))
{
/*
* This is a temporary solution to a big problem.
* You see, the main thread of all Win32 programs is created as a 16 bit
* task. This means that if you wait on an event using Win32 synchronization
* methods, the 16 bit scheduler is stopped and things might just stop happening.
* This implements a semi-busy loop that checks the handles to wait on and
* also the message queue. When either one is ready, the wait function returns.
*
* This will all go away when the real Win32 threads are implemented for all
* the threads of an applications. Including the main thread.
*/
DWORD curTime = GetCurrentTime();
do
{
/*
* Check the handles in the list.
*/
ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 5L);
/*
* If the handles have been triggered, return.
*/
if (ret != WAIT_TIMEOUT)
break;
/*
* Then, let the 16 bit scheduler do it's thing.
*/
K32WOWYield16();
/*
* If a message matching the wait mask has arrived, return.
*/
EnterCriticalSection( &msgQueue->cSection );
if (msgQueue->changeBits & dwWakeMask)
{
LeaveCriticalSection( &msgQueue->cSection );
ret = nCount;
break;
}
LeaveCriticalSection( &msgQueue->cSection );
/*
* And continue doing this until we hit the timeout.
*/
} while ((dwMilliseconds == INFINITE) || (GetCurrentTime()-curTime < dwMilliseconds) );
}
else
{
/* Add the thread event to the handle list */
for (i = 0; i < nCount; i++)
handles[i] = pHandles[i];
handles[nCount] = msgQueue->server_queue;
ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
}
for (i = 0; i < nCount; i++) handles[i] = pHandles[i];
handles[nCount] = msgQueue->server_queue;
ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
QUEUE_Unlock( msgQueue );
return ret;
}
......
......@@ -645,22 +645,13 @@ static BOOL QUEUE_TrySetWakeBit( MESSAGEQUEUE *queue, WORD bit, BOOL always )
if ( wake )
{
/* Wake up thread waiting for message */
if ( THREAD_IsWin16( queue->teb ) )
SERVER_START_REQ( wake_queue )
{
int iWndsLock = WIN_SuspendWndsLock();
PostEvent16( queue->teb->htask16 );
WIN_RestoreWndsLock( iWndsLock );
}
else
{
SERVER_START_REQ( wake_queue )
{
req->handle = queue->server_queue;
req->bits = bit;
SERVER_CALL();
}
SERVER_END_REQ;
req->handle = queue->server_queue;
req->bits = bit;
SERVER_CALL();
}
SERVER_END_REQ;
}
return wake;
......@@ -707,19 +698,17 @@ WORD QUEUE_TestWakeBit( MESSAGEQUEUE *queue, WORD bit )
int QUEUE_WaitBits( WORD bits, DWORD timeout )
{
MESSAGEQUEUE *queue;
DWORD curTime = 0;
HQUEUE16 hQueue;
TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits);
if ( THREAD_IsWin16( NtCurrentTeb() ) && (timeout != INFINITE) )
curTime = GetTickCount();
hQueue = GetFastQueue16();
if (!(queue = QUEUE_Lock( hQueue ))) return 0;
for (;;)
{
DWORD dwlc;
EnterCriticalSection( &queue->cSection );
if (queue->changeBits & bits)
......@@ -745,40 +734,10 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
TRACE_(msg)("%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
LeaveCriticalSection( &queue->cSection );
if ( !THREAD_IsWin16( NtCurrentTeb() ) )
{
BOOL bHasWin16Lock;
DWORD dwlc;
if ( (bHasWin16Lock = _ConfirmWin16Lock()) )
{
TRACE_(msg)("bHasWin16Lock=TRUE\n");
ReleaseThunkLock( &dwlc );
}
WaitForSingleObject( queue->server_queue, timeout );
if ( bHasWin16Lock )
{
RestoreThunkLock( dwlc );
}
}
else
{
if ( timeout == INFINITE )
WaitEvent16( 0 ); /* win 16 thread, use WaitEvent */
else
{
/* check for timeout, then give control to other tasks */
if (GetTickCount() - curTime > timeout)
{
QUEUE_Unlock( queue );
return 0; /* exit with timeout */
}
K32WOWYield16();
}
}
ReleaseThunkLock( &dwlc );
if (dwlc) TRACE_(msg)("had win16 lock\n");
WaitForSingleObject( queue->server_queue, timeout );
if (dwlc) RestoreThunkLock( dwlc );
}
}
......@@ -1630,12 +1589,9 @@ void WINAPI UserYield16(void)
;
QUEUE_Unlock( queue );
/* Yield */
if ( THREAD_IsWin16( NtCurrentTeb() ) )
OldYield16();
else
WIN32_OldYield16();
OldYield16();
/* Handle sent messages again */
queue = QUEUE_Lock( GetFastQueue16() );
......
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