Remove obsolete code from DOSVM_Wait.

Prepare DOSVM_Wait for handling nested interrupts in both real and
protected mode.
Provide temporary workaround for keyboard related deadlock.
This commit is contained in:
Jukka Heinonen 2003-05-02 20:12:52 +00:00 committed by Alexandre Julliard
parent 40bebee7ce
commit e2ae56e0b9
5 changed files with 124 additions and 113 deletions

View File

@ -282,7 +282,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
/* check for new keyboard input */
while (CurOfs == bios->FirstKbdCharPtr) {
/* no input available yet, so wait... */
DOSVM_Wait( -1, 0 );
DOSVM_Wait( ctx );
}
/* read from keyboard queue (call int16?) */
data = ((WORD*)bios)[CurOfs];
@ -301,7 +301,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
/* check for new keyboard input */
while (CurOfs == bios->FirstKbdCharPtr) {
/* no input available yet, so wait... */
DOSVM_Wait( -1, 0 );
DOSVM_Wait( ctx );
}
/* read from keyboard queue (call int16?) */
data = ((WORD*)bios)[CurOfs];

View File

@ -75,8 +75,8 @@ typedef void (*DOSRELAY)(CONTEXT86*,void*);
typedef void (WINAPI *RMCBPROC)(CONTEXT86*);
typedef void (WINAPI *INTPROC)(CONTEXT86*);
#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */
#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */
#define DOS_PRIORITY_REALTIME 1 /* IRQ0 - FIXME: should be 0 */
#define DOS_PRIORITY_KEYBOARD 0 /* IRQ1 - FIXME: should be 1 */
#define DOS_PRIORITY_VGA 2 /* IRQ9 */
#define DOS_PRIORITY_MOUSE 5 /* IRQ12 */
#define DOS_PRIORITY_SERIAL 10 /* IRQ4 */
@ -106,7 +106,7 @@ extern BOOL DOSVM_IsWin16(void);
/* dosvm.c */
extern INT WINAPI DOSVM_Enter( CONTEXT86 *context );
extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject );
extern void WINAPI DOSVM_Wait( CONTEXT86 * );
extern DWORD WINAPI DOSVM_Loop( HANDLE hThread );
extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data );
extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
@ -180,7 +180,7 @@ extern void WINAPI DOSVM_Int1aHandler(CONTEXT86*);
/* int16.c */
extern void WINAPI DOSVM_Int16Handler(CONTEXT86*);
extern int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek);
extern BOOL WINAPI DOSVM_Int16ReadChar( BYTE *, BYTE *, CONTEXT86 * );
extern int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan);
/* int17.c */

View File

@ -90,7 +90,6 @@ static CRITICAL_SECTION qcrit = CRITICAL_SECTION_INIT("DOSVM");
static struct _DOSEVENT *pending_event, *current_event;
static int sig_sent;
static HANDLE event_notifier;
static CONTEXT86 *current_context;
#define SHOULD_PEND(x) \
(x && ((!current_event) || (x->priority < current_event->priority)))
@ -140,7 +139,7 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
{
LPDOSEVENT event, cur, prev;
if (current_context) {
if (MZ_Current()) {
event = malloc(sizeof(DOSEVENT));
if (!event) {
ERR("out of memory allocating event entry\n");
@ -259,79 +258,74 @@ static void DOSVM_ProcessMessage(MSG *msg)
}
}
/***********************************************************************
* Wait (WINEDOS.@)
* DOSVM_Wait
*
* Wait for asynchronous events. This routine temporarily enables
* interrupts and waits until some asynchronous event has been
* processed.
*/
void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject )
void WINAPI DOSVM_Wait( CONTEXT86 *waitctx )
{
if (SHOULD_PEND(pending_event))
{
/*
* FIXME: This does not work in protected mode DOS programs.
* FIXME: If we have pending IRQ which has 16-bit handler,
* DOSVM_SendQueuedEvents may stuck in which case application
* deadlocks. This is why keyboard events must have top
* priority (default timer IRQ handler is 16-bit code).
* FIXME: Critical section locking is broken.
*/
CONTEXT86 context = *waitctx;
IF_SET(&context);
SET_PEND(&context);
DOSVM_SendQueuedEvents(&context);
}
else
{
HANDLE objs[2];
int objc = DOSVM_IsWin16() ? 2 : 1;
DWORD waitret;
objs[0] = event_notifier;
objs[1] = GetStdHandle(STD_INPUT_HANDLE);
waitret = MsgWaitForMultipleObjects( objc, objs, FALSE,
INFINITE, QS_ALLINPUT );
if (waitret == WAIT_OBJECT_0)
{
/*
* New pending event has been queued, we ignore it
* here because it will be processed on next call to
* DOSVM_Wait.
*/
}
else if (objc == 2 && waitret == WAIT_OBJECT_0 + 1)
{
DOSVM_ProcessConsole();
}
else if (waitret == WAIT_OBJECT_0 + objc)
{
MSG msg;
DWORD waitret;
HANDLE objs[3];
int objc;
BOOL got_msg = FALSE;
objs[0]=GetStdHandle(STD_INPUT_HANDLE);
objs[1]=event_notifier;
objs[2]=hObject;
objc=hObject?3:2;
do {
/* check for messages (waste time before the response check below) */
if (PeekMessageA)
while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD))
{
while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
/* got a message */
DOSVM_ProcessMessage(&msg);
/* we don't need a TranslateMessage here */
DispatchMessageA(&msg);
got_msg = TRUE;
}
}
chk_console_input:
if (!got_msg) {
/* check for console input */
INPUT_RECORD msg;
DWORD num;
if (PeekConsoleInputA(objs[0],&msg,1,&num) && num) {
DOSVM_ProcessConsole();
got_msg = TRUE;
}
}
if (read_pipe == -1) {
/* dispatch pending events */
if (SHOULD_PEND(pending_event)) {
CONTEXT86 context = *current_context;
IF_SET(&context);
SET_PEND(&context);
DOSVM_SendQueuedEvents(&context);
got_msg = TRUE;
}
if (got_msg) break;
} else {
fd_set readfds;
struct timeval timeout={0,0};
/* quick check for response from dosmod
* (faster than doing the full blocking wait, if data already available) */
FD_ZERO(&readfds); FD_SET(read_pipe,&readfds);
if (select(read_pipe+1,&readfds,NULL,NULL,&timeout)>0)
break;
}
/* nothing yet, block while waiting for something to do */
if (MsgWaitForMultipleObjects)
waitret = MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT);
else
waitret = WaitForMultipleObjects(objc,objs,FALSE,INFINITE);
if (waitret==(DWORD)-1) {
{
ERR_(module)( "dosvm wait error=%ld\n", GetLastError() );
}
if ((read_pipe != -1) && hObject) {
if (waitret==(WAIT_OBJECT_0+2)) break;
}
if (waitret==WAIT_OBJECT_0)
goto chk_console_input;
} while (TRUE);
}
DWORD WINAPI DOSVM_Loop( HANDLE hThread )
{
HANDLE objs[2];
@ -434,7 +428,7 @@ static WINE_EXCEPTION_FILTER(exception_handler)
* QueryPerformanceCounter() or something like that */
InterlockedDecrement(&(NtCurrentTeb()->alarms));
}
TRACE_(int)("context=%p, current=%p\n", context, current_context);
TRACE_(int)("context=%p\n", context);
TRACE_(int)("cs:ip=%04lx:%04lx, ss:sp=%04lx:%04lx\n", context->SegCs, context->Eip, context->SegSs, context->Esp);
if (!ISV86(context)) {
ERR_(int)("@#&*%%, winedos signal handling is *still* messed up\n");
@ -450,9 +444,6 @@ static WINE_EXCEPTION_FILTER(exception_handler)
int WINAPI DOSVM_Enter( CONTEXT86 *context )
{
CONTEXT86 *old_context = current_context;
current_context = context;
__TRY
{
__wine_enter_vm86( context );
@ -463,7 +454,7 @@ int WINAPI DOSVM_Enter( CONTEXT86 *context )
TRACE_(module)( "leaving vm86 mode\n" );
}
__ENDTRY
current_context = old_context;
return 0;
}
@ -489,7 +480,7 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val)
/* another event is pending, which we should probably
* be able to process now */
TRACE("another event pending, setting flag\n");
current_context->EFlags |= VIP_MASK;
NtCurrentTeb()->vm86_pending |= VIP_MASK;
}
} else {
WARN("EOI without active IRQ\n");

View File

@ -59,7 +59,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
/* Returns: AH = Scan code
AL = ASCII character */
TRACE("Get Keystroke\n");
DOSVM_Int16ReadChar(&ascii, &scan, FALSE);
DOSVM_Int16ReadChar(&ascii, &scan, context);
SET_AL( context, ascii );
SET_AH( context, scan );
break;
@ -69,7 +69,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
/* AH = Scan code */
/* AL = ASCII character */
TRACE("Check for Keystroke\n");
if (!DOSVM_Int16ReadChar(&ascii, &scan, TRUE))
if (!DOSVM_Int16ReadChar(&ascii, &scan, NULL))
{
SET_ZFLAG(context);
}
@ -111,7 +111,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
TRACE("Get Enhanced Keystroke - Partially supported\n");
/* Returns: AH = Scan code
AL = ASCII character */
DOSVM_Int16ReadChar(&ascii, &scan, FALSE);
DOSVM_Int16ReadChar(&ascii, &scan, context);
SET_AL( context, ascii );
SET_AH( context, scan );
break;
@ -122,7 +122,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
/* AH = Scan code */
/* AL = ASCII character */
TRACE("Check for Enhanced Keystroke - Partially supported\n");
if (!DOSVM_Int16ReadChar(&ascii, &scan, TRUE))
if (!DOSVM_Int16ReadChar(&ascii, &scan, NULL))
{
SET_ZFLAG(context);
}
@ -145,31 +145,51 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
}
}
int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
/**********************************************************************
* DOSVM_Int16ReadChar
*
* Either peek into keyboard buffer or wait for next keystroke.
*
* If waitctx is NULL, return TRUE if buffer had keystrokes and
* FALSE if buffer is empty. Returned keystroke will be left into buffer.
*
* If waitctx is non-NULL, wait until keystrokes are available.
* Return value will always be TRUE and returned keystroke will be
* removed from buffer.
*/
int WINAPI DOSVM_Int16ReadChar(BYTE *ascii, BYTE *scan, CONTEXT86 *waitctx)
{
BIOSDATA *data = BIOS_DATA;
WORD CurOfs = data->NextKbdCharPtr;
/* check if there's data in buffer */
if (peek) {
if (waitctx)
{
/* wait until input is available... */
while (CurOfs == data->FirstKbdCharPtr)
DOSVM_Wait( waitctx );
}
else
{
if (CurOfs == data->FirstKbdCharPtr)
return 0;
} else {
while (CurOfs == data->FirstKbdCharPtr) {
/* no input available yet, so wait... */
DOSVM_Wait( -1, 0 );
}
return FALSE;
}
/* read from keyboard queue */
TRACE("(%p,%p,%d) -> %02x %02x\n",ascii,scan,peek,((BYTE*)data)[CurOfs],((BYTE*)data)[CurOfs+1]);
TRACE( "(%p,%p,%p) -> %02x %02x\n", ascii, scan, waitctx,
((BYTE*)data)[CurOfs], ((BYTE*)data)[CurOfs+1] );
if (ascii) *ascii = ((BYTE*)data)[CurOfs];
if (scan) *scan = ((BYTE*)data)[CurOfs+1];
if (!peek) {
if (waitctx)
{
CurOfs += 2;
if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
data->NextKbdCharPtr = CurOfs;
}
return 1;
return TRUE;
}
int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan)

View File

@ -94,7 +94,7 @@ typedef struct _INT21_HEAP {
* Reads a character from the standard input.
* Extended keycodes will be returned as two separate characters.
*/
static BOOL INT21_ReadChar( BYTE *input, BOOL peek )
static BOOL INT21_ReadChar( BYTE *input, CONTEXT86 *waitctx )
{
static BYTE pending_scan = 0;
@ -102,7 +102,7 @@ static BOOL INT21_ReadChar( BYTE *input, BOOL peek )
{
if (input)
*input = pending_scan;
if (!peek)
if (waitctx)
pending_scan = 0;
return TRUE;
}
@ -110,12 +110,12 @@ static BOOL INT21_ReadChar( BYTE *input, BOOL peek )
{
BYTE ascii;
BYTE scan;
if (!DOSVM_Int16ReadChar( &ascii, &scan, peek ))
if (!DOSVM_Int16ReadChar( &ascii, &scan, waitctx ))
return FALSE;
if (input)
*input = ascii;
if (!peek && !ascii)
if (waitctx && !ascii)
pending_scan = scan;
return TRUE;
}
@ -328,7 +328,7 @@ static void INT21_BufferedInput( CONTEXT86 *context )
BYTE ascii;
BYTE scan;
DOSVM_Int16ReadChar( &ascii, &scan, FALSE );
DOSVM_Int16ReadChar( &ascii, &scan, context );
if (ascii == '\r' || ascii == '\n')
{
@ -1312,7 +1312,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{
BYTE ascii;
TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
INT21_ReadChar( &ascii, FALSE );
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
/*
* FIXME: What to echo when extended keycodes are read?
@ -1337,10 +1337,10 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{
TRACE("Direct Console Input\n");
if (INT21_ReadChar( NULL, TRUE ))
if (INT21_ReadChar( NULL, NULL ))
{
BYTE ascii;
INT21_ReadChar( &ascii, FALSE );
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
RESET_ZFLAG( context );
}
@ -1367,7 +1367,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{
BYTE ascii;
TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
INT21_ReadChar( &ascii, FALSE );
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
}
break;
@ -1376,7 +1376,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{
BYTE ascii;
TRACE("CHARACTER INPUT WITHOUT ECHO\n");
INT21_ReadChar( &ascii, FALSE );
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
}
break;
@ -1414,7 +1414,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
case 0x0b: /* GET STDIN STATUS */
TRACE( "GET STDIN STATUS\n" );
{
if (INT21_ReadChar( NULL, TRUE ))
if (INT21_ReadChar( NULL, NULL ))
SET_AL( context, 0xff ); /* character available */
else
SET_AL( context, 0 ); /* no character available */