Windows关键部分-如何完全禁用旋转 [英] Windows Critical Section - how to disable spinning completely

查看:121
本文介绍了Windows关键部分-如何完全禁用旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过不同的方法将CRITICAL_SECTION的旋转计数设置为零:

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);
}

在Windows 7中,所有结果均为0.

在Windows 10中,除了最后一个,所有结果均为0x020007D0值.最后一个结果是0x02000000.

In Windows 10, except the last one, all result in 0x020007D0 value. The last one result in 0x02000000.

显然,0x07D0是实际旋转计数(十进制的2000),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

我怕RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN可能会导致关键部分旋转,即使我通过使用SetCriticalSectionSpinCount要求它不旋转也是如此.

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.

有什么方法可以不使用标准文档化的API来定义RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN吗?

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.

InitializeCriticalSectionEx与非零旋转计数一起使用时,未设置RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN标志.所以这段代码输出00000001:

When InitializeCriticalSectionEx is used with nonzero spin count, RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN flag is not set. So this code outputs 00000001:

::InitializeCriticalSectionEx(&cs, 1, 0);
printf("Spin count after explicit one %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);

一个旋转计数几乎为零.而且,随后调用SetCriticalSectionSpinCount可以将其重置为零.所以这段代码输出00000000:

One spin count is almost zero spin count. And, moreover, with calling SetCriticalSectionSpinCount afterwards it can be reset to zero. So this code outputs 00000000:

::InitializeCriticalSectionEx(&cs, 1, 0);
::SetCriticalSectionSpinCount(&cs, 0);
printf("Spin count after explicit one and then reset to zero %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);

当然,应该有充分的理由禁止旋转.默认情况下,正如@JonathanPotter指出的那样,旋转是好的.否则,它不会被设置为默认行为.因此,我什至没有将禁用旋转的解决方案应用于我原来的问题.

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.

另一方面,关键部分的维护者无意不尊重传递给InitializeCriticalSectionExInitializeCriticalSectionAndSpinCount的零旋转计数.他们只是确保普通InitializeCriticalSection获得自动旋转计数.

On the other hand, it may be not the intention of maintainers of critical section to disrespect zero spin count passed to InitializeCriticalSectionEx or InitializeCriticalSectionAndSpinCount. They just made sure that plain InitializeCriticalSection gets automatic spin count.

这篇关于Windows关键部分-如何完全禁用旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆