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

时间:2023-02-03 18:15:44

I am writing the UMS scheduler for managing large number of UMS worker threads and I have encountered a very strange issue. By some reason the maximum number of UMS threads that I can create is 8192 (there is no such problem with the normal threads, I can easily create >20 000 of them).

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

The error returned by the call to CreateRemoteThreadEx is 1450 "Insufficient system resources"

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

The PC has the following configuration:

PC具有以下配置:

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

I have tried the following:

我尝试过以下方法:

  1. Increase Process Working Set (no effect)
  2. 增加流程工作集(无效)
  3. Increase number of SystemPages through registry (no effect, right now it is set to 0)
  4. 通过注册表增加SystemPages的数量(没有效果,现在它被设置为0)
  5. I have checked the Free Pages, Non-paged and paged pools limits (non of them is starving during the CreateRemoteThreadEx call)
  6. 我已经检查了免费页面,非分页和分页池限制(在CreateRemoteThreadEx调用期间它们没有饿死)
  7. I have tried that on another PC (2GB of RAM, Inter Core 2 Duo processors, Windows 8.1x64 and got the same magic number 8192).
  8. 我在另一台PC(2GB内存,Inter Core 2 Duo处理器,Windows 8.1x64,并获得相同的幻数8192)上尝试过。

Here is a code sample to test:

这是一个要测试的代码示例:

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

I run this snippet on another PC and it worked fine (I have created 20000 UMS Threads).

我在另一台PC上运行这个片段,它工作正常(我创建了20000 UMS线程)。

PC Configuration:

PC配置:

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

So basically this looks like a some sort of limitation (and looks like it can be changed).

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

Do you have any ideas?

你有什么想法?

Update: After installation of the latest updates on the box nothing has changed.

更新:在框上安装最新更新后,没有任何更改。

1 个解决方案

#1


2  

I can't find it right now but at some point I read that the UMS Kernel side implementation used Intel's LDT to map each UMS thread.

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

8192 is exactly the number of entries in the LDT table. The LDT could be managed in a number of creative ways in the Win7 Kernel so it could be that 8192 is the limit per process, per thread or maybe the limit per core. You'll have to experiment setting processor affinity or having more UMS scheduler threads to see if you can get past this limit.

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

#1


2  

I can't find it right now but at some point I read that the UMS Kernel side implementation used Intel's LDT to map each UMS thread.

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

8192 is exactly the number of entries in the LDT table. The LDT could be managed in a number of creative ways in the Win7 Kernel so it could be that 8192 is the limit per process, per thread or maybe the limit per core. You'll have to experiment setting processor affinity or having more UMS scheduler threads to see if you can get past this limit.

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