{"id":4993,"date":"2014-03-30T17:40:28","date_gmt":"2014-03-30T17:40:28","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/does-mutex-call-a-system-call-collection-of-common-programming-errors\/"},"modified":"2014-03-30T17:40:28","modified_gmt":"2014-03-30T17:40:28","slug":"does-mutex-call-a-system-call-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/does-mutex-call-a-system-call-collection-of-common-programming-errors\/","title":{"rendered":"Does Mutex call a system call?-Collection of common programming errors"},"content":{"rendered":"<p>The implementation of critical sections in Windows has changed over the years, but it has always been a combination of user-mode and kernel calls.<\/p>\n<p>The CRITICAL_SECTION is a structure that contains a user-mode updated values, a handle to a kernel-mode object &#8211; EVENT or something like that, and debug information.<\/p>\n<p>EnterCriticalSection uses an interlocked test-and-set operation to acquire the lock. If successful, this is all that is required (almost, it also updates the owner thread). If the set-and-set operation fails to aquire, a longer path is used which usually requires waiting on a kernel object with <code>WaitForSignleObject<\/code>. If you initialized with <code>InitializeCriticalSectionAndSpinCount<\/code> then <code>EnterCriticalSection<\/code> may spin an retry to acquire using interlocked operation in user-mode.<\/p>\n<p>Below is a diassembly of the &#8220;fast&#8221; \/ uncontended path of <code>EnterCriticialSection<\/code> in Windows 7 (64-bit) with some comments inline<\/p>\n<pre><code>0:000&gt; u rtlentercriticalsection rtlentercriticalsection+35\nntdll!RtlEnterCriticalSection:\n00000000`77ae2fc0 fff3            push    rbx\n00000000`77ae2fc2 4883ec20        sub     rsp,20h\n; RCX points to the critical section rcx+8 is the LockCount\n00000000`77ae2fc6 f00fba710800    lock btr dword ptr [rcx+8],0\n00000000`77ae2fcc 488bd9          mov     rbx,rcx\n00000000`77ae2fcf 0f83e9b1ffff    jae     ntdll!RtlEnterCriticalSection+0x31 (00000000`77ade1be)\n; got the critical section - update the owner thread and recursion count\n00000000`77ae2fd5 65488b042530000000 mov   rax,qword ptr gs:[30h]\n00000000`77ae2fde 488b4848        mov     rcx,qword ptr [rax+48h]\n00000000`77ae2fe2 c7430c01000000  mov     dword ptr [rbx+0Ch],1\n00000000`77ae2fe9 33c0            xor     eax,eax\n00000000`77ae2feb 48894b10        mov     qword ptr [rbx+10h],rcx\n00000000`77ae2fef 4883c420        add     rsp,20h\n00000000`77ae2ff3 5b              pop     rbx\n00000000`77ae2ff4 c3              ret\n<\/code><\/pre>\n<p>So the bottom line is that if the thread does not need to block it will not use a system call, just an interlocked test-and-set operation. If blocking is required, there will be a system call. The release path also uses an interlocked test-and-set and may require a system call if other threads are blocked.<\/p>\n<p>Compare this to Mutex which always requires a system call <code>NtWaitForSingleObject<\/code> and <code>NtReleaseMutant<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The implementation of critical sections in Windows has changed over the years, but it has always been a combination of user-mode and kernel calls. The CRITICAL_SECTION is a structure that contains a user-mode updated values, a handle to a kernel-mode object &#8211; EVENT or something like that, and debug information. EnterCriticalSection uses an interlocked test-and-set [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4993","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4993","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=4993"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4993\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=4993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=4993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=4993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}