-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Summary
x86 based hardware introduced the waitpkg
ISA back in 2020 which can be used to better facilitate low-power and low-latency spin-loops.
API Suggestion
namespace System.Runtime.Intrinsics.X86;
[Intrinsic]
[CLSCompliant(false)]
public abstract class WaitPkg : X86Base
{
public static new bool IsSupported { get; }
// UMONITOR: void _umonitor(void *address);
public static unsafe void SetUpUserLevelMonitor(void* address);
// UMWAIT: uint8_t _umwait(uint32_t control, uint64_t counter);
public static bool WaitForUserLevelMonitor(uint control, ulong counter);
// TPAUSE: uint8_t _tpause(uint32_t control, uint64_t counter);
public static bool TimedPause(uint control, ulong counter);
[Intrinsic]
public new abstract class X64 : X86Base.X64
{
internal X64() { }
public static new bool IsSupported { get; }
}
}
Additional Considerations
There is a model specific register IA32_UMWAIT_CONTROL
(MSR 0xE1
) which provides additional information. However, model specific registers can only be read by ring 0 (the kernel) and as such this information is not available to user mode programs without the underlying OS exposing an explicit API. As such, this information is not surfaced to the end user.
IA32_UMWAIT_CONTROL[31:2]
— Determines the maximum time in TSC-quanta that the processor can reside in either C0.1 or C0.2. A zero value indicates no maximum time. The maximum time value is a 32-bit value where the upper 30 bits come from this field and the lower two bits are zero.IA32_UMWAIT_CONTROL[1]
— Reserved.IA32_UMWAIT_CONTROL[0]
— C0.2 is not allowed by the OS. Value of “1” means all C0.2 requests revert to C0.1.
This information is not strictly pertinent to the user either and would not normally influence their use of the APIs. For example, if IA32_UMWAIT_CONTROL[0]
is 1
, it simply means that a user call of TimedPause
where control == 0
will be treated as control == 1
:
Bit Value | State Name | Wakeup Time | Power Savings | Other Benefits |
---|---|---|---|---|
bit[0] = 0 | C0.2 | Slower | Larger | Improves performance of the other SMT thread(s) on the same core |
bit[0] = 1 | C0.1 | Faster | Smaller | N/A |
bits[31:1] | N/A | N/A | N/A | Reserved |
Likewise, if the user specified counter
is larger than IA32_UMWAIT_CONTROL[31:2]
then TimedPause
returns true
indicating that the pause ended due to expiration of the operating system time-limit rather than reaching/exceeding the specified counter
(returns false
). The same applies to WaitForUserLevelMonitor
.