ReactOS 0.4.15-dev-7907-g95bf896
clock.c File Reference
#include "ntvdm.h"
#include <debug.h>
#include "emulator.h"
#include "clock.h"
#include "cpu/cpu.h"
#include "hardware/cmos.h"
#include "hardware/ps2.h"
#include "hardware/pit.h"
#include "hardware/video/svga.h"
#include "hardware/mouse.h"
Include dependency graph for clock.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define STEPS_PER_CYCLE   1024
 

Functions

static VOID FASTCALL IpsCallback (ULONGLONG ElapsedTime)
 
VOID ClockUpdate (VOID)
 
PHARDWARE_TIMER CreateHardwareTimer (ULONG Flags, ULONGLONG Delay, PHARDWARE_TIMER_PROC Callback)
 
VOID EnableHardwareTimer (PHARDWARE_TIMER Timer)
 
VOID DisableHardwareTimer (PHARDWARE_TIMER Timer)
 
VOID SetHardwareTimerDelay (PHARDWARE_TIMER Timer, ULONGLONG NewDelay)
 
VOID DestroyHardwareTimer (PHARDWARE_TIMER Timer)
 
BOOLEAN ClockInitialize (VOID)
 

Variables

static LIST_ENTRY Timers
 
static LARGE_INTEGER StartPerfCount
 
static LARGE_INTEGER Frequency
 
static LARGE_INTEGER Counter
 
static ULONG CurrentTickCount
 
static ULONGLONG LastCycles = 0ULL
 
static PHARDWARE_TIMER IpsTimer
 
ULONGLONG CurrentCycleCount = 0ULL
 
ULONGLONG CurrentIps = 20000000ULL
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file clock.c.

◆ STEPS_PER_CYCLE

#define STEPS_PER_CYCLE   1024

Definition at line 36 of file clock.c.

Function Documentation

◆ ClockInitialize()

BOOLEAN ClockInitialize ( VOID  )

Definition at line 219 of file clock.c.

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}
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
#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 InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:272
#define L(x)
Definition: ntvdm.h:50
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
static LARGE_INTEGER StartPerfCount
Definition: clock.c:41
static LARGE_INTEGER Frequency
Definition: clock.c:41
static PHARDWARE_TIMER IpsTimer
Definition: clock.c:46
static LIST_ENTRY Timers
Definition: clock.c:40
LONGLONG QuadPart
Definition: typedefs.h:114
#define wprintf(...)
Definition: whoami.c:18

Referenced by EmulatorInitialize().

◆ ClockUpdate()

VOID ClockUpdate ( VOID  )

DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);

SetThreadAffinityMask(GetCurrentThread(), oldmask);

Definition at line 76 of file clock.c.

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}
unsigned char BOOLEAN
#define HARDWARE_TIMER_ONESHOT
Definition: clock.h:16
#define HARDWARE_TIMER_PRECISE
Definition: clock.h:17
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
BOOLEAN VdmRunning
Definition: emulator.c:49
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
unsigned int UINT
Definition: ndis.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
VOID DisableHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:183
#define STEPS_PER_CYCLE
Definition: clock.c:36
static LARGE_INTEGER Counter
Definition: clock.c:43
static ULONG CurrentTickCount
Definition: clock.c:44
ULONGLONG CurrentCycleCount
Definition: clock.c:48
VOID CpuStep(VOID)
Definition: cpu.c:108
BOOLEAN CpuRunning
Definition: cpu.c:40
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
static int Link(const char **args)
Definition: vfdcmd.c:2414

Referenced by CpuSimulate().

◆ CreateHardwareTimer()

PHARDWARE_TIMER CreateHardwareTimer ( ULONG  Flags,
ULONGLONG  Delay,
PHARDWARE_TIMER_PROC  Callback 
)

Definition at line 144 of file clock.c.

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}
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
VOID EnableHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:161
VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay)
Definition: clock.c:197
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by ClockInitialize(), CmosInitialize(), MouseInit(), PitInitialize(), PS2Initialize(), and VgaInitialize().

◆ DestroyHardwareTimer()

VOID DestroyHardwareTimer ( PHARDWARE_TIMER  Timer)

Definition at line 210 of file clock.c.

211{
212 if (Timer)
213 {
215 RtlFreeHeap(RtlGetProcessHeap(), 0, Timer);
216 }
217}
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986

Referenced by CmosCleanup(), PS2Cleanup(), and VgaCleanup().

◆ DisableHardwareTimer()

VOID DisableHardwareTimer ( PHARDWARE_TIMER  Timer)

Definition at line 183 of file clock.c.

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}

Referenced by ClockUpdate(), and RtcUpdatePeriodicTimer().

◆ EnableHardwareTimer()

VOID EnableHardwareTimer ( PHARDWARE_TIMER  Timer)

Definition at line 161 of file clock.c.

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}
#define InsertTailList(ListHead, Entry)

Referenced by CreateHardwareTimer(), PS2QueuePush(), and RtcUpdatePeriodicTimer().

◆ IpsCallback()

static VOID FASTCALL IpsCallback ( ULONGLONG  ElapsedTime)
static

Definition at line 53 of file clock.c.

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}
#define DPRINT1
Definition: precomp.h:8
ULONGLONG CurrentIps
Definition: clock.c:49
static ULONGLONG LastCycles
Definition: clock.c:45
int32_t INT
Definition: typedefs.h:58

Referenced by ClockInitialize().

◆ SetHardwareTimerDelay()

VOID SetHardwareTimerDelay ( PHARDWARE_TIMER  Timer,
ULONGLONG  NewDelay 
)

Definition at line 197 of file clock.c.

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}

Referenced by CreateHardwareTimer(), and RtcUpdatePeriodicTimer().

Variable Documentation

◆ Counter

◆ CurrentCycleCount

ULONGLONG CurrentCycleCount = 0ULL

Definition at line 48 of file clock.c.

Referenced by ClockUpdate(), IpsCallback(), VgaHorizontalRetrace(), and VgaReadPort().

◆ CurrentIps

ULONGLONG CurrentIps = 20000000ULL

Definition at line 49 of file clock.c.

Referenced by IpsCallback(), VgaHorizontalRetrace(), and VgaReadPort().

◆ CurrentTickCount

ULONG CurrentTickCount
static

Definition at line 44 of file clock.c.

Referenced by ClockUpdate().

◆ Frequency

◆ IpsTimer

PHARDWARE_TIMER IpsTimer
static

Definition at line 46 of file clock.c.

Referenced by ClockInitialize().

◆ LastCycles

ULONGLONG LastCycles = 0ULL
static

Definition at line 45 of file clock.c.

Referenced by IpsCallback().

◆ StartPerfCount

LARGE_INTEGER StartPerfCount
static

Definition at line 41 of file clock.c.

Referenced by ClockInitialize().

◆ Timers

LIST_ENTRY Timers
static

Definition at line 40 of file clock.c.

Referenced by ClockInitialize(), ClockUpdate(), EnableHardwareTimer(), and KiTimerExpiration().