ReactOS  0.4.14-dev-49-gfb4591c
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 TRUE
Definition: types.h:120
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:278
#define wprintf(...)
Definition: whoami.c:18
static LIST_ENTRY Timers
Definition: clock.c:40
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
smooth NULL
Definition: ftsmooth.c:416
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
static const WCHAR L[]
Definition: oid.c:1250
static LARGE_INTEGER StartPerfCount
Definition: clock.c:41
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
static LARGE_INTEGER Frequency
Definition: clock.c:41
#define HZ_TO_NS(Freq)
Definition: clock.h:20
static PHARDWARE_TIMER IpsTimer
Definition: clock.c:46
LONGLONG QuadPart
Definition: typedefs.h:112

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 
98  Entry = Timers.Flink;
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 }
BOOLEAN CpuRunning
Definition: cpu.c:40
struct _Entry Entry
Definition: kefuncs.h:640
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:278
VOID DisableHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:183
ULONGLONG CurrentCycleCount
Definition: clock.c:48
static int Link(const char **args)
Definition: vfdcmd.c:2414
static LIST_ENTRY Timers
Definition: clock.c:40
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
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
uint64_t ULONGLONG
Definition: typedefs.h:65
#define HARDWARE_TIMER_PRECISE
Definition: clock.h:17
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
#define STEPS_PER_CYCLE
Definition: clock.c:36
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define HARDWARE_TIMER_ONESHOT
Definition: clock.h:16
static ULONG CurrentTickCount
Definition: clock.c:44
Definition: typedefs.h:117
UINT Timer
Definition: capclock.c:11
unsigned int UINT
Definition: ndis.h:50
static LARGE_INTEGER Counter
Definition: clock.c:43
unsigned int ULONG
Definition: retypes.h:1
VOID CpuStep(VOID)
Definition: cpu.c:108
BOOLEAN VdmRunning
Definition: emulator.c:49
base of all file and directory entries
Definition: entries.h:82
LONGLONG QuadPart
Definition: typedefs.h:112

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 }
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
smooth NULL
Definition: ftsmooth.c:416
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay)
Definition: clock.c:197
UINT Timer
Definition: capclock.c:11
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
VOID EnableHardwareTimer(PHARDWARE_TIMER Timer)
Definition: clock.c:161
LPFNPSPCALLBACK Callback
Definition: desk.c:111

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  {
214  if (Timer->Flags & HARDWARE_TIMER_ENABLED) RemoveEntryList(&Timer->Link);
215  RtlFreeHeap(RtlGetProcessHeap(), 0, Timer);
216  }
217 }
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15

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 }
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15

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  {
171  NtQueryPerformanceCounter(&Timer->LastTick, NULL);
172  }
173  else
174  {
175  Timer->LastTick.LowPart = GetTickCount();
176  }
177 
178  Timer->Flags |= HARDWARE_TIMER_ENABLED;
179  InsertTailList(&Timers, &Timer->Link);
180  }
181 }
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:278
#define InsertTailList(ListHead, Entry)
static LIST_ENTRY Timers
Definition: clock.c:40
smooth NULL
Definition: ftsmooth.c:416
#define HARDWARE_TIMER_PRECISE
Definition: clock.h:17
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15

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 }
static ULONGLONG LastCycles
Definition: clock.c:45
ULONGLONG CurrentCycleCount
Definition: clock.c:48
int32_t INT
Definition: typedefs.h:56
#define ULL(a, b)
Definition: format_msg.c:27
uint64_t ULONGLONG
Definition: typedefs.h:65
ULONGLONG CurrentIps
Definition: clock.c:49
#define DPRINT1
Definition: precomp.h:8

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 }
#define ULL(a, b)
Definition: format_msg.c:27
#define HARDWARE_TIMER_PRECISE
Definition: clock.h:17
static LARGE_INTEGER Frequency
Definition: clock.c:41
LONGLONG QuadPart
Definition: typedefs.h:112

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().