示例#1
0
VOID
BenchmarkThreadPool(
    PLW_THREAD_POOL pPool,
    PBENCHMARK_SETTINGS pSettings,
    PULONG64 pullDuration,
    PULONG64 pullBytesTransferred
    )
{
    PLW_TASK_GROUP pGroup = NULL;
    PSOCKET* ppSockets1 = NULL;
    PSOCKET* ppSockets2 = NULL;
    size_t i = 0;
    ULONG64 ullTotal = 0;
    LONG64 llStart = 0;
    LONG64 llEnd = 0;
    ULONG64 ullTime = 0;
    NTSTATUS status;

    gpPool = pPool;
    gpSettings = pSettings;

    status = LwRtlCreateTaskGroup(gpPool, &pGroup);
    ASSERT_SUCCESS(status);

    status = LW_RTL_ALLOCATE_ARRAY_AUTO(&ppSockets1, gpSettings->ulPairs);
    ASSERT_SUCCESS(status);

    status = LW_RTL_ALLOCATE_ARRAY_AUTO(&ppSockets2, gpSettings->ulPairs);
    ASSERT_SUCCESS(status);

    for (i = 0; i < gpSettings->ulPairs; i++)
    {
        NTSTATUS status = CreateSocketPair(pGroup, &ppSockets1[i], &ppSockets2[i]);
        
        ASSERT_SUCCESS(status);
    }
    
    status = TimeNow(&llStart);
    ASSERT_SUCCESS(status);
    
    LwRtlWakeTaskGroup(pGroup);
    LwRtlWaitTaskGroup(pGroup);
    
    status = TimeNow(&llEnd);
    ASSERT_SUCCESS(status);
    
    ullTime = (ULONG64) (llEnd - llStart);
    
    LwRtlFreeTaskGroup(&pGroup);

    for (i = 0; i < gpSettings->ulPairs; i++)
    {
        ullTotal += ppSockets1[i]->ullTotalTransferred;
    }

    *pullDuration = ullTime;
    *pullBytesTransferred = ullTotal;
}
示例#2
0
NTSTATUS
RdrCreateContextArray(
    PIRP pIrp,
    ULONG ulCount,
    PRDR_OP_CONTEXT* ppContexts
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContexts = NULL;
    ULONG ulIndex = 0;

    status = LW_RTL_ALLOCATE_ARRAY_AUTO(&pContexts, ulCount);
    BAIL_ON_NT_STATUS(status);

    for (ulIndex = 0; ulIndex < ulCount; ulIndex++)
    {
        LwListInit(&pContexts[ulIndex].Link);
        pContexts[ulIndex].pIrp = pIrp;
    }

    *ppContexts = pContexts;

error:

    return status;
}
示例#3
0
NTSTATUS
InitWorkThreads(
    PLW_WORK_THREADS pThreads,
    PLW_THREAD_POOL_ATTRIBUTES pAttrs,
    int numCpus
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    size_t i = 0;

    RingInit(&pThreads->WorkItems);

    status = LwErrnoToNtStatus(pthread_mutex_init(&pThreads->Lock, NULL));
    GOTO_ERROR_ON_STATUS(status);
    pThreads->bDestroyLock = TRUE;

    status = LwErrnoToNtStatus(pthread_cond_init(&pThreads->Event, NULL));
    GOTO_ERROR_ON_STATUS(status);
    pThreads->bDestroyEvent = TRUE;

    pThreads->ulWorkThreadCount = GetWorkThreadsAttr(pAttrs, numCpus);
    pThreads->ulWorkThreadStackSize = pAttrs ? pAttrs->ulWorkThreadStackSize : 0;
    pThreads->ulWorkThreadTimeout = GetWorkThreadTimeoutAttr(pAttrs);

    if (pThreads->ulWorkThreadCount)
    {
        status = LW_RTL_ALLOCATE_ARRAY_AUTO(
            &pThreads->pWorkThreads,
            pThreads->ulWorkThreadCount);
        GOTO_ERROR_ON_STATUS(status);

        for (i = 0; i < pThreads->ulWorkThreadCount; i++)
        {
            pThreads->pWorkThreads[i].Thread = INVALID_THREAD_HANDLE;
        }
    }

    if (pThreads->ulWorkThreadTimeout == 0)
    {
        for (i = 0; i < pThreads->ulWorkThreadCount; i++)
        {
            status = StartWorkThread(pThreads, &pThreads->pWorkThreads[i]);
            GOTO_ERROR_ON_STATUS(status);
        }
    }
        
error:

    return status;
}
示例#4
0
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;
}
示例#6
0
NTSTATUS
RegisterTaskUnixSignal(
    LW_IN PLW_TASK pTask,
    LW_IN int Sig,
    LW_IN LW_BOOLEAN bSubscribe
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    size_t i = 0;
    PRING pBase = NULL;
    PRING pRing = NULL;
    PLW_SIGNAL_SUBSCRIPTION pExisting = NULL;
    PLW_SIGNAL_SUBSCRIPTION pSub = NULL;
    struct sigaction action;
#ifdef SIGRTMAX
    int maxSig = SIGRTMAX;
#else
    int maxSig = SIGUSR2;
#endif

    if (Sig == 0)
    {
        for (i = 1; i < maxSig + 1; i++)
        {
            status = RegisterTaskUnixSignal(pTask, (int) i, bSubscribe);
            if (status)
            {
                return status;
            }
        }

        return STATUS_SUCCESS;
    }

    LOCK_SIGNAL();

    if (Sig > maxSig || Sig < 0)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_ERROR_ON_STATUS(status);
    }

    if (!gSignal.pSubscribers)
    {
        status = LW_RTL_ALLOCATE_ARRAY_AUTO(&gSignal.pSubscribers, maxSig + 1);
        GOTO_ERROR_ON_STATUS(status);

        for (i = 0; i < maxSig + 1; i++)
        {
            RingInit(&gSignal.pSubscribers[i]);
        }
        
        gSignal.maxSig = maxSig;
    }

    pBase = &gSignal.pSubscribers[Sig];
    for (pRing = pBase->pNext; pRing != pBase; pRing = pRing->pNext)
    {
        pSub = LW_STRUCT_FROM_FIELD(pRing, LW_SIGNAL_SUBSCRIPTION, Ring);
        if (pSub->pTask == pTask)
        {
            pExisting = pSub;
            break;
        }
    }

    if (bSubscribe && !pExisting)
    {
        if (Sig != SIGINT)
        {
            memset(&action, 0, sizeof(action));
            
            /* Make sure there is a dummy handler for the signal
               so it is actually delivered to the process */
            action.sa_handler = DummyHandler;
            action.sa_flags = 0;
            
            if (sigaction(Sig, &action, NULL) < 0)
            {
                status = LwErrnoToNtStatus(errno);
                GOTO_ERROR_ON_STATUS(status);
            }
        }

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

        pSub->pTask = pTask;
        pSub->ucRefCount = 1;
        RingInit(&pSub->Ring);
        RingInit(&pSub->DispatchRing);

        RingEnqueue(pBase, &pSub->Ring);

        RetainTask(pTask);
    }
    else if (!bSubscribe && pExisting)
    {
        RingRemove(&pExisting->Ring);

        if (--pExisting->ucRefCount == 0)
        {
            LwRtlReleaseTask(&pExisting->pTask);
            LwRtlMemoryFree(pExisting);
        }
    }

error:

    UNLOCK_SIGNAL();

    return status;
}
示例#7
0
static
NTSTATUS
CreateSocketPair(
    PLW_TASK_GROUP pGroup,
    PSOCKET* ppSocket1,
    PSOCKET* ppSocket2
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSOCKET pSocket1 = NULL;
    PSOCKET pSocket2 = NULL;
    int socketFds[2] = {-1, -1};

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

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

    status = LW_RTL_ALLOCATE_ARRAY_AUTO(&pSocket1->pBuffer, gpSettings->ulBufferSize);
    GOTO_ERROR_ON_STATUS(status);

    status = LW_RTL_ALLOCATE_ARRAY_AUTO(&pSocket2->pBuffer, gpSettings->ulBufferSize);
    GOTO_ERROR_ON_STATUS(status);

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketFds) < 0)
    {
        status = LwErrnoToNtStatus(errno);
        GOTO_ERROR_ON_STATUS(status);
    }

    pSocket1->Fd = socketFds[0];
    pSocket2->Fd = socketFds[1];
    
    pSocket1->State = STATE_SEND;
    pSocket2->State = STATE_RECV;

    status = LwRtlCreateTask(
        gpPool,
        &pSocket1->pTask,
        pGroup,
        Transceiver,
        pSocket1);
    GOTO_ERROR_ON_STATUS(status);

    status = LwRtlCreateTask(
        gpPool,
        &pSocket2->pTask,
        pGroup,
        Transceiver,
        pSocket2);
    GOTO_ERROR_ON_STATUS(status);

    *ppSocket1 = pSocket1;
    *ppSocket2 = pSocket2;

cleanup:
    
    return status;

error:

    goto cleanup;
}