{"id":3823,"date":"2013-07-12T07:00:00","date_gmt":"2013-07-12T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/07\/12\/if-you-want-to-track-whether-the-current-thread-owns-a-critical-section-you-can-use-the-critical-section-itself-to-protect-it\/"},"modified":"2013-07-12T07:00:00","modified_gmt":"2013-07-12T07:00:00","slug":"if-you-want-to-track-whether-the-current-thread-owns-a-critical-section-you-can-use-the-critical-section-itself-to-protect-it","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130712-00\/?p=3823\/","title":{"rendered":"If you want to track whether the current thread owns a critical section, you can use the critical section itself to protect it"},"content":{"rendered":"<p>\nYou may find yourself in the situation where you want to keep\ntrack of the owner of a critical section.\nThis is usually for debugging or diagnostic purposes.\nFor example,\na particular function may have as a prerequisite that a particular\ncritical section is held,\nand you want to assert this so that you can catch the problem\nwhen running the debug build.\n<\/p>\n<p><pre>\nclass CriticalSectionWithOwner\n{\npublic:\n  CriticalSectionWithOwner() : m_Owner(0), m_EntryCount(0)\n  {\n    InitializeCriticalSection(&amp;m_cs);\n  }\n  ~CriticalSectionWithOwner()\n  {\n    DeleteCriticalSection(&amp;m_cs);\n  }\n  void Enter()\n  {\n    EnterCriticalSection(&amp;m_cs);\n#ifdef DEBUG\n    m_Owner = GetCurrentThreadId();\n    m_EntryCount++;\n#endif\n  }\n  void Leave()\n  {\n#ifdef DEBUG\n    if (--m_EntryCount == 0) {\n      m_Owner = 0;\n    }\n#endif\n    LeaveCriticalSection(&amp;m_cs);\n  }\n#ifdef DEBUG\n  bool IsHeldByCurrentThread()\n  {\n    return m_EntryCount &amp;&amp;\n           m_Owner == GetCurrentThreadId();\n  }\n#endif\nprivate:\n  CRITICAL_SECTION m_cs;\n#ifdef DEBUG\n  DWORD m_Owner;\n  int m_EntryCount;\n#endif\n};\n<\/pre>\n<p>\nAfter we successfully enter the critical section,\nwe mark the current thread as the owner and increment the\nentry count.\nBefore leaving the critical section, we see if this is the last exit,\nand if so, we clear the owner field.\n<\/p>\n<p>\nNote that we update the owner and entry count while the critical\nsection is held.\nWe are using the critical section to protect its own diagnostic data.\n<\/p>\n<p>\nThe subtle part is the\n<code>Is&shy;Held&shy;By&shy;Current&shy;Thread<\/code> function.\nLet&#8217;s look at the cases:\n<\/p>\n<p>\nFirst, if the current thread is the owner of the critical section,\nthen we know that the diagnostic data is safe to access\nbecause we own the critical section that protects it.\nThat&#8217;s not the subtle part.\n<\/p>\n<p>\nThe subtle part is the case where the current thread is <i>not<\/i>\nthe owner of the critical section.\nA na&iuml;ve analysis would say that the diagnostic data is off limits\nbecause you are trying to access it without owning the protective\ncritical section.\nBut what value can\n<code>m_Owner<\/code> have at this point?\n<\/p>\n<ol>\n<li>If the critical section is not held, then\n    <code>m_Owner<\/code> will be zero, which will be unequal to the\n    current thread ID.<\/p>\n<li>If the critical section is held, then\n    <code>m_Owner<\/code> will be the owner of the critical section,\n    which will also be unequal to the current thread ID.\n<\/ol>\n<p>\nBut what if the value of <code>m_Owner<\/code> changes while we\nare looking at it?\nWell, since we are not the owner of the critical section,\nit can only change between the two states above\n(possibly from one state&nbsp;2 to another state&nbsp;2).\nIn other words, it can only change from one value that is not\nequal to the current thread ID\nto another value that is <i>still<\/i> not equal to the current\nthread ID.\nTherefore, even if we race against another thread entering or\nleaving the critical section,\nthe fact that the owner of the critical section is <i>not us<\/i>\ndoesn&#8217;t change.\n<\/p>\n<p>\nNote that this analysis assumes that the <code>m_Owner<\/code>\nis a suitably-aligned value that can be updated atomically.\n(If not, then it&#8217;s possible that a torn value will be read\nwhich coincidentally matches our thread ID.)\n<\/p>\n<p>\nSince the <code>CRITICAL_SECTION<\/code> itself must already\nbe suitably aligned,\nplacing the <code>DWORD<\/code> up against it will also align\nthe <code>DWORD<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You may find yourself in the situation where you want to keep track of the owner of a critical section. This is usually for debugging or diagnostic purposes. For example, a particular function may have as a prerequisite that a particular critical section is held, and you want to assert this so that you can [&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-3823","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You may find yourself in the situation where you want to keep track of the owner of a critical section. This is usually for debugging or diagnostic purposes. For example, a particular function may have as a prerequisite that a particular critical section is held, and you want to assert this so that you can [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/3823","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=3823"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/3823\/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=3823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=3823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=3823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}