Added MZ_Current() (returns current LPDOSTASK) and DOSVM_Wait()

(DOSVM idle message loop), and fields hConInput and hConOutput.
This commit is contained in:
Ove Kaaven 1999-05-22 10:40:15 +00:00 committed by Alexandre Julliard
parent 8903e536fb
commit e54d4d15c4
3 changed files with 140 additions and 115 deletions

View File

@ -30,7 +30,7 @@ typedef struct _DOSTASK {
HMODULE16 hModule; HMODULE16 hModule;
char mm_name[128]; char mm_name[128];
int mm_fd; int mm_fd;
HANDLE hReadPipe,hXPipe; HANDLE hReadPipe,hXPipe,hConInput,hConOutput;
int read_pipe,write_pipe; int read_pipe,write_pipe;
pid_t task; pid_t task;
int sig_sent; int sig_sent;
@ -67,7 +67,9 @@ extern BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, LPSTARTUPINFOA startup, BOOL inherit, LPSTARTUPINFOA startup,
LPPROCESS_INFORMATION info ); LPPROCESS_INFORMATION info );
extern LPDOSTASK MZ_Current( void );
extern int DOSVM_Enter( PCONTEXT context ); extern int DOSVM_Enter( PCONTEXT context );
extern void DOSVM_Wait( int read_pipe, HANDLE hObject );
extern void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data ); extern void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data );
extern void DOSVM_PIC_ioport_out( WORD port, BYTE val ); extern void DOSVM_PIC_ioport_out( WORD port, BYTE val );
extern void DOSVM_SetTimer( unsigned ticks ); extern void DOSVM_SetTimer( unsigned ticks );

View File

@ -167,12 +167,10 @@ static void DOSVM_SendQueuedEvents(PCONTEXT context, LPDOSTASK lpDosTask)
void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data) void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data)
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
LPDOSEVENT event, cur, prev; LPDOSEVENT event, cur, prev;
GlobalUnlock16( GetCurrentTask() ); if (lpDosTask) {
if (pModule && pModule->lpDosTask) {
event = malloc(sizeof(DOSEVENT)); event = malloc(sizeof(DOSEVENT));
if (!event) { if (!event) {
ERR_(int)("out of memory allocating event entry\n"); ERR_(int)("out of memory allocating event entry\n");
@ -183,20 +181,20 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,v
/* insert event into linked list, in order *after* /* insert event into linked list, in order *after*
* all earlier events of higher or equal priority */ * all earlier events of higher or equal priority */
cur = pModule->lpDosTask->pending; prev = NULL; cur = lpDosTask->pending; prev = NULL;
while (cur && cur->priority<=priority) { while (cur && cur->priority<=priority) {
prev = cur; prev = cur;
cur = cur->next; cur = cur->next;
} }
event->next = cur; event->next = cur;
if (prev) prev->next = event; if (prev) prev->next = event;
else pModule->lpDosTask->pending = event; else lpDosTask->pending = event;
/* get dosmod's attention to the new event, except for irq==0 where we already have it */ /* get dosmod's attention to the new event, except for irq==0 where we already have it */
if (irq && !pModule->lpDosTask->sig_sent) { if (irq && !lpDosTask->sig_sent) {
TRACE_(int)("new event queued, signalling dosmod\n"); TRACE_(int)("new event queued, signalling dosmod\n");
kill(pModule->lpDosTask->task,SIGUSR2); kill(lpDosTask->task,SIGUSR2);
pModule->lpDosTask->sig_sent++; lpDosTask->sig_sent++;
} else { } else {
TRACE_(int)("new event queued\n"); TRACE_(int)("new event queued\n");
} }
@ -222,6 +220,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
CV; CV;
#undef CP #undef CP
if (fnINSTR_EmulateInstruction) ret=fnINSTR_EmulateInstruction(&sigcontext); if (fnINSTR_EmulateInstruction) ret=fnINSTR_EmulateInstruction(&sigcontext);
else ERR_(module)("fnINSTR_EmulateInstruction is not initialized!\n");
#define CP(x,y) VM86->regs.x = y##_sig(&sigcontext) #define CP(x,y) VM86->regs.x = y##_sig(&sigcontext)
CV; CV;
#undef CP #undef CP
@ -334,24 +333,53 @@ void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg)
} }
} }
void DOSVM_Wait( int read_pipe, HANDLE hObject )
{
LPDOSTASK lpDosTask = MZ_Current();
MSG msg;
DWORD waitret;
BOOL got_msg = FALSE;
do {
/* check for messages (waste time before the response check below) */
while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
/* got a message */
DOSVM_ProcessMessage(lpDosTask,&msg);
/* we don't need a TranslateMessage here */
DispatchMessageA(&msg);
got_msg = TRUE;
}
if (read_pipe == -1) {
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;
}
/* check for data from win32 console device */
/* nothing yet, block while waiting for something to do */
waitret=MsgWaitForMultipleObjects(1,&hObject,FALSE,INFINITE,QS_ALLINPUT);
if (waitret==(DWORD)-1) {
ERR_(module)("dosvm wait error=%ld\n",GetLastError());
}
if (read_pipe != -1) {
if (waitret==WAIT_OBJECT_0) break;
}
} while (TRUE);
}
int DOSVM_Enter( PCONTEXT context ) int DOSVM_Enter( PCONTEXT context )
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
LPDOSTASK lpDosTask;
struct vm86plus_struct VM86; struct vm86plus_struct VM86;
int stat,len,sig; int stat,len,sig;
DWORD waitret;
MSG msg;
fd_set readfds;
struct timeval timeout={0,0};
GlobalUnlock16( GetCurrentTask() ); if (!lpDosTask) {
if (!pModule) {
ERR_(module)("No task is currently active!\n");
return -1;
}
if (!(lpDosTask=pModule->lpDosTask)) {
/* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */ /* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */
ERR_(module)("dosmod has not been initialized!"); ERR_(module)("dosmod has not been initialized!");
return -1; return -1;
@ -390,25 +418,8 @@ int DOSVM_Enter( PCONTEXT context )
ERR_(module)("dosmod sync lost, errno=%d\n",errno); ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return -1; return -1;
} }
do { /* wait for response, doing other things in the meantime */
/* check for messages (waste time before the response check below) */ DOSVM_Wait(lpDosTask->read_pipe, lpDosTask->hReadPipe);
while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
/* got a message */
DOSVM_ProcessMessage(lpDosTask,&msg);
/* we don't need a TranslateMessage here */
DispatchMessageA(&msg);
}
/* quick check for response from dosmod
* (faster than doing the full blocking wait, if data already available) */
FD_ZERO(&readfds); FD_SET(lpDosTask->read_pipe,&readfds);
if (select(lpDosTask->read_pipe+1,&readfds,NULL,NULL,&timeout)>0)
break;
/* nothing yet, block while waiting for something to do */
waitret=MsgWaitForMultipleObjects(1,&(lpDosTask->hReadPipe),FALSE,INFINITE,QS_ALLINPUT);
if (waitret==(DWORD)-1) {
ERR_(module)("dosvm wait error=%ld\n",GetLastError());
}
} while (waitret!=WAIT_OBJECT_0);
/* read response */ /* read response */
while (1) { while (1) {
if ((len=read(lpDosTask->read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break; if ((len=read(lpDosTask->read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break;
@ -453,29 +464,27 @@ int DOSVM_Enter( PCONTEXT context )
void DOSVM_PIC_ioport_out( WORD port, BYTE val) void DOSVM_PIC_ioport_out( WORD port, BYTE val)
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
LPDOSEVENT event; LPDOSEVENT event;
GlobalUnlock16( GetCurrentTask() ); if (lpDosTask) {
if (pModule && pModule->lpDosTask) {
if ((port==0x20) && (val==0x20)) { if ((port==0x20) && (val==0x20)) {
if (pModule->lpDosTask->current) { if (lpDosTask->current) {
/* EOI (End Of Interrupt) */ /* EOI (End Of Interrupt) */
TRACE_(int)("received EOI for current IRQ, clearing\n"); TRACE_(int)("received EOI for current IRQ, clearing\n");
event = pModule->lpDosTask->current; event = lpDosTask->current;
pModule->lpDosTask->current = event->next; lpDosTask->current = event->next;
if (event->relay) if (event->relay)
(*event->relay)(pModule->lpDosTask,NULL,event->data); (*event->relay)(lpDosTask,NULL,event->data);
free(event); free(event);
if (pModule->lpDosTask->pending && if (lpDosTask->pending &&
!pModule->lpDosTask->sig_sent) { !lpDosTask->sig_sent) {
/* another event is pending, which we should probably /* another event is pending, which we should probably
* be able to process now, so tell dosmod about it */ * be able to process now, so tell dosmod about it */
TRACE_(int)("another event pending, signalling dosmod\n"); TRACE_(int)("another event pending, signalling dosmod\n");
kill(pModule->lpDosTask->task,SIGUSR2); kill(lpDosTask->task,SIGUSR2);
pModule->lpDosTask->sig_sent++; lpDosTask->sig_sent++;
} }
} else { } else {
WARN_(int)("EOI without active IRQ\n"); WARN_(int)("EOI without active IRQ\n");
@ -488,65 +497,59 @@ void DOSVM_PIC_ioport_out( WORD port, BYTE val)
void DOSVM_SetTimer( unsigned ticks ) void DOSVM_SetTimer( unsigned ticks )
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); int stat=DOSMOD_SET_TIMER;
int stat=DOSMOD_SET_TIMER; struct timeval tim;
struct timeval tim;
GlobalUnlock16( GetCurrentTask() ); if (lpDosTask) {
if (pModule&&pModule->lpDosTask) { /* the PC clocks ticks at 1193180 Hz */
/* the PC clocks ticks at 1193180 Hz */ tim.tv_sec=0;
tim.tv_sec=0; tim.tv_usec=((unsigned long long)ticks*1000000)/1193180;
tim.tv_usec=((unsigned long long)ticks*1000000)/1193180; /* sanity check */
/* sanity check */ if (!tim.tv_usec) tim.tv_usec=1;
if (!tim.tv_usec) tim.tv_usec=1;
if (write(pModule->lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno); ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return; return;
}
if (write(lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return;
}
/* there's no return */
} }
if (write(pModule->lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return;
}
/* there's no return */
}
} }
unsigned DOSVM_GetTimer( void ) unsigned DOSVM_GetTimer( void )
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); int stat=DOSMOD_GET_TIMER;
int stat=DOSMOD_GET_TIMER; struct timeval tim;
struct timeval tim;
GlobalUnlock16( GetCurrentTask() ); if (lpDosTask) {
if (pModule&&pModule->lpDosTask) { if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
if (write(pModule->lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { ERR_(module)("dosmod sync lost, errno=%d\n",errno);
ERR_(module)("dosmod sync lost, errno=%d\n",errno); return 0;
return 0; }
/* read response */
while (1) {
if (read(lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break;
if ((errno==EINTR)||(errno==EAGAIN)) continue;
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return 0;
}
return ((unsigned long long)tim.tv_usec*1193180)/1000000;
} }
/* read response */ return 0;
while (1) {
if (read(pModule->lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break;
if ((errno==EINTR)||(errno==EAGAIN)) continue;
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return 0;
}
return ((unsigned long long)tim.tv_usec*1193180)/1000000;
}
return 0;
} }
void DOSVM_SetSystemData( int id, void *data ) void DOSVM_SetSystemData( int id, void *data )
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
DOSSYSTEM *sys, *prev; DOSSYSTEM *sys, *prev;
GlobalUnlock16( GetCurrentTask() ); if (lpDosTask) {
if (pModule && pModule->lpDosTask) { sys = lpDosTask->sys;
sys = pModule->lpDosTask->sys;
prev = NULL; prev = NULL;
while (sys && (sys->id != id)) { while (sys && (sys->id != id)) {
prev = sys; prev = sys;
@ -561,20 +564,18 @@ void DOSVM_SetSystemData( int id, void *data )
sys->data = data; sys->data = data;
sys->next = NULL; sys->next = NULL;
if (prev) prev->next = sys; if (prev) prev->next = sys;
else pModule->lpDosTask->sys = sys; else lpDosTask->sys = sys;
} }
} else free(data); } else free(data);
} }
void* DOSVM_GetSystemData( int id ) void* DOSVM_GetSystemData( int id )
{ {
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); LPDOSTASK lpDosTask = MZ_Current();
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
DOSSYSTEM *sys; DOSSYSTEM *sys;
GlobalUnlock16( GetCurrentTask() ); if (lpDosTask) {
if (pModule && pModule->lpDosTask) { sys = lpDosTask->sys;
sys = pModule->lpDosTask->sys;
while (sys && (sys->id != id)) while (sys && (sys->id != id))
sys = sys->next; sys = sys->next;
if (sys) if (sys)
@ -591,11 +592,12 @@ int DOSVM_Enter( PCONTEXT context )
return -1; return -1;
} }
void DOSVM_Wait( int read_pipe, HANDLE hObject) {}
void DOSVM_PIC_ioport_out( WORD port, BYTE val) {} void DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
void DOSVM_SetTimer( unsigned ticks ) {} void DOSVM_SetTimer( unsigned ticks ) {}
unsigned DOSVM_GetTimer( void ) { return 0; } unsigned DOSVM_GetTimer( void ) { return 0; }
void DOSVM_SetSystemData( int id, void *data ) { free(data); } void DOSVM_SetSystemData( int id, void *data ) { free(data); }
void* DOSVM_GetSystemData( int id ) { return NULL; } void* DOSVM_GetSystemData( int id ) { return NULL; }
void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data) { /* EMPTY */ } void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data) {}
#endif #endif

View File

@ -182,7 +182,7 @@ static BOOL MZ_InitMemory( LPDOSTASK lpDosTask, NE_MODULE *pModule )
{ {
int x; int x;
if (lpDosTask->img_ofs) return TRUE; /* already allocated */ if (lpDosTask->img) return TRUE; /* already allocated */
/* allocate 1MB+64K shared memory */ /* allocate 1MB+64K shared memory */
lpDosTask->img_ofs=START_OFFSET; lpDosTask->img_ofs=START_OFFSET;
@ -330,7 +330,7 @@ static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver )
int func; int func;
struct timeval tim; struct timeval tim;
/* start dosmod timer at 55Hz */ /* start dosmod timer at 55ms (18.2Hz) */
func=DOSMOD_SET_TIMER; func=DOSMOD_SET_TIMER;
tim.tv_sec=0; tim.tv_usec=54925; tim.tv_sec=0; tim.tv_usec=54925;
write(lpDosTask->write_pipe,&func,sizeof(func)); write(lpDosTask->write_pipe,&func,sizeof(func));
@ -370,14 +370,17 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask )
lpDosTask->write_pipe=write_fd[1]; lpDosTask->write_pipe=write_fd[1];
/* if we have a mapping file, use it */ lpDosTask->hConInput=GetStdHandle(STD_INPUT_HANDLE);
fname=lpDosTask->mm_name; farg=NULL; lpDosTask->hConOutput=GetStdHandle(STD_OUTPUT_HANDLE);
if (!fname[0]) {
/* otherwise, map our own memory image */ /* if we have a mapping file, use it */
sprintf(fproc,"/proc/%d/mem",getpid()); fname=lpDosTask->mm_name; farg=NULL;
sprintf(arg,"%ld",(unsigned long)lpDosTask->img); if (!fname[0]) {
fname=fproc; farg=arg; /* otherwise, map our own memory image */
} sprintf(fproc,"/proc/%d/mem",getpid());
sprintf(arg,"%ld",(unsigned long)lpDosTask->img);
fname=fproc; farg=arg;
}
TRACE(module,"Loading DOS VM support module (hmodule=%04x)\n",lpDosTask->hModule); TRACE(module,"Loading DOS VM support module (hmodule=%04x)\n",lpDosTask->hModule);
if ((child=fork())<0) { if ((child=fork())<0) {
@ -541,6 +544,19 @@ void MZ_KillModule( LPDOSTASK lpDosTask )
#endif #endif
} }
LPDOSTASK MZ_Current( void )
{
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL;
GlobalUnlock16( GetCurrentTask() );
if (pModule)
return pModule->lpDosTask;
return NULL;
}
#else /* !MZ_SUPPORTED */ #else /* !MZ_SUPPORTED */
BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR env, BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR env,
@ -553,4 +569,9 @@ BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR env,
return FALSE; return FALSE;
} }
LPDOSTASK *MZ_Current( void )
{
return NULL;
}
#endif #endif