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

View File

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

View File

@ -90,7 +90,6 @@ static CRITICAL_SECTION qcrit = CRITICAL_SECTION_INIT("DOSVM");
static struct _DOSEVENT *pending_event, *current_event; static struct _DOSEVENT *pending_event, *current_event;
static int sig_sent; static int sig_sent;
static HANDLE event_notifier; static HANDLE event_notifier;
static CONTEXT86 *current_context;
#define SHOULD_PEND(x) \ #define SHOULD_PEND(x) \
(x && ((!current_event) || (x->priority < current_event->priority))) (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; LPDOSEVENT event, cur, prev;
if (current_context) { if (MZ_Current()) {
event = malloc(sizeof(DOSEVENT)); event = malloc(sizeof(DOSEVENT));
if (!event) { if (!event) {
ERR("out of memory allocating event entry\n"); 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; MSG msg;
DWORD waitret; while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD))
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)) {
/* got a message */ /* got a message */
DOSVM_ProcessMessage(&msg); DOSVM_ProcessMessage(&msg);
/* we don't need a TranslateMessage here */ /* we don't need a TranslateMessage here */
DispatchMessageA(&msg); 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 else
waitret = WaitForMultipleObjects(objc,objs,FALSE,INFINITE); {
if (waitret==(DWORD)-1) {
ERR_(module)( "dosvm wait error=%ld\n", GetLastError() ); 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 ) DWORD WINAPI DOSVM_Loop( HANDLE hThread )
{ {
HANDLE objs[2]; HANDLE objs[2];
@ -434,7 +428,7 @@ static WINE_EXCEPTION_FILTER(exception_handler)
* QueryPerformanceCounter() or something like that */ * QueryPerformanceCounter() or something like that */
InterlockedDecrement(&(NtCurrentTeb()->alarms)); 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); TRACE_(int)("cs:ip=%04lx:%04lx, ss:sp=%04lx:%04lx\n", context->SegCs, context->Eip, context->SegSs, context->Esp);
if (!ISV86(context)) { if (!ISV86(context)) {
ERR_(int)("@#&*%%, winedos signal handling is *still* messed up\n"); 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 ) int WINAPI DOSVM_Enter( CONTEXT86 *context )
{ {
CONTEXT86 *old_context = current_context;
current_context = context;
__TRY __TRY
{ {
__wine_enter_vm86( context ); __wine_enter_vm86( context );
@ -463,7 +454,7 @@ int WINAPI DOSVM_Enter( CONTEXT86 *context )
TRACE_(module)( "leaving vm86 mode\n" ); TRACE_(module)( "leaving vm86 mode\n" );
} }
__ENDTRY __ENDTRY
current_context = old_context;
return 0; return 0;
} }
@ -489,7 +480,7 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val)
/* another event is pending, which we should probably /* another event is pending, which we should probably
* be able to process now */ * be able to process now */
TRACE("another event pending, setting flag\n"); TRACE("another event pending, setting flag\n");
current_context->EFlags |= VIP_MASK; NtCurrentTeb()->vm86_pending |= VIP_MASK;
} }
} else { } else {
WARN("EOI without active IRQ\n"); WARN("EOI without active IRQ\n");

View File

@ -59,7 +59,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
/* Returns: AH = Scan code /* Returns: AH = Scan code
AL = ASCII character */ AL = ASCII character */
TRACE("Get Keystroke\n"); TRACE("Get Keystroke\n");
DOSVM_Int16ReadChar(&ascii, &scan, FALSE); DOSVM_Int16ReadChar(&ascii, &scan, context);
SET_AL( context, ascii ); SET_AL( context, ascii );
SET_AH( context, scan ); SET_AH( context, scan );
break; break;
@ -69,7 +69,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
/* AH = Scan code */ /* AH = Scan code */
/* AL = ASCII character */ /* AL = ASCII character */
TRACE("Check for Keystroke\n"); TRACE("Check for Keystroke\n");
if (!DOSVM_Int16ReadChar(&ascii, &scan, TRUE)) if (!DOSVM_Int16ReadChar(&ascii, &scan, NULL))
{ {
SET_ZFLAG(context); SET_ZFLAG(context);
} }
@ -111,7 +111,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
TRACE("Get Enhanced Keystroke - Partially supported\n"); TRACE("Get Enhanced Keystroke - Partially supported\n");
/* Returns: AH = Scan code /* Returns: AH = Scan code
AL = ASCII character */ AL = ASCII character */
DOSVM_Int16ReadChar(&ascii, &scan, FALSE); DOSVM_Int16ReadChar(&ascii, &scan, context);
SET_AL( context, ascii ); SET_AL( context, ascii );
SET_AH( context, scan ); SET_AH( context, scan );
break; break;
@ -122,7 +122,7 @@ void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
/* AH = Scan code */ /* AH = Scan code */
/* AL = ASCII character */ /* AL = ASCII character */
TRACE("Check for Enhanced Keystroke - Partially supported\n"); TRACE("Check for Enhanced Keystroke - Partially supported\n");
if (!DOSVM_Int16ReadChar(&ascii, &scan, TRUE)) if (!DOSVM_Int16ReadChar(&ascii, &scan, NULL))
{ {
SET_ZFLAG(context); 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; BIOSDATA *data = BIOS_DATA;
WORD CurOfs = data->NextKbdCharPtr; WORD CurOfs = data->NextKbdCharPtr;
/* check if there's data in buffer */ /* 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) if (CurOfs == data->FirstKbdCharPtr)
return 0; return FALSE;
} else {
while (CurOfs == data->FirstKbdCharPtr) {
/* no input available yet, so wait... */
DOSVM_Wait( -1, 0 );
}
} }
/* read from keyboard queue */ /* 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 (ascii) *ascii = ((BYTE*)data)[CurOfs];
if (scan) *scan = ((BYTE*)data)[CurOfs+1]; if (scan) *scan = ((BYTE*)data)[CurOfs+1];
if (!peek) {
if (waitctx)
{
CurOfs += 2; CurOfs += 2;
if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart; if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
data->NextKbdCharPtr = CurOfs; data->NextKbdCharPtr = CurOfs;
} }
return 1;
return TRUE;
} }
int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan) 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. * Reads a character from the standard input.
* Extended keycodes will be returned as two separate characters. * 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; static BYTE pending_scan = 0;
@ -102,7 +102,7 @@ static BOOL INT21_ReadChar( BYTE *input, BOOL peek )
{ {
if (input) if (input)
*input = pending_scan; *input = pending_scan;
if (!peek) if (waitctx)
pending_scan = 0; pending_scan = 0;
return TRUE; return TRUE;
} }
@ -110,12 +110,12 @@ static BOOL INT21_ReadChar( BYTE *input, BOOL peek )
{ {
BYTE ascii; BYTE ascii;
BYTE scan; BYTE scan;
if (!DOSVM_Int16ReadChar( &ascii, &scan, peek )) if (!DOSVM_Int16ReadChar( &ascii, &scan, waitctx ))
return FALSE; return FALSE;
if (input) if (input)
*input = ascii; *input = ascii;
if (!peek && !ascii) if (waitctx && !ascii)
pending_scan = scan; pending_scan = scan;
return TRUE; return TRUE;
} }
@ -328,7 +328,7 @@ static void INT21_BufferedInput( CONTEXT86 *context )
BYTE ascii; BYTE ascii;
BYTE scan; BYTE scan;
DOSVM_Int16ReadChar( &ascii, &scan, FALSE ); DOSVM_Int16ReadChar( &ascii, &scan, context );
if (ascii == '\r' || ascii == '\n') if (ascii == '\r' || ascii == '\n')
{ {
@ -1312,7 +1312,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{ {
BYTE ascii; BYTE ascii;
TRACE("DIRECT CHARACTER INPUT WITH ECHO\n"); TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
INT21_ReadChar( &ascii, FALSE ); INT21_ReadChar( &ascii, context );
SET_AL( context, ascii ); SET_AL( context, ascii );
/* /*
* FIXME: What to echo when extended keycodes are read? * FIXME: What to echo when extended keycodes are read?
@ -1337,10 +1337,10 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{ {
TRACE("Direct Console Input\n"); TRACE("Direct Console Input\n");
if (INT21_ReadChar( NULL, TRUE )) if (INT21_ReadChar( NULL, NULL ))
{ {
BYTE ascii; BYTE ascii;
INT21_ReadChar( &ascii, FALSE ); INT21_ReadChar( &ascii, context );
SET_AL( context, ascii ); SET_AL( context, ascii );
RESET_ZFLAG( context ); RESET_ZFLAG( context );
} }
@ -1367,7 +1367,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{ {
BYTE ascii; BYTE ascii;
TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n"); TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
INT21_ReadChar( &ascii, FALSE ); INT21_ReadChar( &ascii, context );
SET_AL( context, ascii ); SET_AL( context, ascii );
} }
break; break;
@ -1376,7 +1376,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{ {
BYTE ascii; BYTE ascii;
TRACE("CHARACTER INPUT WITHOUT ECHO\n"); TRACE("CHARACTER INPUT WITHOUT ECHO\n");
INT21_ReadChar( &ascii, FALSE ); INT21_ReadChar( &ascii, context );
SET_AL( context, ascii ); SET_AL( context, ascii );
} }
break; break;
@ -1414,7 +1414,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
case 0x0b: /* GET STDIN STATUS */ case 0x0b: /* GET STDIN STATUS */
TRACE( "GET STDIN STATUS\n" ); TRACE( "GET STDIN STATUS\n" );
{ {
if (INT21_ReadChar( NULL, TRUE )) if (INT21_ReadChar( NULL, NULL ))
SET_AL( context, 0xff ); /* character available */ SET_AL( context, 0xff ); /* character available */
else else
SET_AL( context, 0 ); /* no character available */ SET_AL( context, 0 ); /* no character available */