用户模式调度程序线程的最大数量

时间:2014-11-24 07:54:23

标签: c++ c multithreading windows-server-2012-r2

我正在编写用于管理大量UMS工作线程的UMS调度程序,我遇到了一个非常奇怪的问题。由于某种原因,我可以创建的UMS线程的最大数量是8192(普通线程没有这样的问题,我可以很容易地创建> 20 000个)。

调用CreateRemoteThreadEx返回的错误是1450“系统资源不足”

PC具有以下配置:

  • Windows Server 2012R2 Datacenter x64
  • 16GB或RAM
  • 2xIntel Xeon 5520处理器
  • 1TB的磁盘空间

我尝试了以下内容:

  1. 增加流程工作集(无效)
  2. 通过注册表增加SystemPages的数量(无效,现在设置为0)
  3. 我检查了免费页面,非分页和分页池限制(在CreateRemoteThreadEx调用期间没有它们正在挨饿)
  4. 我在另一台PC(2GB内存,Inter Core 2 Duo处理器,Windows 8.1x64,并获得相同的幻数8192)上尝试了这一点。
  5. 以下是要测试的代码示例:

    DWORD
    UmsThreadRoutine(
        PVOID pState
    )
    {
        UNREFERENCED_PARAMETER(pState);
        return 0;
    };
    
    int main(int args, char **argv)
    {
        PCHAR pMessage = "Program End";
        DWORD dwErrorCode = ERROR_SUCCESS;
        DWORD dwIteration = 0;
        PUMS_COMPLETION_LIST pUmsCompletionList = NULL;
        if (!::CreateUmsCompletionList(&pUmsCompletionList))
        {
            pMessage = "CreateUmsCompletionList";
            goto EXIT_POINT;
        }
    
        for (int i = 0; i < 20000; ++i)
        {
            dwIteration = i;
            LPPROC_THREAD_ATTRIBUTE_LIST pAttributes = NULL;
            SIZE_T szAttributes = 0;
    
            if (::InitializeProcThreadAttributeList(NULL, 1, 0, &szAttributes))
            {
                pMessage = "InitializeProcThreadAttributeList(Size)";
                goto EXIT_POINT;
            }
    
            pAttributes = (LPPROC_THREAD_ATTRIBUTE_LIST)::malloc(szAttributes);
            if (pAttributes == NULL)
            {
                pMessage = "malloc";
                goto EXIT_POINT;
            }
            if (!::InitializeProcThreadAttributeList(pAttributes, 1, 0, &szAttributes))
            {
                pMessage = "InitializeProcThreadAttributeList";
                goto EXIT_POINT;
            }
    
            PUMS_CONTEXT pUmsContext = NULL;
            if (!::CreateUmsThreadContext(&pUmsContext))
            {
                pMessage = "CreateUmsThreadContext";
                goto EXIT_POINT;
            }
    
            UMS_CREATE_THREAD_ATTRIBUTES umsCreationAttributes = { UMS_VERSION, pUmsContext, pUmsCompletionList };
            if (!::UpdateProcThreadAttribute(pAttributes, 0, PROC_THREAD_ATTRIBUTE_UMS_THREAD, &umsCreationAttributes, sizeof(UMS_CREATE_THREAD_ATTRIBUTES), NULL, NULL))
            {
                pMessage = "UpdateProcThreadAttribute";
                goto EXIT_POINT;
            }
    
            DWORD dwId = 0;
            HANDLE hThread = ::CreateRemoteThreadEx(
                ::GetCurrentProcess(),
                NULL,
                0,
                (LPTHREAD_START_ROUTINE)::UmsThreadRoutine,
                NULL,
                CREATE_SUSPENDED,
                pAttributes,
                &dwId
            );
            if (hThread == NULL)
            {
                pMessage = "CreateRemoteThreadEx";
                goto EXIT_POINT;
            }
    
            ::DeleteProcThreadAttributeList(pAttributes);
        }
    
        EXIT_POINT:
        dwErrorCode = ::GetLastError();
        ::printf("Program exited with Error Code '%d' on step '%s' on iteration '%d'", dwErrorCode, pMessage, dwIteration);
    }
    

    我在另一台PC上运行此代码片段并且工作正常(我创建了20000个UMS线程)。

    PC配置:

    • Windows 8.1 Enterprise x64
    • 英特尔酷睿i5-3470
    • 8 GB RAM
    • 1 TB的可用空间。

    所以基本上这看起来像某种限制(看起来可以改变)。

    你有什么想法吗?

    更新:在包装盒上安装最新更新后,一切都没有改变。

1 个答案:

答案 0 :(得分:2)

我现在无法找到它,但在某些时候我读到UMS内核端实现使用Intel LDT来映射每个UMS线程。

8192正好是LDT表中的条目数。可以在Win7内核中以多种创造性的方式管理LDT,因此可能是8192是每个进程的限制,每个线程或每个核心的限制。您必须尝试设置处理器亲缘关系或拥有更多UMS调度程序线程,以确定您是否可以超过此限制。