Split timer code into separate source file.

Stop using SIGALRM for timers.
This commit is contained in:
Jukka Heinonen 2003-06-13 16:28:49 +00:00 committed by Alexandre Julliard
parent 03e0a49649
commit b2844d2c3a
3 changed files with 129 additions and 51 deletions

View File

@ -48,6 +48,7 @@ C_SRCS = \
module.c \
relay.c \
soundblaster.c \
timer.c \
vga.c \
vxd.c \
xms.c

View File

@ -374,6 +374,8 @@ DWORD WINAPI DOSVM_Loop( HANDLE hThread )
SetEvent( (HANDLE)msg.wParam );
}
break;
default:
DispatchMessageA(&msg);
}
}
}
@ -423,13 +425,6 @@ static WINE_EXCEPTION_FILTER(exception_handler)
IF_SET(context);
EnterCriticalSection(&qcrit);
sig_sent++;
while (NtCurrentTeb()->alarms) {
DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
/* hmm, instead of relying on this signal counter, we should
* probably check how many ticks have *really* passed, probably using
* QueryPerformanceCounter() or something like that */
InterlockedDecrement(&(NtCurrentTeb()->alarms));
}
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)) {
@ -493,40 +488,6 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val)
}
}
/***********************************************************************
* SetTimer (WINEDOS.@)
*/
void WINAPI DOSVM_SetTimer( UINT ticks )
{
struct itimerval tim;
if (dosvm_pid) {
/* the PC clocks ticks at 1193180 Hz */
tim.it_interval.tv_sec=0;
tim.it_interval.tv_usec=MulDiv(ticks,1000000,1193180);
/* sanity check */
if (!tim.it_interval.tv_usec) tim.it_interval.tv_usec=1;
/* first tick value */
tim.it_value = tim.it_interval;
TRACE_(int)("setting timer tick delay to %ld us\n", tim.it_interval.tv_usec);
setitimer(ITIMER_REAL, &tim, NULL);
}
}
/***********************************************************************
* GetTimer (WINEDOS.@)
*/
UINT WINAPI DOSVM_GetTimer( void )
{
struct itimerval tim;
if (dosvm_pid) {
getitimer(ITIMER_REAL, &tim);
return MulDiv(tim.it_value.tv_usec,1193180,1000000);
}
return 0;
}
#else /* !MZ_SUPPORTED */
/***********************************************************************
@ -548,16 +509,6 @@ void WINAPI DOSVM_Wait( CONTEXT86 *waitctx ) { }
*/
void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
/***********************************************************************
* SetTimer (WINEDOS.@)
*/
void WINAPI DOSVM_SetTimer( UINT ticks ) {}
/***********************************************************************
* GetTimer (WINEDOS.@)
*/
UINT WINAPI DOSVM_GetTimer( void ) { return 0; }
/***********************************************************************
* QueueEvent (WINEDOS.@)
*/

126
dlls/winedos/timer.c Normal file
View File

@ -0,0 +1,126 @@
/*
* 8253/8254 Programmable Interval Timer (PIT) emulation
*
* Copyright 2003 Jukka Heinonen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "dosexe.h"
#include "wine/debug.h"
#include "wingdi.h"
#include "winuser.h"
WINE_DEFAULT_DEBUG_CHANNEL(int);
/*
* FIXME: Move timer ioport handling here and remove
* Dosvm.GetTimer/Dosvm.SetTimer.
* FIXME: Use QueryPerformanceCounter for
* more precise GetTimer implementation.
* FIXME: Use QueryPerformanceCounter (or GetTimer implementation)
* in timer tick routine to compensate for lost ticks.
* This should also make it possible to
* emulate really fast timers.
* FIXME: Support special timer modes in addition to periodic mode.
* FIXME: Make sure that there are only limited number
* of pending timer IRQ events queued. This makes sure that
* timer handling does not eat all available memory even
* if IRQ handling stops for some reason (suspended process?).
* This is easy to do by using DOSRELAY parameter.
* FIXME: Use timeSetEvent, NtSetEvent or timer thread for more precise
* timing.
* FIXME: Move Win16 timer emulation code here.
*/
/* The PC clocks ticks at 1193180 Hz. */
#define TIMER_FREQ 1193180
/* Unique system timer identifier. */
static UINT_PTR TIMER_id = 0;
/* Time when timer IRQ was last queued. */
static DWORD TIMER_stamp = 0;
/* Timer ticks between timer IRQs. */
static UINT TIMER_ticks = 0;
/***********************************************************************
* TIMER_TimerProc
*/
static void CALLBACK TIMER_TimerProc( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime )
{
TIMER_stamp = dwTime;
DOSVM_QueueEvent( 0, DOS_PRIORITY_REALTIME, NULL, NULL );
}
/***********************************************************************
* TIMER_DoSetTimer
*/
static void WINAPI TIMER_DoSetTimer( ULONG_PTR arg )
{
INT millis = MulDiv( arg, 1000, TIMER_FREQ );
/* sanity check - too fast timer */
if (millis < 1)
millis = 1;
TRACE_(int)( "setting timer tick delay to %d ms\n", millis );
if (TIMER_id)
KillTimer( NULL, TIMER_id );
TIMER_id = SetTimer( NULL, 0, millis, TIMER_TimerProc );
TIMER_stamp = GetTickCount();
TIMER_ticks = arg;
}
/***********************************************************************
* GetTimer (WINEDOS.@)
*/
UINT WINAPI DOSVM_GetTimer( void )
{
if (!DOSVM_IsWin16())
{
DWORD millis = GetTickCount() - TIMER_stamp;
INT ticks = MulDiv( millis, TIMER_FREQ, 1000 );
/* sanity check - tick wrap or suspended process or update race */
if (ticks < 0 || ticks >= TIMER_ticks)
ticks = 0;
return ticks;
}
return 0;
}
/***********************************************************************
* SetTimer (WINEDOS.@)
*/
void WINAPI DOSVM_SetTimer( UINT ticks )
{
if (!DOSVM_IsWin16())
MZ_RunInThread( TIMER_DoSetTimer, ticks );
}