I'm trying to set spin count for CRITICAL_SECTION to zero by different methods:
int main()
{
CRITICAL_SECTION cs;
::InitializeCriticalSection(&cs);
printf("Spin count by default %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);
::InitializeCriticalSectionAndSpinCount(&cs, 0);
printf("Spin count with zero spin count init %08X\n", cs.SpinCount );
::DeleteCriticalSection(&cs);
::InitializeCriticalSectionEx(&cs, 0, 0);
printf("Spin count with zero spin count and flags init %08X\n", cs.SpinCount );
::DeleteCriticalSection(&cs);
::InitializeCriticalSection(&cs);
::SetCriticalSectionSpinCount(&cs, 0);
printf("Spin count after explicit reset to zero %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);
}
In Windows 7, all results are 0 as expected.
In Windows 10, except the last one, all result in 0x020007D0
value. The last one result in 0x02000000
.
Apparently, 0x07D0
is actual spin count (2000
in decimal), and 0x02000000
is one of these flags:
#define RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO 0x01000000
#define RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN 0x02000000
#define RTL_CRITICAL_SECTION_FLAG_STATIC_INIT 0x04000000
#define RTL_CRITICAL_SECTION_FLAG_RESOURCE_TYPE 0x08000000
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO 0x10000000
I'm afraid that RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN
may cause critical section to spin even if I asked it not to spin by using SetCriticalSectionSpinCount
.
Is there any way not to define RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN
by using standard documented APIs ?
After peeking into the implementation, figured out answer myself.
When
InitializeCriticalSectionEx
is used with nonzero spin count,RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN
flag is not set. So this code outputs00000001
:One spin count is almost zero spin count. And, moreover, with calling
SetCriticalSectionSpinCount
afterwards it can be reset to zero. So this code outputs00000000
:Sure, there should be compelling reason to disable spinning. By default, as @JonathanPotter pointed out, spinning is good. Otherwise it wouldn't have been set as default behavior. So I didn't even apply the solution for disabling spinning to my original problem.
On the other hand, it may be not the intention of maintainers of critical section to disrespect zero spin count passed to
InitializeCriticalSectionEx
orInitializeCriticalSectionAndSpinCount
. They just made sure that plainInitializeCriticalSection
gets automatic spin count.