{"id":2823,"date":"2013-10-28T07:00:00","date_gmt":"2013-10-28T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/10\/28\/using-getlogicalprocessorinformationex-to-see-the-relationship-between-logical-and-physical-processors\/"},"modified":"2013-10-28T07:00:00","modified_gmt":"2013-10-28T07:00:00","slug":"using-getlogicalprocessorinformationex-to-see-the-relationship-between-logical-and-physical-processors","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20131028-00\/?p=2823","title":{"rendered":"Using GetLogicalProcessorInformationEx to see the relationship between logical and physical processors"},"content":{"rendered":"<p>\nToday&#8217;s Little Program uses the\n<code>Get&shy;Logical&shy;Processor&shy;Information&shy;Ex<\/code>\nfunction to print the mapping of logical processors to\nphysical processors,\nas well as the mapping of logical processors to packages.\n(A dual-core processor is a single package with two cores.\nIf those cores are themselves dual-hyperthreaded, then you have\nfour logical processors total.)\n<\/p>\n<pre>\n#define STRICT\n#include &lt;windows.h&gt;\n#include &lt;stdio.h&gt;\ntemplate&lt;typename T&gt;\nT *AdvanceBytes(T *p, SIZE_T cb)\n{\n return reinterpret_cast&lt;T*&gt;(reinterpret_cast&lt;BYTE *&gt;(p) + cb);\n}\n<\/pre>\n<p>\nThe <code>Advance&shy;Bytes<\/code> helper function takes\na typed pointer and adds a byte offset to it.\nThis is just a typing-saver function.\n<\/p>\n<p><pre>\nclass EnumLogicalProcessorInformation\n{\npublic:\n EnumLogicalProcessorInformation(LOGICAL_PROCESSOR_RELATIONSHIP Relationship)\n  : m_pinfoBase(nullptr), m_pinfoCurrent(nullptr), m_cbRemaining(0)\n {\n  DWORD cb = 0;\n  if (GetLogicalProcessorInformationEx(Relationship,\n                                       nullptr, &amp;cb)) return;\n  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return;\n  m_pinfoBase =\n   reinterpret_cast&lt;SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *&gt;\n                                     (LocalAlloc(LMEM_FIXED, cb));\n  if (!m_pinfoBase) return;\n  if (!GetLogicalProcessorInformationEx(Relationship,\n                                        m_pinfoBase, &amp;cb)) return;\n  m_pinfoCurrent = m_pinfoBase;\n  m_cbRemaining = cb;\n }\n ~EnumLogicalProcessorInformation() { LocalFree(m_pinfoBase); }\n void MoveNext()\n {\n  if (m_pinfoCurrent) {\n   m_cbRemaining -= m_pinfoCurrent-&gt;Size;\n   if (m_cbRemaining) {\n    m_pinfoCurrent = AdvanceBytes(m_pinfoCurrent,\n                                  m_pinfoCurrent-&gt;Size);\n   } else {\n    m_pinfoCurrent = nullptr;\n   }\n  }\n }\n SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *Current()\n                                         { return m_pinfoCurrent; }\nprivate:\n SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *m_pinfoBase;\n SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *m_pinfoCurrent;\n DWORD m_cbRemaining;\n};\n<\/pre>\n<p>\nEnumerating logical processor information is complicated due\nto the variable-size structures, so I wrap it inside this helper\nenumerator class.\n<\/p>\n<p>\nConstruct it with the relationship you are interested in,\nthen use <code>Current()<\/code> to see the current item\nand <code>Move&shy;Next()<\/code> to move to the next item.\nWhen there are no more items,\n<code>Current()<\/code> returns <code>nullptr<\/code>.\n<\/p>\n<p>\nThe constructor does the standard two-step query we&#8217;ve seen\nbefore:\nAsk for the required buffer size, then allocate a buffer,\nthen ask for the buffer to be filled in.\nThere is a TOCTTOU race condition if\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ff562404(v=VS.85).aspx\">\na processor is added dynamically<\/a>,\nbut I&#8217;m going to ignore that case\nbecause this is a Little Program.\n<\/p>\n<p>\nSince the\n<code>SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX<\/code>\nstructure is variable-sized,\nwalking the packed array is not a simple array indexing operation.\nInstead, you have to bump the pointer by the <code>Size<\/code> of the\ncurrent element to find the next element.\n<\/p>\n<p>\nNext comes a helper function to print processor affinity bitmasks.\n<\/p>\n<pre>\nvoid PrintMask(KAFFINITY Mask)\n{\n printf(\" [\");\n for (int i = 0; i &lt; sizeof(Mask) * 8; i++) {\n  if (Mask &amp; (static_cast&lt;KAFFINITY&gt;(1) &lt;&lt; i)) {\n   printf(\" %d\", i);\n  }\n }\n printf(\" ]\");\n}\n<\/pre>\n<p>\nNothing exciting there.\n<\/p>\n<p>\nFinally, we wrap it up inside a sample program that enumerates\nthe cores and then, just for fun, enumerates the packages.\n<\/p>\n<pre>\nint __cdecl main(int argc, char **argv)\n{\n for (EnumLogicalProcessorInformation enumInfo(RelationProcessorCore);\n      auto pinfo = enumInfo.Current(); enumInfo.MoveNext()) {\n   PrintMask(pinfo-&gt;Processor.GroupMask[0].Mask);\n   printf(\"\\n\");\n }\n for (EnumLogicalProcessorInformation enumInfo(RelationProcessorPackage);\n      auto pinfo = enumInfo.Current(); enumInfo.MoveNext()) {\n   printf(\"[\");\n   for (UINT GroupIndex = 0; GroupIndex &lt; pinfo-&gt;Processor.GroupCount; GroupIndex++) {\n    PrintMask(pinfo-&gt;Processor.GroupMask[GroupIndex].Mask);\n   }\n   printf(\" ]\\n\");\n }\n return 0;\n}\n<\/pre>\n<p>\nEnumerating processor cores produces a bunch of\n<code>PROCESSOR_RELATIONSHIP<\/code> structures,\neach with a single group that describes the logical processors\nassigned to the core.\n<\/p>\n<p>\nEnumerating processor packages produces a bunch of\n<code>PROCESSOR_RELATIONSHIP<\/code> structures,\nand each one contains as many groups as there are cores in the package.\n<\/p>\n<p>\n<b>Bonus chatter<\/b>:\nThe\n<a HREF=\"http:\/\/technet.microsoft.com\/en-us\/sysinternals\/cc835722.aspx\">\nCoreInfo<\/a> utility from Sysinternals\nis a command-line tool that is a fancier version of this Little Program.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today&#8217;s Little Program uses the Get&shy;Logical&shy;Processor&shy;Information&shy;Ex function to print the mapping of logical processors to physical processors, as well as the mapping of logical processors to packages. (A dual-core processor is a single package with two cores. If those cores are themselves dual-hyperthreaded, then you have four logical processors total.) #define STRICT #include &lt;windows.h&gt; #include [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-2823","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Today&#8217;s Little Program uses the Get&shy;Logical&shy;Processor&shy;Information&shy;Ex function to print the mapping of logical processors to physical processors, as well as the mapping of logical processors to packages. (A dual-core processor is a single package with two cores. If those cores are themselves dual-hyperthreaded, then you have four logical processors total.) #define STRICT #include &lt;windows.h&gt; #include [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2823","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=2823"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2823\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=2823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=2823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=2823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}