static NTSTATUS InitPool( VOID ) { NTSTATUS status = STATUS_SUCCESS; PLW_THREAD_POOL pNewPool = NULL; if (!gSvcmState.pPool) { status = LwRtlCreateThreadPool(&pNewPool, NULL); GCOS(status); if (InterlockedCompareExchangePointer( OUT_PPVOID(&gSvcmState.pPool), pNewPool, NULL) != NULL) { LwRtlFreeThreadPool(&pNewPool); } } cleanup: return status; }
VOID ReleaseDelegatePool( PLW_THREAD_POOL* ppPool ) { BOOLEAN bFree = FALSE; if (*ppPool) { pthread_mutex_lock(&gpDelegateLock); assert(*ppPool == gpDelegatePool); if (--gpDelegatePoolRefCount == 0) { gpDelegatePool = NULL; bFree = TRUE; } pthread_mutex_unlock(&gpDelegateLock); } if (bFree) { LwRtlFreeThreadPool(ppPool); } }
VOID LwRtlSvcmFreePool( VOID ) { LwRtlFreeThreadPool((PLW_THREAD_POOL*) &gSvcmState.pPool); }
VOID SvcmDestructor( VOID ) { LwRtlFreeThreadPool((PLW_THREAD_POOL*) &gSvcmState.pPool); }
static NTSTATUS RdrShutdown( VOID ) { NTSTATUS status = STATUS_SUCCESS; /* We need to run down all cached tress/session/sockets sitting around. * Set the global shutdown flag, then cancel and wait for each task group * in turn. */ RdrSetShutdown(); if (gRdrRuntime.pTreeTimerGroup) { LwRtlCancelTaskGroup(gRdrRuntime.pTreeTimerGroup); LwRtlWaitTaskGroup(gRdrRuntime.pTreeTimerGroup); } if (gRdrRuntime.pSessionTimerGroup) { LwRtlCancelTaskGroup(gRdrRuntime.pSessionTimerGroup); LwRtlWaitTaskGroup(gRdrRuntime.pSessionTimerGroup); } if (gRdrRuntime.pSocketTimerGroup) { LwRtlCancelTaskGroup(gRdrRuntime.pSocketTimerGroup); LwRtlWaitTaskGroup(gRdrRuntime.pSocketTimerGroup); } /* All socket tasks should have been canceled by this point, * so wait for them to finish shutting down */ if (gRdrRuntime.pSocketTaskGroup) { LwRtlWaitTaskGroup(gRdrRuntime.pSocketTaskGroup); } /* Now we can free everything */ LwRtlFreeTaskGroup(&gRdrRuntime.pTreeTimerGroup); LwRtlFreeTaskGroup(&gRdrRuntime.pSessionTimerGroup); LwRtlFreeTaskGroup(&gRdrRuntime.pSocketTimerGroup); LwRtlFreeTaskGroup(&gRdrRuntime.pSocketTaskGroup); SMBHashSafeFree(&gRdrRuntime.pSocketHashByName); LwRtlFreeThreadPool(&gRdrRuntime.pThreadPool); /* Free the global mutex */ if (gRdrRuntime.bLockConstructed) { pthread_mutex_destroy(&gRdrRuntime.Lock); gRdrRuntime.bLockConstructed = FALSE; } 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; }
int main( int argc, char** ppszArgv ) { DWORD dwError = 0; /* Parse command line */ dwError = LwSmParseArguments(argc, ppszArgv); BAIL_ON_ERROR(dwError); /* Block all signals */ dwError = LwNtStatusToWin32Error(LwRtlBlockSignals()); BAIL_ON_ERROR(dwError); /* Fork into background if running as a daemon */ if (gState.bStartAsDaemon) { dwError = LwSmDaemonize(); BAIL_ON_ERROR(dwError); } /* If we're starting as the control server, acquire lock */ if (!gState.bContainer) { dwError = LwSmControlLock(); BAIL_ON_ERROR(dwError); } /* Create thread pool */ dwError = LwNtStatusToWin32Error(LwRtlCreateThreadPool(&gpPool, NULL)); BAIL_ON_ERROR(dwError); dwError = LWNetExtendEnvironmentForKrb5Affinity(FALSE); BAIL_ON_ERROR(dwError); /* Mac OS X - avoid potential circular calls into directory services */ dwError = LwDsCacheAddPidException(getpid()); BAIL_ON_ERROR(dwError); /* Initialize i18n */ setlocale(LC_ALL, ""); /* Initialize logging subsystem */ LwSmLogInit(); /* Set up logging */ dwError = LwSmConfigureLogging(gState.pName); BAIL_ON_ERROR(dwError); /* Initialize the container subsystem */ dwError = LwSmContainerInit(); BAIL_ON_ERROR(dwError); /* Initialize the service table subsystem */ dwError = LwSmTableInit(); BAIL_ON_ERROR(dwError); /* Enter main loop */ dwError = LwSmMain(); BAIL_ON_ERROR(dwError); error: /* If we are starting as a daemon and have not notified the parent process yet, notify it of an error now */ if (gState.bStartAsDaemon && !gState.bNotified) { LwSmNotify(dwError); } /* Shut down service table */ LwSmTableShutdown(); /* Shut down containers */ LwSmContainerShutdown(); /* Shut down logging */ LwSmLoggingShutdown(); /* Remove DS cache exception */ LwDsCacheRemovePidException(getpid()); /* Free thread pool */ LwRtlFreeThreadPool(&gpPool); /* Close control file if it is open */ if (gState.ControlLock >= 0) { close(gState.ControlLock); } if (dwError) { fprintf(stderr, "Error: %s (%d)\n", LwWin32ExtErrorToName(dwError), (int) dwError); } return dwError ? 1 : 0; }
static DWORD LwSmCmdTapLog( int argc, char** pArgv ) { DWORD error = ERROR_SUCCESS; PLW_THREAD_POOL pPool = NULL; PLW_TASK pTask = NULL; BOOLEAN bResetLogger = FALSE; BOOLEAN bRmPipe = FALSE; LW_SM_LOGGER_TYPE oldLogger = 0; PSTR pOldTarget = NULL; LW_SM_LOG_LEVEL oldLevel = 0; LW_SM_LOG_LEVEL newLevel = 0; PSTR pFacility = NULL; LW_SERVICE_HANDLE hHandle = NULL; PWSTR pServiceName = NULL; PSTR pFifo = NULL; int FifoFd = -1; if (argc < 4) { error = LW_ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(error); } if (strcmp(pArgv[1], "-")) { error = LwMbsToWc16s(pArgv[1], &pServiceName); BAIL_ON_ERROR(error); error = LwSmAcquireServiceHandle(pServiceName, &hHandle); BAIL_ON_ERROR(error); } if (strcmp(pArgv[2], "-")) { pFacility = pArgv[2]; } error = LwSmLogLevelNameToLogLevel(pArgv[3], &newLevel); BAIL_ON_ERROR(error); error = LwSmGetServiceLogState(hHandle, pFacility, &oldLogger, &pOldTarget, &oldLevel); BAIL_ON_ERROR(error); error = LwAllocateStringPrintf(&pFifo, "/tmp/.lwsm-log-tap-%lu", (unsigned long) getpid()); BAIL_ON_ERROR(error); LwRtlBlockSignals(); if (mknod(pFifo, S_IRUSR | S_IWUSR | S_IFIFO, 0) < 0) { error = LwErrnoToWin32Error(errno); BAIL_ON_ERROR(error); } bRmPipe = TRUE; if ((FifoFd = open(pFifo, O_RDONLY | O_NONBLOCK)) < 0) { error = LwErrnoToWin32Error(errno); BAIL_ON_ERROR(error); } if (fcntl(FifoFd, F_SETFL, O_NONBLOCK) < 0) { error = LwErrnoToWin32Error(errno); BAIL_ON_ERROR(error); } error = LwSmSetServiceLogTarget(hHandle, pFacility, LW_SM_LOGGER_FILE, pFifo); BAIL_ON_ERROR(error); bResetLogger = TRUE; error = LwSmSetServiceLogLevel(hHandle, pFacility, newLevel); BAIL_ON_ERROR(error); error = LwNtStatusToWin32Error(LwRtlCreateThreadPool(&pPool, NULL)); BAIL_ON_ERROR(error); error = LwNtStatusToWin32Error(LwRtlCreateTask(pPool, &pTask, NULL, LogTapper, &FifoFd)); BAIL_ON_ERROR(error); LwRtlWakeTask(pTask); error = LwNtStatusToWin32Error(LwRtlMain()); BAIL_ON_ERROR(error); error: if (pTask) { LwRtlCancelTask(pTask); LwRtlWaitTask(pTask); LwRtlReleaseTask(&pTask); } LwRtlFreeThreadPool(&pPool); if (bResetLogger) { error = LwSmSetServiceLogLevel(hHandle, pFacility, oldLevel); BAIL_ON_ERROR(error); error = LwSmSetServiceLogTarget(hHandle, pFacility, oldLogger, pOldTarget); BAIL_ON_ERROR(error); } if (pOldTarget) { LwSmFreeLogTarget(pOldTarget); } if (FifoFd >= 0) { close(FifoFd); } if (bRmPipe) { unlink(pFifo); } LW_SAFE_FREE_MEMORY(pFifo); return error; }
NTSTATUS AcquireDelegatePool( PLW_THREAD_POOL* ppPool ) { NTSTATUS status = STATUS_SUCCESS; LW_THREAD_POOL_ATTRIBUTES attrs = { .bDelegateTasks = FALSE, .lTaskThreads = -1, .lWorkThreads = 0, .ulTaskThreadStackSize = 0, .ulWorkThreadStackSize = 0 }; if (getenv("LW_GLOBAL_TASK_THREADS")) { attrs.lTaskThreads = (LONG) atoi(getenv("LW_GLOBAL_TASK_THREADS")); } pthread_mutex_lock(&gpDelegateLock); if (!gpDelegatePool) { status = LwRtlCreateThreadPool(&gpDelegatePool, &attrs); GOTO_ERROR_ON_STATUS(status); gpDelegatePoolRefCount = 1; } else { gpDelegatePoolRefCount++; } *ppPool = gpDelegatePool; cleanup: pthread_mutex_unlock(&gpDelegateLock); return status; error: goto cleanup; } VOID ReleaseDelegatePool( PLW_THREAD_POOL* ppPool ) { BOOLEAN bFree = FALSE; if (*ppPool) { pthread_mutex_lock(&gpDelegateLock); assert(*ppPool == gpDelegatePool); if (--gpDelegatePoolRefCount == 0) { gpDelegatePool = NULL; bFree = TRUE; } pthread_mutex_unlock(&gpDelegateLock); } if (bFree) { LwRtlFreeThreadPool(ppPool); } }