Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
75e87b44
Commit
75e87b44
authored
Jun 20, 2003
by
Jukka Heinonen
Committed by
Alexandre Julliard
Jun 20, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add int31 VIF manipulation functions.
Fix asynchronous event locking. Make asynchronous event handling support DPMI.
parent
0a970ce0
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
135 additions
and
61 deletions
+135
-61
dosvm.c
dlls/winedos/dosvm.c
+115
-60
int31.c
dlls/winedos/int31.c
+20
-1
No files found.
dlls/winedos/dosvm.c
View file @
75e87b44
...
...
@@ -70,14 +70,6 @@ WORD DOSVM_retval = 0;
# include <sys/mman.h>
#endif
#define IF_CLR(ctx) ((ctx)->EFlags &= ~VIF_MASK)
#define IF_SET(ctx) ((ctx)->EFlags |= VIF_MASK)
#define IF_ENABLED(ctx) ((ctx)->EFlags & VIF_MASK)
#define SET_PEND(ctx) ((ctx)->EFlags |= VIP_MASK)
#define CLR_PEND(ctx) ((ctx)->EFlags &= ~VIP_MASK)
#define IS_PEND(ctx) ((ctx)->EFlags & VIP_MASK)
#undef TRY_PICRETURN
typedef
struct
_DOSEVENT
{
int
irq
,
priority
;
...
...
@@ -88,7 +80,6 @@ typedef struct _DOSEVENT {
static
CRITICAL_SECTION
qcrit
=
CRITICAL_SECTION_INIT
(
"DOSVM"
);
static
struct
_DOSEVENT
*
pending_event
,
*
current_event
;
static
int
sig_sent
;
static
HANDLE
event_notifier
;
...
...
@@ -113,50 +104,122 @@ static BOOL DOSVM_HasPendingEvents( void )
}
static
void
DOSVM_SendQueuedEvent
(
CONTEXT86
*
context
)
/***********************************************************************
* DOSVM_SendOneEvent
*
* Process single pending event.
*
* This function should be called with queue critical section locked.
* The function temporarily releases the critical section if it is
* possible that internal interrupt handler or user procedure will
* be called. This is because we may otherwise get a deadlock if
* another thread is waiting for the same critical section.
*/
static
void
DOSVM_SendOneEvent
(
CONTEXT86
*
context
)
{
LPDOSEVENT
event
=
pending_event
;
LPDOSEVENT
event
=
pending_event
;
if
(
DOSVM_HasPendingEvents
())
{
/* remove from "pending" list */
/* Remove from pending events list. */
pending_event
=
event
->
next
;
/* process event */
if
(
event
->
irq
>=
0
)
{
/* it's an IRQ, move it to "current" list */
event
->
next
=
current_event
;
current_event
=
event
;
TRACE
(
"dispatching IRQ %d
\n
"
,
event
->
irq
);
/* note that if DOSVM_SimulateInt calls an internal interrupt directly,
* current_event might be cleared (and event freed) in this very call! */
DOSVM_HardwareInterruptRM
(
context
,
(
event
->
irq
<
8
)
?
(
event
->
irq
+
8
)
:
(
event
->
irq
-
8
+
0x70
)
);
}
else
{
/* callback event */
TRACE
(
"dispatching callback event
\n
"
);
(
*
event
->
relay
)(
context
,
event
->
data
);
free
(
event
);
/* Process active event. */
if
(
event
->
irq
>=
0
)
{
BYTE
intnum
=
(
event
->
irq
<
8
)
?
(
event
->
irq
+
8
)
:
(
event
->
irq
-
8
+
0x70
);
/* Event is an IRQ, move it to current events list. */
event
->
next
=
current_event
;
current_event
=
event
;
TRACE
(
"Dispatching IRQ %d.
\n
"
,
event
->
irq
);
if
(
ISV86
(
context
))
{
/*
* Note that if DOSVM_HardwareInterruptRM calls an internal
* interrupt directly, current_event might be cleared
* (and event freed) in this call.
*/
LeaveCriticalSection
(
&
qcrit
);
DOSVM_HardwareInterruptRM
(
context
,
intnum
);
EnterCriticalSection
(
&
qcrit
);
}
else
{
/*
* This routine only modifies current context so it is
* not necessary to release critical section.
*/
DOSVM_HardwareInterruptPM
(
context
,
intnum
);
}
}
else
{
/* Callback event. */
TRACE
(
"Dispatching callback event.
\n
"
);
LeaveCriticalSection
(
&
qcrit
);
(
*
event
->
relay
)(
context
,
event
->
data
);
EnterCriticalSection
(
&
qcrit
);
free
(
event
);
}
}
if
(
!
DOSVM_HasPendingEvents
())
{
TRACE
(
"clearing Pending flag
\n
"
);
CLR_PEND
(
context
);
}
}
static
void
DOSVM_SendQueuedEvents
(
CONTEXT86
*
context
)
/***********************************************************************
* DOSVM_SendQueuedEvents
*
* As long as interrupts are enabled, process all pending events
* that are not blocked by currently active event.
*/
static
void
DOSVM_SendQueuedEvents
(
CONTEXT86
*
context
)
{
/* we will send all queued events as long as interrupts are enabled,
* but IRQ events will disable interrupts again */
while
(
IS_PEND
(
context
)
&&
IF_ENABLED
(
context
))
DOSVM_SendQueuedEvent
(
context
);
EnterCriticalSection
(
&
qcrit
);
TRACE
(
"Called in %s mode %s events pending (time=%ld)
\n
"
,
ISV86
(
context
)
?
"real"
:
"protected"
,
DOSVM_HasPendingEvents
()
?
"with"
:
"without"
,
GetTickCount
()
);
TRACE
(
"cs:ip=%04lx:%08lx, ss:sp=%04lx:%08lx
\n
"
,
context
->
SegCs
,
context
->
Eip
,
context
->
SegSs
,
context
->
Esp
);
while
(
DOSVM_HasPendingEvents
()
&&
(
ISV86
(
context
)
?
(
context
->
EFlags
&
VIF_MASK
)
:
NtCurrentTeb
()
->
dpmi_vif
))
{
DOSVM_SendOneEvent
(
context
);
/*
* Event handling may have turned pending events flag on.
* We disable it here because this prevents some
* unnecessary calls to this function.
*/
NtCurrentTeb
()
->
vm86_pending
=
0
;
}
if
(
DOSVM_HasPendingEvents
())
{
/*
* Interrupts disabled, but there are still
* pending events, make sure that pending flag is turned on.
*/
TRACE
(
"Another event is pending, setting VIP flag.
\n
"
);
NtCurrentTeb
()
->
vm86_pending
|=
VIP_MASK
;
}
LeaveCriticalSection
(
&
qcrit
);
}
/***********************************************************************
* QueueEvent (WINEDOS.@)
*/
void
WINAPI
DOSVM_QueueEvent
(
INT
irq
,
INT
priority
,
DOSRELAY
relay
,
LPVOID
data
)
{
LPDOSEVENT
event
,
cur
,
prev
;
BOOL
old_pending
;
if
(
MZ_Current
())
{
event
=
malloc
(
sizeof
(
DOSEVENT
));
...
...
@@ -168,6 +231,8 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
event
->
relay
=
relay
;
event
->
data
=
data
;
EnterCriticalSection
(
&
qcrit
);
old_pending
=
DOSVM_HasPendingEvents
();
/* insert event into linked list, in order *after*
* all earlier events of higher or equal priority */
cur
=
pending_event
;
prev
=
NULL
;
...
...
@@ -179,18 +244,18 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
if
(
prev
)
prev
->
next
=
event
;
else
pending_event
=
event
;
/* alert the vm86 about the new event */
if
(
!
sig_sent
)
{
if
(
!
old_pending
&&
DOSVM_HasPendingEvents
())
{
TRACE
(
"new event queued, signalling (time=%ld)
\n
"
,
GetTickCount
());
/* Alert VM86 thread about the new event. */
kill
(
dosvm_pid
,
SIGUSR2
);
sig_sent
++
;
/* Wake up DOSVM_Wait so that it can serve pending events. */
SetEvent
(
event_notifier
);
}
else
{
TRACE
(
"new event queued (time=%ld)
\n
"
,
GetTickCount
());
}
/* Wake up DOSVM_Wait so that it can serve pending events. */
SetEvent
(
event_notifier
);
LeaveCriticalSection
(
&
qcrit
);
}
else
{
/* DOS subsystem not running */
...
...
@@ -289,9 +354,6 @@ void WINAPI DOSVM_Wait( CONTEXT86 *waitctx )
{
if
(
DOSVM_HasPendingEvents
())
{
/*
* FIXME: Critical section locking is broken.
*/
CONTEXT86
context
=
*
waitctx
;
/*
...
...
@@ -312,8 +374,7 @@ void WINAPI DOSVM_Wait( CONTEXT86 *waitctx )
context
.
Esp
=
0
;
}
IF_SET
(
&
context
);
SET_PEND
(
&
context
);
context
.
EFlags
|=
VIF_MASK
;
context
.
SegCs
=
0
;
context
.
Eip
=
0
;
...
...
@@ -459,18 +520,12 @@ static WINE_EXCEPTION_FILTER(exception_handler)
case
EXCEPTION_VM86_STI
:
/* case EXCEPTION_VM86_PICRETURN: */
IF_SET
(
context
);
EnterCriticalSection
(
&
qcrit
);
sig_sent
++
;
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
"
);
}
TRACE_
(
int
)(
"DOS task enabled interrupts %s events pending, sending events (time=%ld)
\n
"
,
IS_PEND
(
context
)
?
"with"
:
"without"
,
GetTickCount
());
if
(
!
ISV86
(
context
))
ERR
(
"Protected mode STI caught by real mode handler!
\n
"
);
context
->
EFlags
|=
VIF_MASK
;
context
->
EFlags
&=
~
VIP_MASK
;
DOSVM_SendQueuedEvents
(
context
);
sig_sent
=
0
;
LeaveCriticalSection
(
&
qcrit
);
return
EXCEPTION_CONTINUE_EXECUTION
;
}
return
EXCEPTION_CONTINUE_SEARCH
;
...
...
dlls/winedos/int31.c
View file @
75e87b44
...
...
@@ -1062,7 +1062,6 @@ void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
break
;
case
0x0300
:
/* Simulate real mode interrupt */
TRACE
(
"Simulate real mode interrupt %d.
\n
"
,
BL_reg
(
context
));
DOSVM_CallRMInt
(
context
);
break
;
...
...
@@ -1252,6 +1251,26 @@ void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
MAKELONG
(
CX_reg
(
context
),
BX_reg
(
context
))
);
break
;
case
0x0900
:
/* Get and Disable Virtual Interrupt State */
TRACE
(
"Get and Disable Virtual Interrupt State: %ld
\n
"
,
NtCurrentTeb
()
->
dpmi_vif
);
SET_AL
(
context
,
NtCurrentTeb
()
->
dpmi_vif
?
1
:
0
);
NtCurrentTeb
()
->
dpmi_vif
=
0
;
break
;
case
0x0901
:
/* Get and Enable Virtual Interrupt State */
TRACE
(
"Get and Enable Virtual Interrupt State: %ld
\n
"
,
NtCurrentTeb
()
->
dpmi_vif
);
SET_AL
(
context
,
NtCurrentTeb
()
->
dpmi_vif
?
1
:
0
);
NtCurrentTeb
()
->
dpmi_vif
=
1
;
break
;
case
0x0902
:
/* Get Virtual Interrupt State */
TRACE
(
"Get Virtual Interrupt State: %ld
\n
"
,
NtCurrentTeb
()
->
dpmi_vif
);
SET_AL
(
context
,
NtCurrentTeb
()
->
dpmi_vif
?
1
:
0
);
break
;
case
0x0e00
:
/* Get Coprocessor Status (1.0) */
/*
* Return status in AX bits:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment