diff --git a/PInvoke/Kernel32/RealtimeApiSet.cs b/PInvoke/Kernel32/RealtimeApiSet.cs
index 28dff426..e1f11b64 100644
--- a/PInvoke/Kernel32/RealtimeApiSet.cs
+++ b/PInvoke/Kernel32/RealtimeApiSet.cs
@@ -6,15 +6,18 @@ namespace Vanara.PInvoke
public static partial class Kernel32
{
///
- /// Converts the specified auxiliary counter value to the corresponding performance counter value; optionally provides the estimated conversion error in
- /// nanoseconds due to latencies and maximum possible drift.
+ /// Converts the specified auxiliary counter value to the corresponding performance counter value; optionally provides the estimated
+ /// conversion error in nanoseconds due to latencies and maximum possible drift.
///
/// The auxiliary counter value to convert.
- /// On success, contains the converted performance counter value. Will be undefined if the function fails.
- /// On success, contains the estimated conversion error, in nanoseconds. Will be undefined if the function fails.
+ ///
+ /// On success, contains the converted performance counter value. Will be undefined if the function fails.
+ ///
+ ///
+ /// On success, contains the estimated conversion error, in nanoseconds. Will be undefined if the function fails.
+ ///
///
/// Returns S_OK if the conversion succeeds; otherwise, returns another HRESULT specifying the error.
- ///
///
///
/// Return value
@@ -33,24 +36,27 @@ namespace Vanara.PInvoke
/// The value to convert is outside the permitted range (+/- 10 seconds from when the called occurred).
///
///
- ///
///
- // HRESULT WINAPI ConvertAuxiliaryCounterToPerformanceCounter( _In_ ULONGLONG ullAuxiliaryCounterValue, _Out_ PULONGLONG lpPerformanceCounterValue,
- // _Out_opt_ PULONGLONG lpConversionError); https://msdn.microsoft.com/en-us/library/windows/desktop/mt781214(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Realtimeapiset.h", MSDNShortId = "mt781214")]
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-convertauxiliarycountertoperformancecounter
+ // HRESULT ConvertAuxiliaryCounterToPerformanceCounter( ULONGLONG ullAuxiliaryCounterValue, PULONGLONG lpPerformanceCounterValue,
+ // PULONGLONG lpConversionError );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "94664D63-D1B0-443B-BB88-C8A8771577A6")]
public static extern HRESULT ConvertAuxiliaryCounterToPerformanceCounter(ulong ullAuxiliaryCounterValue, out ulong lpPerformanceCounterValue, out ulong lpConversionError);
///
- /// Converts the specified performance counter value to the corresponding auxiliary counter value; optionally provides the estimated conversion error in
- /// nanoseconds due to latencies and maximum possible drift.
+ /// Converts the specified performance counter value to the corresponding auxiliary counter value; optionally provides the estimated
+ /// conversion error in nanoseconds due to latencies and maximum possible drift.
///
/// The performance counter value to convert.
- /// On success, contains the converted auxiliary counter value. Will be undefined if the function fails.
- /// On success, contains the estimated conversion error, in nanoseconds. Will be undefined if the function fails.
+ ///
+ /// On success, contains the converted auxiliary counter value. Will be undefined if the function fails.
+ ///
+ ///
+ /// On success, contains the estimated conversion error, in nanoseconds. Will be undefined if the function fails.
+ ///
///
/// Returns S_OK if the conversion succeeds; otherwise, returns another HRESULT specifying the error.
- ///
///
///
/// Return value
@@ -73,40 +79,47 @@ namespace Vanara.PInvoke
/// The value to convert is prior to the last system boot or S3/S4 transition.
///
///
- ///
///
- // HRESULT WINAPI ConvertPerformanceCounterToAuxiliaryCounter( _In_ ULONGLONG ullPerformanceCounterValue, _Out_ PULONGLONG lpAuxiliaryCounterValue,
- // _Out_opt_ PULONGLONG lpConversionError); https://msdn.microsoft.com/en-us/library/windows/desktop/mt781215(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Realtimeapiset.h", MSDNShortId = "mt781215")]
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-convertperformancecountertoauxiliarycounter
+ // HRESULT ConvertPerformanceCounterToAuxiliaryCounter( ULONGLONG ullPerformanceCounterValue, PULONGLONG lpAuxiliaryCounterValue,
+ // PULONGLONG lpConversionError );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "2499981B-6C13-4A3D-836A-D4CCD11C8D50")]
public static extern HRESULT ConvertPerformanceCounterToAuxiliaryCounter(ulong ullPerformanceCounterValue, out ulong lpAuxiliaryCounterValue, out ulong lpConversionError);
/// Queries the auxiliary counter frequency.
///
- /// Long pointer to an output buffer that contains the specified auxiliary counter frequency. If the auxiliary counter is not supported, the value in the
- /// output buffer will be undefined.
+ /// Long pointer to an output buffer that contains the specified auxiliary counter frequency. If the auxiliary counter is not
+ /// supported, the value in the output buffer will be undefined.
///
/// Returns S_OK if the auxiliary counter is supported and E_NOTIMPL if the auxiliary counter is not supported.
- // HRESULT WINAPI QueryAuxiliaryCounterFrequency( _Out_ PULONGLONG lpAuxiliaryCounterFrequency); https://msdn.microsoft.com/en-us/library/windows/desktop/mt781218(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Realtimeapiset.h", MSDNShortId = "mt781218")]
+ ///
+ /// You can determine the availability of the auxiliary counter by comparing the returned value against E_NOTIMPL.
+ /// Examples
+ /// The following sample describes how to call QueryAuxiliaryCounterFrequency to retrieve the counter frequency.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryauxiliarycounterfrequency HRESULT
+ // QueryAuxiliaryCounterFrequency( PULONGLONG lpAuxiliaryCounterFrequency );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "71E00DF2-7F67-43D2-9D6D-BFE9FEA4B30A")]
public static extern HRESULT QueryAuxiliaryCounterFrequency(out ulong lpAuxiliaryCounterFrequency);
///
/// Retrieves the cycle time for the idle thread of each processor in the system.
///
- /// On a system with more than 64 processors, this function retrieves the cycle time for the idle thread of each processor in the processor group to
- /// which the calling thread is assigned. Use the QueryIdleProcessorCycleTimeEx function to retrieve the cycle time for the idle thread on each
- /// logical processor for a specific processor group.
+ /// On a system with more than 64 processors, this function retrieves the cycle time for the idle thread of each processor in the
+ /// processor group to which the calling thread is assigned. Use the QueryIdleProcessorCycleTimeEx function to retrieve the cycle
+ /// time for the idle thread on each logical processor for a specific processor group.
///
///
///
///
- /// On input, specifies the size of the ProcessorIdleCycleTime buffer, in bytes. This buffer is expected to be 8 times the number of processors in the group.
+ /// On input, specifies the size of the ProcessorIdleCycleTime buffer, in bytes. This buffer is expected to be 8 times the number of
+ /// processors in the group.
///
///
- /// On output, specifies the number of elements written to the buffer. If the buffer size is not sufficient, the function fails and this parameter
- /// receives the required length of the buffer.
+ /// On output, specifies the number of elements written to the buffer. If the buffer size is not sufficient, the function fails and
+ /// this parameter receives the required length of the buffer.
///
///
///
@@ -114,123 +127,300 @@ namespace Vanara.PInvoke
///
///
/// If the function succeeds, the return value is nonzero.
- /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
- // BOOL WINAPI QueryIdleProcessorCycleTime( _Inout_ PULONG BufferLength, _Out_ PULONG64 ProcessorIdleCycleTime); https://msdn.microsoft.com/en-us/library/windows/desktop/ms684922(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
- [PInvokeData("WinBase.h", MSDNShortId = "ms684922")]
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later.
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryidleprocessorcycletime BOOL
+ // QueryIdleProcessorCycleTime( PULONG BufferLength, PULONG64 ProcessorIdleCycleTime );
+ [DllImport(Lib.KernelBase, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "75a5c4cf-ccc7-47ab-a2a9-88051e0a7d06")]
[return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool QueryIdleProcessorCycleTime(ref uint BufferLength, IntPtr ProcessorIdleCycleTime);
+ public static extern bool QueryIdleProcessorCycleTime(ref uint BufferLength, ulong[] ProcessorIdleCycleTime);
+
+ ///
+ /// Retrieves the cycle time for the idle thread of each processor in the system.
+ ///
+ /// On a system with more than 64 processors, this function retrieves the cycle time for the idle thread of each processor in the
+ /// processor group to which the calling thread is assigned. Use the QueryIdleProcessorCycleTimeEx function to retrieve the cycle
+ /// time for the idle thread on each logical processor for a specific processor group.
+ ///
+ ///
+ /// The number of CPU clock cycles used by each idle thread.
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "75a5c4cf-ccc7-47ab-a2a9-88051e0a7d06")]
+ public static ulong[] QueryIdleProcessorCycleTime()
+ {
+ var ct = new ulong[Environment.ProcessorCount];
+ var sz = (uint)ct.Length * sizeof(ulong);
+ if (!QueryIdleProcessorCycleTime(ref sz, ct))
+ Win32Error.ThrowLastError();
+ return ct;
+ }
/// Retrieves the accumulated cycle time for the idle thread on each logical processor in the specified processor group.
/// The number of the processor group for which to retrieve the cycle time.
///
///
- /// On input, specifies the size of the ProcessorIdleCycleTime buffer, in bytes. This buffer is expected to be 8 times the number of processors in the group.
+ /// On input, specifies the size of the ProcessorIdleCycleTime buffer, in bytes. This buffer is expected to be 8 times the number of
+ /// processors in the group.
///
///
- /// On output, specifies the number of elements written to the buffer. If the buffer size is not sufficient, the function fails and this parameter
- /// receives the required length of the buffer.
+ /// On output, specifies the number of elements written to the buffer. If the buffer size is not sufficient, the function fails and
+ /// this parameter receives the required length of the buffer.
///
///
///
- /// The number of CPU clock cycles used by each idle thread. If this parameter is NULL, the function updates the BufferLength parameter with the required length.
+ /// The number of CPU clock cycles used by each idle thread. If this parameter is NULL, the function updates the BufferLength
+ /// parameter with the required length.
///
///
/// If the function succeeds, the return value is nonzero.
- /// If the function fails, the return value is zero. To get extended error information, use GetLastError.
+ /// If the function fails, the return value is zero. To get extended error information, use GetLastError.
///
- // BOOL QueryIdleProcessorCycleTimeEx( _In_ USHORT Group, _Inout_ PULONG BufferLength, _Out_ PULONG64 ProcessorIdleCycleTime); https://msdn.microsoft.com/en-us/library/windows/desktop/dd405507(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
- [PInvokeData("WinBase.h", MSDNShortId = "dd405507")]
+ ///
+ /// To compile an application that uses this function, set _WIN32_WINNT >= 0x0601. For more information, see Using the Windows Headers.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryidleprocessorcycletimeex BOOL
+ // QueryIdleProcessorCycleTimeEx( USHORT Group, PULONG BufferLength, PULONG64 ProcessorIdleCycleTime );
+ [DllImport(Lib.KernelBase, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "4bf05e40-96d1-4c01-b3a8-8a45934b38c6")]
[return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool QueryIdleProcessorCycleTimeEx(ushort Group, ref uint BufferLength, IntPtr ProcessorIdleCycleTime);
+ public static extern bool QueryIdleProcessorCycleTimeEx(ushort Group, ref uint BufferLength, ulong[] ProcessorIdleCycleTime);
- /// Gets the current interrupt-time count. For a more precise count, use QueryInterruptTimePrecise.
+ /// Retrieves the accumulated cycle time for the idle thread on each logical processor in the specified processor group.
+ /// The number of the processor group for which to retrieve the cycle time.
+ /// The number of CPU clock cycles used by each idle thread.
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "4bf05e40-96d1-4c01-b3a8-8a45934b38c6")]
+ public static ulong[] QueryIdleProcessorCycleTimeEx(ushort Group)
+ {
+ var ct = new ulong[Environment.ProcessorCount];
+ var sz = (uint)ct.Length * sizeof(ulong);
+ if (!QueryIdleProcessorCycleTimeEx(Group, ref sz, ct))
+ Win32Error.ThrowLastError();
+ return ct;
+ }
+
+ /// Gets the current interrupt-time count. For a more precise count, use QueryInterruptTimePrecise.
///
- /// A pointer to a ULONGLONG in which to receive the interrupt-time count in system time units of 100 nanoseconds. Divide by ten million, or 1e7, to get
- /// seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
+ /// A pointer to a ULONGLONG in which to receive the interrupt-time count in system time units of 100 nanoseconds. Divide by ten
+ /// million, or 1e7, to get seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
///
/// This function does not return a value.
- // VOID QueryInterruptTime( _Out_ PULONGLONG lpInterruptTime); https://msdn.microsoft.com/en-us/library/windows/desktop/dn903659(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Realtimeapiset.h", MSDNShortId = "dn903659")]
+ ///
+ ///
+ /// The interrupt-time count begins at zero when the system starts and is incremented at each clock interrupt by the length of a
+ /// clock tick. The exact length of a clock tick depends on underlying hardware and can vary between systems.
+ ///
+ ///
+ /// Unlike system time, the interrupt-time count is not subject to adjustments by users or the Windows time service. Applications can
+ /// use the interrupt-time count to measure finer durations than are possible with system time. Applications that require greater
+ /// precision than the interrupt-time count should use a high-resolution timer. Use the QueryPerformanceFrequency function to
+ /// retrieve the frequency of the high-resolution timer and the QueryPerformanceCounter function to retrieve the counter's value.
+ ///
+ ///
+ /// The timer resolution set by the timeBeginPeriod and timeEndPeriod functions affects the resolution of the
+ /// QueryInterruptTime function. However, increasing the timer resolution is not recommended because it can reduce overall
+ /// system performance and increase system power consumption by preventing the processor from entering power-saving states. Instead,
+ /// applications should use a high-resolution timer.
+ ///
+ ///
+ /// Note The QueryInterruptTime function produces different results on debug ("checked") builds of Windows, because the
+ /// interrupt-time count and tick count are advanced by approximately 49 days. This helps to identify bugs that might not occur until
+ /// the system has been running for a long time. The checked build is available to MSDN subscribers through the Microsoft Developer
+ /// Network (MSDN) Web site.
+ ///
+ ///
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0601 or later. For more information, see Using the
+ /// Windows Headers.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryinterrupttime void QueryInterruptTime(
+ // PULONGLONG lpInterruptTime );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "FB2B179B-5E44-4201-86E2-DB386607FD90")]
public static extern void QueryInterruptTime(out ulong lpInterruptTime);
- /// Gets the current interrupt-time count, in a more precise form than QueryInterruptTime does.
+ /// Gets the current interrupt-time count, in a more precise form than QueryInterruptTime does.
///
- /// A pointer to a ULONGLONG in which to receive the interrupt-time count in system time units of 100 nanoseconds. Divide by ten million, or 1e7, to get
- /// seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
+ /// A pointer to a ULONGLONG in which to receive the interrupt-time count in system time units of 100 nanoseconds. Divide by ten
+ /// million, or 1e7, to get seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
///
/// This function does not return a value.
- // VOID QueryInterruptTimePrecise( _Out_ PULONGLONG lpInterruptTimePrecise); https://msdn.microsoft.com/en-us/library/windows/desktop/dn903660(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Realtimeapiset.h", MSDNShortId = "dn903660")]
+ ///
+ ///
+ /// QueryInterruptTimePrecise is similar to the QueryInterruptTime routine, but is more precise. The interrupt time reported
+ /// by QueryInterruptTime is based on the latest tick of the system clock timer. The system clock timer is the hardware timer
+ /// that periodically generates interrupts for the system clock. The uniform period between system clock timer interrupts is referred
+ /// to as a system clock tick, and is typically in the range of 0.5 milliseconds to 15.625 milliseconds, depending on the hardware
+ /// platform. The interrupt time value retrieved by QueryInterruptTime is accurate within a system clock tick.
+ ///
+ ///
+ /// To provide a system time value that is more precise than that of QueryInterruptTime, QueryInterruptTimePrecise reads the
+ /// timer hardware directly, therefore a QueryInterruptTimePrecise call can be slower than a QueryInterruptTime call.
+ ///
+ /// Call the KeQueryTimeIncrement routine to determine the duration of a system clock tick.
+ /// Also see Remarks in QueryInterruptTime.
+ ///
+ /// Note The QueryInterruptTimePrecise function produces different results on debug ("checked") builds of Windows,
+ /// because the interrupt-time count and tick count are advanced by approximately 49 days. This helps to identify bugs that might not
+ /// occur until the system has been running for a long time. The checked build is available to MSDN subscribers through the Microsoft
+ /// Developer Network (MSDN) Web site.
+ ///
+ ///
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0601 or later. For more information, see Using the
+ /// Windows Headers.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryinterrupttimeprecise void
+ // QueryInterruptTimePrecise( PULONGLONG lpInterruptTimePrecise );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "0F65A707-0899-4F79-B7CD-16C9143C4173")]
public static extern void QueryInterruptTimePrecise(out ulong lpInterruptTimePrecise);
/// Retrieves the sum of the cycle time of all threads of the specified process.
///
- /// A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. For more information,
- /// see Process Security and Access Rights.
+ /// A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right.
+ /// For more information, see Process Security and Access Rights.
///
///
/// The number of CPU clock cycles used by the threads of the process. This value includes cycles spent in both user mode and kernel mode.
///
///
/// If the function succeeds, the return value is nonzero.
- /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
- // BOOL WINAPI QueryProcessCycleTime( _In_ HANDLE ProcessHandle, _Out_ PULONG64 CycleTime); https://msdn.microsoft.com/en-us/library/windows/desktop/ms684929(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
- [PInvokeData("WinBase.h", MSDNShortId = "ms684929")]
+ ///
+ /// To enumerate the processes in the system, use the EnumProcesses function.
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryprocesscycletime BOOL
+ // QueryProcessCycleTime( HANDLE ProcessHandle, PULONG64 CycleTime );
+ [DllImport(Lib.KernelBase, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "1859bc0f-8065-4104-b421-1b4c020ad5ea")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool QueryProcessCycleTime(HPROCESS ProcessHandle, out ulong CycleTime);
/// Retrieves the cycle time for the specified thread.
///
- /// A handle to the thread. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. For more information,
- /// see Process Security and Access Rights.
+ /// A handle to the thread. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. For
+ /// more information, see Process Security and Access Rights.
+ ///
+ ///
+ /// The number of CPU clock cycles used by the thread. This value includes cycles spent in both user mode and kernel mode.
///
- /// The number of CPU clock cycles used by the thread. This value includes cycles spent in both user mode and kernel mode.
///
/// If the function succeeds, the return value is nonzero.
- /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
- // BOOL WINAPI QueryThreadCycleTime( _In_ HANDLE ThreadHandle, _Out_ PULONG64 CycleTime); https://msdn.microsoft.com/en-us/library/windows/desktop/ms684943(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
- [PInvokeData("WinBase.h", MSDNShortId = "ms684943")]
+ ///
+ ///
+ /// To enumerate the threads of the process, use the Thread32First and Thread32Next functions. To get the thread handle for a thread
+ /// identifier, use the OpenThread function.
+ ///
+ ///
+ /// Do not attempt to convert the CPU clock cycles returned by QueryThreadCycleTime to elapsed time. This function uses timer
+ /// services provided by the CPU, which can vary in implementation. For example, some CPUs will vary the frequency of the timer when
+ /// changing the frequency at which the CPU runs and others will leave it at a fixed rate. The behavior of each CPU is described in
+ /// the documentation provided by the CPU vendor.
+ ///
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-querythreadcycletime BOOL
+ // QueryThreadCycleTime( HANDLE ThreadHandle, PULONG64 CycleTime );
+ [DllImport(Lib.KernelBase, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "5828b073-48af-4118-9206-096b87c978e7")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool QueryThreadCycleTime(HTHREAD ThreadHandle, out ulong CycleTime);
///
- /// Gets the current unbiased interrupt-time count, in units of 100 nanoseconds. The unbiased interrupt-time count does not include time the system
- /// spends in sleep or hibernation.
+ /// Gets the current unbiased interrupt-time count, in units of 100 nanoseconds. The unbiased interrupt-time count does not include
+ /// time the system spends in sleep or hibernation.
///
- ///
- /// A pointer to a ULONGLONG in which to receive the unbiased interrupt-time count in system time units of 100 nanoseconds. Divide by ten million, or
- /// 1e7, to get seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
- ///
+ /// TBD
///
- /// If the function succeeds, the return value is nonzero. If the function fails because it is called with a null parameter, the return value is zero.
+ /// If the function succeeds, the return value is nonzero. If the function fails because it is called with a null parameter, the
+ /// return value is zero.
///
- // BOOL QueryUnbiasedInterruptTime( _Out_ PULONGLONG lpUnbiasedInterruptTime); https://msdn.microsoft.com/en-us/library/windows/desktop/ee662307(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Winbase.h", MSDNShortId = "ee662307")]
+ ///
+ ///
+ /// The interrupt-time count begins at zero when the system starts and is incremented at each clock interrupt by the length of a
+ /// clock tick. The exact length of a clock tick depends on underlying hardware and can vary between systems.
+ ///
+ ///
+ /// The interrupt-time count retrieved by the QueryUnbiasedInterruptTime function reflects only the time that the system is in
+ /// the working state. Therefore, the interrupt-time count is not "biased" by time the system spends in sleep or hibernation. The
+ /// system uses biased interrupt time for some operations, such as ensuring that relative timers that would have expired during sleep
+ /// expire immediately upon waking.
+ ///
+ ///
+ /// Unlike system time, the interrupt-time count is not subject to adjustments by users or the Windows time service. Applications can
+ /// use the interrupt-time count to measure finer durations than are possible with system time. Applications that require greater
+ /// precision than the interrupt-time count should use a high-resolution timer. Use the QueryPerformanceFrequency function to
+ /// retrieve the frequency of the high-resolution timer and the QueryPerformanceCounter function to retrieve the counter's value.
+ ///
+ ///
+ /// The timer resolution set by the timeBeginPeriod and timeEndPeriod functions affects the resolution of the
+ /// QueryUnbiasedInterruptTime function. However, increasing the timer resolution is not recommended because it can reduce
+ /// overall system performance and increase system power consumption by preventing the processor from entering power-saving states.
+ /// Instead, applications should use a high-resolution timer.
+ ///
+ ///
+ /// Note The QueryUnbiasedInterruptTime function produces different results on debug ("checked") builds of Windows,
+ /// because the interrupt-time count and tick count are advanced by approximately 49 days. This helps to identify bugs that might not
+ /// occur until the system has been running for a long time. The checked build is available to MSDN subscribers through the Microsoft
+ /// Developer Network (MSDN) Web site.
+ ///
+ ///
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0601 or later. For more information, see Using the
+ /// Windows Headers.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryunbiasedinterrupttime BOOL
+ // QueryUnbiasedInterruptTime( PULONGLONG UnbiasedTime );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "f9cf5440-9be9-4ff9-b85c-2779b847954c")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool QueryUnbiasedInterruptTime(out ulong lpUnbiasedInterruptTime);
///
- /// Gets the current unbiased interrupt-time count, in a more precise form than QueryUnbiasedInterruptTime does. The unbiased interrupt-time count
- /// does not include time the system spends in sleep or hibernation.
+ /// Gets the current unbiased interrupt-time count, in a more precise form than QueryUnbiasedInterruptTime does. The unbiased
+ /// interrupt-time count does not include time the system spends in sleep or hibernation.
///
///
- /// A pointer to a ULONGLONG in which to receive the unbiased interrupt-time count in system time units of 100 nanoseconds. Divide by ten million, or
- /// 1e7, to get seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
+ /// A pointer to a ULONGLONG in which to receive the unbiased interrupt-time count in system time units of 100 nanoseconds. Divide by
+ /// ten million, or 1e7, to get seconds (there are 1e9 nanoseconds in a second, so there are 1e7 100-nanoseconds in a second).
///
/// This function does not return a value.
- // VOID QueryUnbiasedInterruptTimePrecise( _Out_ PULONGLONG lpUnbiasedInterruptTimePrecise); https://msdn.microsoft.com/en-us/library/windows/desktop/dn891448(v=vs.85).aspx
- [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
- [PInvokeData("Realtimeapiset.h", MSDNShortId = "dn891448")]
+ ///
+ ///
+ /// QueryUnbiasedInterruptTimePrecise is similar to the QueryUnbiasedInterruptTime routine, but is more precise. The interrupt
+ /// time reported by QueryUnbiasedInterruptTime is based on the latest tick of the system clock timer. The system clock timer
+ /// is the hardware timer that periodically generates interrupts for the system clock. The uniform period between system clock timer
+ /// interrupts is referred to as a system clock tick, and is typically in the range of 0.5 milliseconds to 15.625 milliseconds,
+ /// depending on the hardware platform. The interrupt time value retrieved by QueryUnbiasedInterruptTime is accurate within a
+ /// system clock tick.
+ ///
+ ///
+ /// To provide a system time value that is more precise than that of QueryUnbiasedInterruptTime,
+ /// QueryUnbiasedInterruptTimePrecise reads the timer hardware directly, therefore a QueryUnbiasedInterruptTimePrecise
+ /// call can be slower than a QueryUnbiasedInterruptTime call.
+ ///
+ /// Call the KeQueryTimeIncrement routine to determine the duration of a system clock tick.
+ /// Also see Remarks in QueryUnbiasedInterruptTime.
+ ///
+ /// Note The QueryUnbiasedInterruptTimePrecise function produces different results on debug ("checked") builds of
+ /// Windows, because the interrupt-time count and tick count are advanced by approximately 49 days. This helps to identify bugs that
+ /// might not occur until the system has been running for a long time. The checked build is available to MSDN subscribers through the
+ /// Microsoft Developer Network (MSDN) Web site.
+ ///
+ ///
+ /// To compile an application that uses this function, define _WIN32_WINNT as 0x0601 or later. For more information, see Using the
+ /// Windows Headers.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryunbiasedinterrupttimeprecise void
+ // QueryUnbiasedInterruptTimePrecise( PULONGLONG lpUnbiasedInterruptTimePrecise );
+ [DllImport(Lib.KernelBase, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("realtimeapiset.h", MSDNShortId = "FADFC168-A3CF-4676-9B6E-7A4028049423")]
public static extern void QueryUnbiasedInterruptTimePrecise(out ulong lpUnbiasedInterruptTimePrecise);
}
}
\ No newline at end of file
diff --git a/UnitTests/PInvoke/Kernel32/RealtimeApiSetTests.cs b/UnitTests/PInvoke/Kernel32/RealtimeApiSetTests.cs
new file mode 100644
index 00000000..9c25550b
--- /dev/null
+++ b/UnitTests/PInvoke/Kernel32/RealtimeApiSetTests.cs
@@ -0,0 +1,84 @@
+using NUnit.Framework;
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using Vanara.InteropServices;
+using static Vanara.PInvoke.AdvApi32;
+using static Vanara.PInvoke.Kernel32;
+
+namespace Vanara.PInvoke.Tests
+{
+ [TestFixture]
+ public class RealtimeApiSetTests
+ {
+ [Test]
+ public void ConvertAuxiliaryCounterToPerformanceCounterTest()
+ {
+ ulong aux = (ulong)new Random().Next();
+ Assert.That(ConvertAuxiliaryCounterToPerformanceCounter(aux, out var perf, out var err), ResultIs.Successful);
+ Assert.That(ConvertPerformanceCounterToAuxiliaryCounter(perf, out var aux2, out err), ResultIs.Successful);
+ Assert.That(aux, Is.EqualTo(aux2));
+ }
+
+ [Test]
+ public void QueryAuxiliaryCounterFrequencyTest()
+ {
+ Assert.That(QueryAuxiliaryCounterFrequency(out var f), ResultIs.Successful);
+ Assert.That(f, Is.Not.Zero);
+ }
+
+ [Test]
+ public void QueryIdleProcessorCycleTimeTest()
+ {
+ Assert.That(() => { Assert.That(QueryIdleProcessorCycleTime(), Is.Not.Empty); }, Throws.Nothing);
+ }
+
+ [Test]
+ public void QueryIdleProcessorCycleTimeExTest()
+ {
+ Assert.That(() => { Assert.That(QueryIdleProcessorCycleTimeEx(0), Is.Not.Empty); }, Throws.Nothing);
+ }
+
+ [Test]
+ public void QueryInterruptTimeTest()
+ {
+ QueryInterruptTime(out var t);
+ Assert.That(t, Is.Not.Zero);
+ }
+
+ [Test]
+ public void QueryInterruptTimePreciseTest()
+ {
+ QueryInterruptTimePrecise(out var t);
+ Assert.That(t, Is.Not.Zero);
+ }
+
+ [Test]
+ public void QueryProcessCycleTimeTest()
+ {
+ Assert.That(QueryProcessCycleTime(GetCurrentProcess(), out var t), ResultIs.Successful);
+ Assert.That(t, Is.Not.Zero);
+ }
+
+ [Test]
+ public void QueryThreadCycleTimeTest()
+ {
+ Assert.That(QueryThreadCycleTime(GetCurrentThread(), out var t), ResultIs.Successful);
+ Assert.That(t, Is.Not.Zero);
+ }
+
+ [Test]
+ public void QueryUnbiasedInterruptTimeTest()
+ {
+ Assert.That(QueryUnbiasedInterruptTime(out var t), ResultIs.Successful);
+ Assert.That(t, Is.Not.Zero);
+ }
+
+ [Test]
+ public void QueryUnbiasedInterruptTimePreciseTest()
+ {
+ QueryUnbiasedInterruptTimePrecise(out var t);
+ Assert.That(t, Is.Not.Zero);
+ }
+ }
+}
\ No newline at end of file