ReactOS 0.4.16-dev-122-g325d74c
clock.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/clock.c
5 * PURPOSE: Clock for VDM
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10/* INCLUDES *******************************************************************/
11
12#include "ntvdm.h"
13
14#define NDEBUG
15#include <debug.h>
16
17#include "emulator.h"
18#include "clock.h"
19
20#include "cpu/cpu.h"
21#include "hardware/cmos.h"
22#include "hardware/ps2.h"
23#include "hardware/pit.h"
24#include "hardware/video/svga.h"
25#include "hardware/mouse.h"
26
27/* DEFINES ********************************************************************/
28
29/*
30 * Activate IPS_DISPLAY if you want to display the
31 * number of instructions per second.
32 */
33// #define IPS_DISPLAY
34
35/* Processor speed */
36#define STEPS_PER_CYCLE 1024
37
38/* VARIABLES ******************************************************************/
39
42// static ULONG StartTickCount;
47
49ULONGLONG CurrentIps = 20000000ULL; // 20 MIPS is a good estimate
50
51/* PRIVATE FUNCTIONS **********************************************************/
52
54{
55#ifdef IPS_DISPLAY
56 static INT NumCalls = 0;
57#endif
58
59 ULONGLONG NewIps = 10ULL * (CurrentCycleCount - LastCycles) / ElapsedTime;
60 CurrentIps = (CurrentIps + NewIps) >> 1;
61
62#ifdef IPS_DISPLAY
63 NumCalls++;
64 if (NumCalls == 10)
65 {
66 DPRINT1("NTVDM: %I64u Instructions Per Second\n", CurrentIps);
67 NumCalls = 0;
68 }
69#endif
70
72}
73
74/* PUBLIC FUNCTIONS ***********************************************************/
75
77{
78 extern BOOLEAN CpuRunning;
79 UINT i;
82
83 while (VdmRunning && CpuRunning)
84 {
85 /* Get the current counters */
90
91 /* Continue CPU emulation */
92 for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++)
93 {
94 CpuStep();
96 }
97
99 while (Entry != &Timers)
100 {
101 ULONGLONG Ticks = (ULONGLONG)-1;
102
104 Entry = Entry->Flink;
105
106 ASSERT((Timer->EnableCount > 0) && (Timer->Flags & HARDWARE_TIMER_ENABLED));
107
108 if (Timer->Delay)
109 {
110 if (Timer->Flags & HARDWARE_TIMER_PRECISE)
111 {
112 /* Use the performance counter for precise timers */
113 if (Counter.QuadPart <= Timer->LastTick.QuadPart) continue;
114 Ticks = (Counter.QuadPart - Timer->LastTick.QuadPart) / Timer->Delay;
115 }
116 else
117 {
118 /* Use the regular tick count for normal timers */
119 if (CurrentTickCount <= Timer->LastTick.LowPart) continue;
120 Ticks = (CurrentTickCount - Timer->LastTick.LowPart) / (ULONG)Timer->Delay;
121 }
122
123 if (Ticks == 0) continue;
124 }
125
126 Timer->Callback(Ticks);
127
128 if (Timer->Flags & HARDWARE_TIMER_ONESHOT)
129 {
130 /* Disable this timer */
132 }
133
134 /* Update the time of the last timer tick */
135 Timer->LastTick.QuadPart += Ticks * Timer->Delay;
136 }
137
138 /* Yield execution to other threads */
139 // FIXME: Disabled because it causes timing issues (slowdowns).
140 // NtYieldExecution();
141 }
142}
143
145{
147
148 Timer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*Timer));
149 if (Timer == NULL) return NULL;
150
151 Timer->Flags = Flags & ~HARDWARE_TIMER_ENABLED;
152 Timer->EnableCount = 0;
153 Timer->Callback = Callback;
154 Timer->LastTick.QuadPart = 0;
156
158 return Timer;
159}
160
162{
163 /* Increment the count */
164 Timer->EnableCount++;
165
166 /* Check if the count is above 0 but the timer isn't enabled */
167 if ((Timer->EnableCount > 0) && !(Timer->Flags & HARDWARE_TIMER_ENABLED))
168 {
169 if (Timer->Flags & HARDWARE_TIMER_PRECISE)
170 {
172 }
173 else
174 {
175 Timer->LastTick.LowPart = GetTickCount();
176 }
177
179 InsertTailList(&Timers, &Timer->Link);
180 }
181}
182
184{
185 /* Decrement the count */
186 Timer->EnableCount--;
187
188 /* Check if the count is 0 or less but the timer is enabled */
189 if ((Timer->EnableCount <= 0) && (Timer->Flags & HARDWARE_TIMER_ENABLED))
190 {
191 /* Disable the timer */
192 Timer->Flags &= ~HARDWARE_TIMER_ENABLED;
193 RemoveEntryList(&Timer->Link);
194 }
195}
196
198{
199 if (Timer->Flags & HARDWARE_TIMER_PRECISE)
200 {
201 /* Convert the delay from nanoseconds to performance counter ticks */
202 Timer->Delay = (NewDelay * Frequency.QuadPart + 500000000ULL) / 1000000000ULL;
203 }
204 else
205 {
206 Timer->Delay = NewDelay / 1000000ULL;
207 }
208}
209
211{
212 if (Timer)
213 {
215 RtlFreeHeap(RtlGetProcessHeap(), 0, Timer);
216 }
217}
218
220{
222
223 /* Initialize the performance counter (needed for hardware timers) */
224 /* Find the starting performance */
226 if (Frequency.QuadPart == 0)
227 {
228 wprintf(L"FATAL: Performance counter not available\n");
229 return FALSE;
230 }
231
232 /* Find the starting tick count */
233 // StartTickCount = GetTickCount();
234
236 if (IpsTimer == NULL)
237 {
238 wprintf(L"FATAL: Cannot create IPS timer.\n");
239 return FALSE;
240 }
241
242 return TRUE;
243}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
#define HARDWARE_TIMER_ONESHOT
Definition: clock.h:16
VOID(FASTCALL * PHARDWARE_TIMER_PROC)(ULONGLONG ElapsedTime)
Definition: clock.h:22
#define HARDWARE_TIMER_PRECISE
Definition: clock.h:17
#define HZ_TO_NS(Freq)
Definition: clock.h:20
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
BOOLEAN VdmRunning
Definition: emulator.c:49
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
#define ULL(a, b)
Definition: format_msg.c:27
unsigned int UINT
Definition: ndis.h:50
#define FASTCALL
Definition: nt_native.h:50
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:272
#define L(x)
Definition: ntvdm.h:50
base of all file and directory entries
Definition: entries.h:83
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
static VOID FASTCALL IpsCallback(ULONGLONG ElapsedTime)
Definition: clock.c:53
PHARDWARE_TIMER CreateHardwareTimer(ULONG Flags, ULONGLONG Delay, PHARDWARE_TIMER_PROC Callback)
Definition: clock.c:144
VOID DisableHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:183
ULONGLONG CurrentIps
Definition: clock.c:49
BOOLEAN ClockInitialize(VOID)
Definition: clock.c:219
VOID ClockUpdate(VOID)
Definition: clock.c:76
static LARGE_INTEGER StartPerfCount
Definition: clock.c:41
VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:210
#define STEPS_PER_CYCLE
Definition: clock.c:36
static LARGE_INTEGER Frequency
Definition: clock.c:41
static LARGE_INTEGER Counter
Definition: clock.c:43
static PHARDWARE_TIMER IpsTimer
Definition: clock.c:46
VOID EnableHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:161
static ULONG CurrentTickCount
Definition: clock.c:44
static LIST_ENTRY Timers
Definition: clock.c:40
ULONGLONG CurrentCycleCount
Definition: clock.c:48
VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay)
Definition: clock.c:197
static ULONGLONG LastCycles
Definition: clock.c:45
VOID CpuStep(VOID)
Definition: cpu.c:108
BOOLEAN CpuRunning
Definition: cpu.c:40
int32_t INT
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
LONGLONG QuadPart
Definition: typedefs.h:114
static int Link(const char **args)
Definition: vfdcmd.c:2414
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
#define wprintf(...)
Definition: whoami.c:18
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170