Partilhar via


No Guarded Mutex in Win8?

As the MSDN article “Fast Mutexes and Guarded Mutexes” says,

Starting with Windows 8, guarded mutexes and fast mutexes are implemented identically.

If you check WDK8 header file wdm.h, KGUARDED_MUTEX equals to FAST_MUTEX:

typedef struct _FAST_MUTEX {  volatile LONG Count;  PVOID Owner;  ULONG Contention;  KEVENT Event;  ULONG OldIrql;  } FAST_MUTEX, *PFAST_MUTEX, KGUARDED_MUTEX, *PKGUARDED_MUTEX;

 

In WDK7.1 wdm.h, KGUARDED_MUTEX is defined as below:

typedef struct _KGUARDED_MUTEX {  volatile LONG Count;  PKTHREAD Owner;  ULONG Contention;  KGATE Gate;  union {  struct {  SHORT KernelApcDisable;  SHORT SpecialApcDisable;  };  ULONG CombinedApcDisable;  };  } KGUARDED_MUTEX, *PKGUARDED_MUTEX;

 

Before Win8, People use guarded mutex, because comparing to fast mutex, guarded mutex is faster, more importantly, it will not raise IRQL to APC_LEVEL, which means the protected code can stay at PASSIVE_LEVEL in synchronization. A code path that is protected by fast mutex runs at IRQL = APC_LEVEL.

The problem is ‘OLD‘ Win7 KGUARDED_MUTEX was implemented based on guarded region, which disables all APCs (Normal Kernel APC and Special Kernel APC). This identical to raise current IRQL to APC_LEVEL.  As such, any APIs that are illegal at APC_LEVEL are also illegal in protection of guarded mutex. Win8 made the conscious choice to unify the code implementation for fast mutex and guarded mutex. They are identical.

Here’s a blog calling out the fact that calling passive level APIs in guarded regions is bad:

https://blogs.technet.com/b/fbsblogs/archive/2008/12/26/failing-io_2700_s-issued-at-apc-level-or-with-special-kernel-apcs-disabled-_2800_except-in-the-case-of-paging-io_2900_.aspx