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