Does Mutex call a system call?
Asked Answered
M

4

5

CRITICAL_SECTION locking (enter) and unlocking (leave) are efficient because CS testing is performed in user space without making the kernel system call that a mutex makes. Unlocking is performed entirely in user space, whereas ReleaseMutex requires a system call.

I just read these sentences in this book.
What the kernel system call mean? Could you give me the function's name?

I'm a English newbie. I interpreted them like this.

  • CS testing doesn't use a system call.
  • Mutex testing uses a system call.(But I don't know the function name. Let me know)
  • CS unlocking doesn't call a system call.
  • Mutex unlocking requires a system call.(But I don't know the function name. Let me know)

Another question.

  • I think CRITICAL_SECTION might call WaitForSingleObject or family functions. Don't these functions require a system call? I guess they do. So CS testing doesn't use a system call is very weird to me.
Motorboat answered 3/3, 2011 at 2:51 Comment(1)
Spin-locks are indeed meant for kernel use (of course you can spin doing nothing in your own program, but that doesn't help). The answer below regarding spin-locks was previously misleading but the poster has corrected it now.Wade
C
7

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 - EVENT or something like that, and debug information.

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 test-and-set operation fails to aquire, a longer path is used which usually requires waiting on a kernel object with WaitForSignleObject. If you initialized with InitializeCriticalSectionAndSpinCount then EnterCriticalSection may spin an retry to acquire using interlocked operation in user-mode.

Below is a diassembly of the "fast" / uncontended path of EnterCriticialSection in Windows 7 (64-bit) with some comments inline

0:000> u rtlentercriticalsection rtlentercriticalsection+35
ntdll!RtlEnterCriticalSection:
00000000`77ae2fc0 fff3            push    rbx
00000000`77ae2fc2 4883ec20        sub     rsp,20h
; RCX points to the critical section rcx+8 is the LockCount
00000000`77ae2fc6 f00fba710800    lock btr dword ptr [rcx+8],0
00000000`77ae2fcc 488bd9          mov     rbx,rcx
00000000`77ae2fcf 0f83e9b1ffff    jae     ntdll!RtlEnterCriticalSection+0x31 (00000000`77ade1be)
; got the critical section - update the owner thread and recursion count
00000000`77ae2fd5 65488b042530000000 mov   rax,qword ptr gs:[30h]
00000000`77ae2fde 488b4848        mov     rcx,qword ptr [rax+48h]
00000000`77ae2fe2 c7430c01000000  mov     dword ptr [rbx+0Ch],1
00000000`77ae2fe9 33c0            xor     eax,eax
00000000`77ae2feb 48894b10        mov     qword ptr [rbx+10h],rcx
00000000`77ae2fef 4883c420        add     rsp,20h
00000000`77ae2ff3 5b              pop     rbx
00000000`77ae2ff4 c3              ret

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.

Compare this to Mutex which always requires a system call NtWaitForSingleObject and NtReleaseMutant

Caladium answered 21/5, 2011 at 5:1 Comment(0)
J
4

Calling to the kernel requires a context switch, which is takes a small (but measurable) performance hit for every context switch. The function in question is ReleaseMutex() itself.

The critical section functions are available in kernel32.dll (at least from the caller's point of view - see comments for discussion about ntdll.dll) and can often avoid making any calls into the kernel.

It is worthwhile to know that Mutex objects can be accessed from different processes at the same time. On the other hand, CRITICAL_SECTION objects are limited to one process.

Jotham answered 3/3, 2011 at 2:55 Comment(6)
The other function in question is one of the wait functions such as WaitForSingleObject used to acquire a mutex, which once again incurs a system call.Wade
@Greg Hewgill: I'm sorry I have to correct you on this one, but it's a simple function forwarder (within the export table) pointing to NTDLL.RtlEnterCriticalSection.Sixfooter
A syscall is not the same as a context switch. Transitioning to the kernel increases the privilege level, but it isn't necessary to save floating point state, reconfigure page tables, or much of the other complexity associated with context switching.Lytle
@STATUS: True, but not really relevant. ntdll.dll is also a user-mode DLL (although most of its functions are implemented as thin wrappers over a syscall, the documentation indicates that this one is not).Lytle
@Ben Voigt: oh, I think it is relevant, because it directly rejects the statement in the answer that the functions are implemented in kernel32.dll. I'm aware of the other details, both on the user mode side and the kernel mode side of the native APIs.Sixfooter
A context switch is not the same thing as a mode switch.Canker
S
1

To my knowledge critical sections are implemented using semaphores.

The critical section functions are implemented in NTDLL, which implements some runtime functions in user mode and passes control so the kernel for others (system call). The functions in kernel32.dll are simple function forwarders.

Mutexes on the other hand are kernel objects and require a system call as such. The kernel calls them "mutants", by the way (no joke).

Sixfooter answered 3/3, 2011 at 3:6 Comment(4)
Spin-locks are for mutual exclusion within the kernel and are used very sparingly because they waste cycles. User threads can't afford to sit spinning doing nothing -- the lock test is done in user-space, but the thread will still block if the lock isn't free.Wade
@casablanca: I'm sorry, I was confusing it because of the use of InitializeCriticalSectionAndSpinCount. It uses semaphores.Sixfooter
I've removed my downvote. Also, the part about the lock prefix is correct -- it is indeed used for testing locks, but it's different from a spin-lock.Wade
@casablanca: yes, I removed that part. Should still be in the version history if anyone needs to know. Yep, a spin lock would be one of the few synchronization methods available at certain IRQLs that cannot "wait" (higher than APC level, IIRC).Sixfooter
M
1

Critical section calls only transition to kernel mode if there is contention and only then if they can't relieve the contention by spinning. In that case the thread blocks and calls a wait function – that's a system call.

Miriam answered 3/3, 2011 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.