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:
parent
40bebee7ce
commit
e2ae56e0b9
|
@ -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];
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject )
|
||||
{
|
||||
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)
|
||||
/***********************************************************************
|
||||
* DOSVM_Wait
|
||||
*
|
||||
* Wait for asynchronous events. This routine temporarily enables
|
||||
* interrupts and waits until some asynchronous event has been
|
||||
* processed.
|
||||
*/
|
||||
void WINAPI DOSVM_Wait( CONTEXT86 *waitctx )
|
||||
{
|
||||
if (SHOULD_PEND(pending_event))
|
||||
{
|
||||
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;
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
{
|
||||
HANDLE objs[2];
|
||||
int objc = DOSVM_IsWin16() ? 2 : 1;
|
||||
DWORD waitret;
|
||||
|
||||
if (waitret==(DWORD)-1) {
|
||||
ERR_(module)("dosvm wait error=%ld\n",GetLastError());
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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");
|
||||
|
|
|
@ -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;
|
||||
BIOSDATA *data = BIOS_DATA;
|
||||
WORD CurOfs = data->NextKbdCharPtr;
|
||||
|
||||
/* check if there's data in buffer */
|
||||
if (peek) {
|
||||
if (CurOfs == data->FirstKbdCharPtr)
|
||||
return 0;
|
||||
} else {
|
||||
while (CurOfs == data->FirstKbdCharPtr) {
|
||||
/* no input available yet, so wait... */
|
||||
DOSVM_Wait( -1, 0 );
|
||||
/* check if there's data in buffer */
|
||||
if (waitctx)
|
||||
{
|
||||
/* wait until input is available... */
|
||||
while (CurOfs == data->FirstKbdCharPtr)
|
||||
DOSVM_Wait( waitctx );
|
||||
}
|
||||
}
|
||||
/* read from keyboard queue */
|
||||
TRACE("(%p,%p,%d) -> %02x %02x\n",ascii,scan,peek,((BYTE*)data)[CurOfs],((BYTE*)data)[CurOfs+1]);
|
||||
if (ascii) *ascii = ((BYTE*)data)[CurOfs];
|
||||
if (scan) *scan = ((BYTE*)data)[CurOfs+1];
|
||||
if (!peek) {
|
||||
CurOfs += 2;
|
||||
if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
|
||||
data->NextKbdCharPtr = CurOfs;
|
||||
}
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
if (CurOfs == data->FirstKbdCharPtr)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* read from keyboard queue */
|
||||
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 (waitctx)
|
||||
{
|
||||
CurOfs += 2;
|
||||
if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
|
||||
data->NextKbdCharPtr = CurOfs;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan)
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue