Geoff Chappell, Software Analyst
This function sets the profile interval for a given profile source.
NTSTATUS NtSetIntervalProfile ( ULONG Interval, KPROFILE_SOURCE ProfileSource);
in version 3.51 and higher, but
NTSTATUS NtSetIntervalProfile (ULONG Interval);
in versions 3.10 and 3.50.
The Interval argument provides the new time or count that is to separate profile interrupts that have the given source. The unit of measurement depends on the source.
The ProfileSource argument selects a possible source of profile interrupts.
The function returns STATUS_SUCCESS if successful, else a negative error code.
The NtSetIntervalProfile function and its alias ZwSetIntervalProfile are exported by name from NTDLL in version 3.10 and higher. In kernel mode, where ZwSetIntervalProfile is a stub and NtSetIntervalProfile is the implementation, neither is exported.
Neither NtSetIntervalProfile nor its alias is documented. As ZwSetIntervalProfile, it is declared in the ZWAPI.H file in the Windows Driver Kit (WDK) for Windows 10.
Unusually for native API functions, no repackaging of NtSetIntervalProfile, documented or not, is known in any higher-level user-mode module that is distributed as standard with Windows.
The following implementation notes are from inspection of the kernel from the original release of Windows 10 only. They may some day get revised to account for earlier versions. Meanwhile, where anything is added about earlier versions, take it not as an attempt at comprehensiveness but as a bonus from my being unable to resist a trip down memory lane or at least a quick look into the history.
The function requires SeSystemProfilePrivilege. Without it, the function returns STATUS_PRIVILEGE_NOT_HELD. With it, the function necessarily succeeds, but the behaviour is not trivial. It may help to sketch the basic behaviour before getting to details.
All profile sources other than ProfileAlignmentFixup (0x01) are managed by the HAL. On each currently active processor, the kernel calls the HAL via the HalSetSystemInformation pointer in the kernel’s HAL_DISPATCH, specifically for the information class HalProfileSourceInterval (0x00), giving the Interval and ProfileSource as the information.
What, if anything, the HAL does with the Interval and ProfileSource is immaterial to the NtSetIntervalProfile function. Some points to watch for can be surmised as interface features. The profile source might not be supported. For each supported profile source, the HAL has a minimum and maximum interval which can be learnt in advance even from user mode through TraceQueryInformation with the information class TraceProfileSourceListInfo (0x07). How the HAL is required to respond to an attempt to set an interval that is too small or too large is unclear. Indeed, it’s not clear that the HAL is required to accept any interval exactly as given. If it matters, e.g., for calculations, to know what interval the HAL uses, it might be prudent to follow NtSetIntervalProfile with a call to NtQueryIntervalProfile.
Beware anyway that profile sources are global. An interval that one process sets for a profile source can be changed by any other sufficiently privileged process’s call to the same function for the same profile source.
If the tracing of profile events to NT Kernel Logger sessions is enabled when the function has set the interval, the function will trace an event to record what the interval changed from. If the tracing of profile events is already enabled before the function sets the interval, the function first queries for the current setting, as preparation.
The profile source ProfileTime (0) has special interest to the kernel for cache errata support. If the desired Interval is larger than the kernel needs for that support, the kernel’s interval is what gets set.
For ProfileAlignmentFixup, the kernel does not involve the HAL but simply remembers the given Interval. No known x86 or x64 build of Windows in any version has any other use of this interval except that it can be set and queried.
Once the interval has been set as described above, if tracing of profile events is enabled, the function queries for what actually did get set as the new interval and puts both the new and old settings in an event. If tracing was not enabled before the function set the interval, then zero is used as the old setting. The hook ID for the event that records the change of interval is PERFINFO_LOG_TYPE_SAMPLED_PROFILE_SET_INTERVAL (0x0F48).