{"id":36,"date":"2020-06-04T11:48:46","date_gmt":"2020-06-04T11:48:46","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=36"},"modified":"2020-06-04T11:48:46","modified_gmt":"2020-06-04T11:48:46","slug":"rdtsc-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/06\/04\/rdtsc-cs\/","title":{"rendered":"Rdtsc.cs"},"content":{"rendered":"\n<p>Rdtsc 32 and 64 Bit In C#<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing System.Security;\npublic static class Rdtsc\n{\n    [SuppressUnmanagedCodeSecurity]\n    [UnmanagedFunctionPointer(CallingConvention.StdCall)]\n    public delegate ulong FuncUInt64();\n    private const          uint       PAGE_READWRITE         = 0x04;\n    private const          uint       PAGE_EXECUTE           = 0x10;\n    private const          uint       PAGE_EXECUTE_READWRITE = 0x40;\n    private const          uint       MEM_COMMIT             = 0x1000;\n    private const          uint       MEM_RELEASE            = 0x8000;\n    public static readonly FuncUInt64 Timestamp;\n    public static readonly FuncUInt64 TimestampP;\n    public static readonly bool       IsRdtscSupported;\n    public static readonly bool       IsRdtscPSupported;\n    static Rdtsc()\n    {\n        SystemInfo systemInfo;\n        GetNativeSystemInfo(out systemInfo);\n        if (systemInfo.wProcessorArchitecture != 0 &amp;&amp; systemInfo.wProcessorArchitecture != 9)\n        {\n            Timestamp         = StopwatchGetTimestamp;\n            TimestampP        = StopwatchGetTimestamp;\n            IsRdtscSupported  = false;\n            IsRdtscPSupported = false;\n            return;\n        }\n        byte[] cpuid;\n        byte[] rdtsc;\n        byte[] rdtscp;\n        byte[] rdtsccpuid;\n        IsRdtscSupported = true;\n        if (Is64Bit())\n        {\n            cpuid = new byte[]\n            {\n                0x53, 0xB8, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xA2, 0xBB, 0x01, 0x00, 0x00, 0x80, 0x39, 0xD8, 0x72, 0x16, 0x89, 0xD8,\n                0x48, 0xC7, 0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xA2, 0x89, 0xC8, 0x48, 0xC1, 0xE0, 0x20, 0x48, 0x09, 0xD0, 0xEB,\n                0x03, 0x48, 0x31, 0xC0, 0x5B, 0xC3\n            };\n            rdtsc  = new byte[] {0x0F, 0x31, 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x09, 0xD0, 0xC3};\n            rdtscp = new byte[] {0x0F, 0x01, 0xF9, 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x09, 0xD0, 0xC3};\n            rdtsccpuid = new byte[]\n                {0x53, 0x31, 0xC0, 0x0F, 0xA2, 0x0F, 0x31, 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x09, 0xD0, 0x5B, 0xC3};\n        }\n        else\n        {\n            cpuid = new byte[]\n            {\n                0x53, 0xB8, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xA2, 0xBB, 0x01, 0x00, 0x00, 0x80, 0x39, 0xD8, 0x72, 0x0A, 0x89, 0xD8,\n                0x0F, 0xA2, 0x89, 0xD0, 0x89, 0xCA, 0xEB, 0x04, 0x31, 0xC0, 0x31, 0xD2, 0x5B, 0xC3\n            };\n            rdtsc      = new byte[] {0x0F, 0x31, 0xC3};\n            rdtscp     = new byte[] {0x0F, 0x01, 0xF9, 0xC3};\n            rdtsccpuid = new byte[] {0x53, 0x31, 0xC0, 0x0F, 0xA2, 0x0F, 0x31, 0x5B, 0xC3};\n        }\n        var buf = IntPtr.Zero;\n        try\n        {\n            var cpuidLength      = (cpuid.Length      &amp; 63) != 0 ? (cpuid.Length      | 63) + 1 : cpuid.Length;\n            var rdtscLength      = (rdtsc.Length      &amp; 63) != 0 ? (rdtsc.Length      | 63) + 1 : rdtsc.Length;\n            var rdtscpLength     = (rdtscp.Length     &amp; 63) != 0 ? (rdtscp.Length     | 63) + 1 : rdtscp.Length;\n            var rdtsccpuidLength = (rdtsccpuid.Length &amp; 63) != 0 ? (rdtsccpuid.Length | 63) + 1 : rdtsccpuid.Length;\n            var totalLength      = cpuidLength + rdtscLength + Math.Max(rdtscpLength, rdtsccpuidLength);\n            buf = VirtualAlloc(IntPtr.Zero, (IntPtr) totalLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\n            if (buf != IntPtr.Zero)\n            {\n                Marshal.Copy(cpuid, 0, buf, cpuid.Length);\n                for (var i = cpuid.Length; i &lt; cpuidLength; i++)\n                    Marshal.WriteByte(buf, i, 0x90);\n                Marshal.Copy(rdtsc, 0, buf + cpuidLength, rdtsc.Length);\n                for (var i = rdtsc.Length; i &lt; rdtscLength; i++)\n                    Marshal.WriteByte(buf, cpuidLength + i, 0x90);\n                var    cpuidFunc         = (FuncUInt64) Marshal.GetDelegateForFunctionPointer(buf, typeof(FuncUInt64));\n                var    supportedFeatures = cpuidFunc();\n                byte[] rdtscpSelected;\n                int    rdtscpSelectedLength;\n                if ((supportedFeatures &amp; (1L &lt;&lt; 27)) != 0)\n                {\n                    rdtscpSelected       = rdtscp;\n                    rdtscpSelectedLength = rdtscpLength;\n                    IsRdtscPSupported    = true;\n                }\n                else\n                {\n                    rdtscpSelected       = rdtsccpuid;\n                    rdtscpSelectedLength = rdtsccpuidLength;\n                    IsRdtscPSupported    = false;\n                }\n                Marshal.Copy(rdtscpSelected, 0, buf + cpuidLength + rdtscLength, rdtscpSelected.Length);\n                for (var i = rdtscpSelected.Length; i &lt; rdtscpSelectedLength; i++)\n                    Marshal.WriteByte(buf, cpuidLength + rdtscLength + i, 0x90);\n                var result = VirtualProtect(buf, (IntPtr) totalLength, PAGE_EXECUTE, out var oldProtection);\n                if (result)\n                {\n                    Timestamp = (FuncUInt64) Marshal.GetDelegateForFunctionPointer(buf + cpuidLength, typeof(FuncUInt64));\n                    TimestampP = (FuncUInt64) Marshal.GetDelegateForFunctionPointer(buf + cpuidLength + rdtscLength,\n                        typeof(FuncUInt64));\n                    buf = IntPtr.Zero;\n                }\n            }\n        }\n        finally\n        {\n            if (buf != IntPtr.Zero)\n                VirtualFree(buf, IntPtr.Zero, MEM_RELEASE);\n        }\n    }\n    private static bool Is64Bit()\n    {\n        return Marshal.SizeOf(typeof(IntPtr)) == 8;\n    }\n    [DllImport(\"kernel32.dll\", ExactSpelling = true)]\n    private static extern void GetNativeSystemInfo(out SystemInfo lpSystemInfo);\n    [DllImport(\"kernel32.dll\", ExactSpelling = true, SetLastError = true)]\n    private static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);\n    [DllImport(\"kernel32.dll\", ExactSpelling = true, SetLastError = true)]\n    [return: MarshalAs(UnmanagedType.Bool)]\n    private static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, out uint lpflOldProtect);\n    [DllImport(\"kernel32.dll\", ExactSpelling = true, SetLastError = true)]\n    [return: MarshalAs(UnmanagedType.Bool)]\n    private static extern bool VirtualFree(IntPtr lpAddress, IntPtr dwSize, uint dwFreeType);\n    private static ulong StopwatchGetTimestamp()\n    {\n        return unchecked((ulong) Stopwatch.GetTimestamp());\n    }\n    [StructLayout(LayoutKind.Sequential)]\n    private struct SystemInfo\n    {\n        public readonly ushort wProcessorArchitecture;\n        public readonly ushort wReserved;\n        public readonly uint   dwPageSize;\n        public readonly IntPtr lpMinimumApplicationAddress;\n        public readonly IntPtr lpMaximumApplicationAddress;\n        public readonly IntPtr dwActiveProcessorMask;\n        public readonly uint   dwNumberOfProcessors;\n        public readonly uint   dwProcessorType;\n        public readonly uint   dwAllocationGranularity;\n        public readonly ushort wProcessorLevel;\n        public readonly ushort wProcessorRevision;\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Rdtsc 32 and 64 Bit In C#<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/36"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=36"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/36\/revisions"}],"predecessor-version":[{"id":37,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/36\/revisions\/37"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=36"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=36"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=36"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}