NTSTATUS
LwRtlCreateThreadPool(
    PLW_THREAD_POOL* ppPool,
    PLW_THREAD_POOL_ATTRIBUTES pAttrs
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PLW_THREAD_POOL pPool = NULL;
    int i = 0;
    int numCpus = 0;

    status = LW_RTL_ALLOCATE_AUTO(&pPool);
    GOTO_ERROR_ON_STATUS(status);

    status = LwErrnoToNtStatus(pthread_mutex_init(&pPool->Lock, NULL));
    GOTO_ERROR_ON_STATUS(status);

    status = LwErrnoToNtStatus(pthread_cond_init(&pPool->Event, NULL));
    GOTO_ERROR_ON_STATUS(status);

    numCpus = LwRtlGetCpuCount();

    if (GetDelegateAttr(pAttrs))
    {
        status = AcquireDelegatePool(&pPool->pDelegate);
        GOTO_ERROR_ON_STATUS(status);
    }
    else
    {
        pPool->ulEventThreadCount = GetTaskThreadsAttr(pAttrs, numCpus);

        if (pPool->ulEventThreadCount)
        {
            status = LW_RTL_ALLOCATE_ARRAY_AUTO(
                &pPool->pEventThreads,
                pPool->ulEventThreadCount);
            GOTO_ERROR_ON_STATUS(status);

            for (i = 0; i < pPool->ulEventThreadCount; i++)
            {
                status = InitEventThread(pPool, pAttrs, &pPool->pEventThreads[i], i % numCpus);
                GOTO_ERROR_ON_STATUS(status);
            }
        }
    }

    status = InitWorkThreads(&pPool->WorkThreads, pAttrs, numCpus);
    GOTO_ERROR_ON_STATUS(status);

    *ppPool = pPool;

cleanup:

    return status;

error:

    LwRtlFreeThreadPool(&pPool);

    goto cleanup;
}
NTSTATUS
LwRtlCreateThreadPool(
    PLW_THREAD_POOL* ppPool,
    PLW_THREAD_POOL_ATTRIBUTES pAttrs
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PLW_THREAD_POOL pPool = NULL;
    int i = 0;
    int numCpus = 0;
    ULONG ulFdLimit = 0;

#if defined(_SC_NPROCESSORS_ONLN)
    numCpus = sysconf(_SC_NPROCESSORS_ONLN);

    if (numCpus < 0)
    {
        numCpus = 1;
    }
#else
    numCpus = 1;
#endif
   

    GOTO_ERROR_ON_STATUS(status = LW_RTL_ALLOCATE_AUTO(&pPool));
    
    GOTO_ERROR_ON_STATUS(status = LwErrnoToNtStatus(pthread_mutex_init(&pPool->Lock, NULL)));
    GOTO_ERROR_ON_STATUS(status = LwErrnoToNtStatus(pthread_cond_init(&pPool->Event, NULL)));

    if (GetDelegateAttr(pAttrs))
    {
        status = AcquireDelegatePool(&pPool->pDelegate);
        GOTO_ERROR_ON_STATUS(status);
    }
    else
    {
        pPool->ulEventThreadCount = GetTaskThreadsAttr(pAttrs, numCpus);
        pPool->ulNextEventThread = 0;

        status = GetFdLimit(&ulFdLimit);
        GOTO_ERROR_ON_STATUS(status);

        /*
         * Each thread needs 2 fds for the notification pipe.
         * This check will limit us to 1/4 of the process fd limit.
         * This is particularly important on Solaris which has a very
         * low default limit of 256.
         */
        if (pPool->ulEventThreadCount > ulFdLimit / 8)
        {
            pPool->ulEventThreadCount = ulFdLimit / 8;
        }

        if (pPool->ulEventThreadCount)
        {
            GOTO_ERROR_ON_STATUS(status = LW_RTL_ALLOCATE_ARRAY_AUTO(
                                     &pPool->pEventThreads,
                                     pPool->ulEventThreadCount));
            for (i = 0; i < pPool->ulEventThreadCount; i++)
            {
                GOTO_ERROR_ON_STATUS(status = SelectThreadInit(pAttrs, &pPool->pEventThreads[i]));
            }
        }
    }

    status = InitWorkThreads(&pPool->WorkThreads, pAttrs, numCpus);
    GOTO_ERROR_ON_STATUS(status);

    *ppPool = pPool;

error:

    return status;
}