Exemplo n.º 1
0
static
VOID
DispatchSignal(
    siginfo_t* pInfo
    )
{
    RING dispatch;
    PRING pBase = NULL;
    PRING pRing = NULL;
    PRING pNext = NULL;
    PLW_SIGNAL_SUBSCRIPTION pSub = NULL;

    if (!gSignal.pSubscribers || pInfo->si_signo > gSignal.maxSig || pInfo->si_signo < 0)
    {
        return;
    }

    RingInit(&dispatch);

    pBase = &gSignal.pSubscribers[pInfo->si_signo];
    for (pRing = pBase->pNext; pRing != pBase; pRing = pRing->pNext)
    {
        pSub = LW_STRUCT_FROM_FIELD(pRing, LW_SIGNAL_SUBSCRIPTION, Ring);
        
        pSub->ucRefCount++;
        RingInit(&pSub->DispatchRing);
        RingEnqueue(&dispatch, &pSub->DispatchRing);
    }

    UNLOCK_SIGNAL();
    for (pRing = dispatch.pNext; pRing != &dispatch; pRing = pRing->pNext)
    {
        pSub = LW_STRUCT_FROM_FIELD(pRing, LW_SIGNAL_SUBSCRIPTION, DispatchRing);
        
        NotifyTaskUnixSignal(pSub->pTask, pInfo);
    }
    LOCK_SIGNAL();

    for (pRing = dispatch.pNext; pRing != &dispatch; pRing = pNext)
    {
        pNext = pRing->pNext;
        pSub = LW_STRUCT_FROM_FIELD(pRing, LW_SIGNAL_SUBSCRIPTION, DispatchRing);
        
        if (--pSub->ucRefCount == 0)
        {
            RingRemove(&pSub->Ring);
            LwRtlReleaseTask(&pSub->pTask);
            LwRtlMemoryFree(pSub);
        }
    }
}
Exemplo n.º 2
0
VOID
PvfsZctCloseCcb(
    IN PPVFS_CCB pCcb
    )
{
    BOOLEAN bMutexLocked = FALSE;
    PLW_LIST_LINKS pZctCtxLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    PPVFS_ZCT_CONTEXT pZctContext = NULL;

    LWIO_LOCK_MUTEX(bMutexLocked, &pCcb->FileMutex);

    pZctCtxLink = PvfsListTraverse(pCcb->pZctContextList, NULL);

    while (pZctCtxLink)
    {
        pZctContext = LW_STRUCT_FROM_FIELD(
                          pZctCtxLink,
                          PVFS_ZCT_CONTEXT,
                          CcbLinks);

        pNextLink = PvfsListTraverse(pCcb->pZctContextList, pZctCtxLink);
        PvfsListRemoveItem(pCcb->pZctContextList, pZctCtxLink);
        pZctCtxLink = pNextLink;

        PvfsFreeZctContext(&pZctContext);
    }

    LWIO_UNLOCK_MUTEX(bMutexLocked, &pCcb->FileMutex);
}
Exemplo n.º 3
0
VOID
LwRtlCancelTaskGroup(
    PLW_TASK_GROUP group
    )
{
    PRING ring = NULL;
    PLW_TASK pTask = NULL;
    ULONG i = 0;

    LOCK_GROUP(group);

    group->bCancelled = TRUE;

    for (i = 0; i < group->pPool->ulEventThreadCount; i++)
    {
        LOCK_THREAD(&group->pPool->pEventThreads[i]);
    }

    for (ring = group->Tasks.pNext; ring != &group->Tasks; ring = ring->pNext)
    {
        pTask = LW_STRUCT_FROM_FIELD(ring, SELECT_TASK, GroupRing);

        pTask->TriggerSet |= LW_TASK_EVENT_EXPLICIT | LW_TASK_EVENT_CANCEL;        
    }

    for (i = 0; i < group->pPool->ulEventThreadCount; i++)
    {
        SignalThread(&group->pPool->pEventThreads[i]);
        UNLOCK_THREAD(&group->pPool->pEventThreads[i]);
    }

    UNLOCK_GROUP(group);
}
Exemplo n.º 4
0
static
PVDIR_PAGED_SEARCH_RECORD
VmDirPagedSearchCacheFind(
    PCSTR pszCookie
    )
{
    DWORD dwError = 0;
    PLW_HASHTABLE_NODE pNode = NULL;
    PVDIR_PAGED_SEARCH_RECORD pSearchRecord = NULL;
    BOOLEAN bInLock = FALSE;

    if (IsNullOrEmptyString(pszCookie))
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER);
    }

    VMDIR_LOCK_MUTEX(bInLock, gPagedSearchCache.mutex);
    dwError = LwRtlHashTableFindKey(
                    gPagedSearchCache.pHashTbl,
                    &pNode,
                    (PVOID)pszCookie);
    dwError = LwNtStatusToWin32Error(dwError);
    BAIL_ON_VMDIR_ERROR(dwError);

    pSearchRecord = LW_STRUCT_FROM_FIELD(pNode, VDIR_PAGED_SEARCH_RECORD, Node);
    _RefPagedSearchRecord(pSearchRecord);

cleanup:
    VMDIR_UNLOCK_MUTEX(bInLock, gPagedSearchCache.mutex);
    return pSearchRecord;
error:
    goto cleanup;
}
Exemplo n.º 5
0
VOID
LwRtlWaitTaskGroup(
    PLW_TASK_GROUP group
    )
{
    PRING pRing = NULL;
    PLW_TASK pTask = NULL;
    BOOLEAN bStillAlive = TRUE;

    LOCK_GROUP(group);

    while (bStillAlive)
    {
        bStillAlive = FALSE;

        for (pRing = group->Tasks.pNext; !bStillAlive && pRing != &group->Tasks; pRing = pRing->pNext)
        {
            pTask = LW_STRUCT_FROM_FIELD(pRing, SELECT_TASK, GroupRing);
         
            LOCK_THREAD(pTask->pThread);
            if (pTask->TriggerSet != TASK_COMPLETE_MASK)
            {
                bStillAlive = TRUE;
            }
            UNLOCK_THREAD(pTask->pThread);         
        }

        if (bStillAlive)
        {
            pthread_cond_wait(&group->Event, &group->Lock);
        }
    }

    UNLOCK_GROUP(group);
}
Exemplo n.º 6
0
VOID
LwRtlCancelTaskGroup(
    PLW_TASK_GROUP pGroup
    )
{
    PRING ring = NULL;
    PLW_TASK pTask = NULL;

    LOCK_GROUP(pGroup);

    pGroup->bCancelled = TRUE;

    LockAllThreads(pGroup->pPool);

    for (ring = pGroup->Tasks.pNext; ring != &pGroup->Tasks; ring = ring->pNext)
    {
        pTask = LW_STRUCT_FROM_FIELD(ring, EPOLL_TASK, GroupRing);

        if (pTask->EventSignal != TASK_COMPLETE_MASK)
        {
            pTask->EventSignal |= LW_TASK_EVENT_EXPLICIT | LW_TASK_EVENT_CANCEL;
            RingRemove(&pTask->SignalRing);
            RingEnqueue(&pTask->pThread->Tasks, &pTask->SignalRing);
            SignalThread(pTask->pThread);
        }
    }

    UnlockAllThreads(pGroup->pPool);
    UNLOCK_GROUP(pGroup);
}
Exemplo n.º 7
0
static
VOID
ScheduleTimedTasks(
    PRING pTimed,
    LONG64 llNow,
    PRING pRunnable
    )
{
    PLW_TASK pTask = NULL;
    PRING pRing = NULL;
    PRING pNext = NULL;

    for (pRing = pTimed->pNext; pRing != pTimed; pRing = pNext)
    {
        pNext = pRing->pNext;
        pTask = LW_STRUCT_FROM_FIELD(pRing, EPOLL_TASK, QueueRing);

        /* No more tasks in the queue are past the deadline
           since the queue is sorted */
        if (pTask->llDeadline > llNow)
        {
            break;
        }

        RingRemove(&pTask->QueueRing);
        RingEnqueue(pRunnable, &pTask->QueueRing);

        pTask->EventArgs |= LW_TASK_EVENT_TIME;
    }
}
Exemplo n.º 8
0
static
NTSTATUS
PvfsWildcardStackPop(
    IN OUT PLW_LIST_LINKS pStack,
    OUT PSTR *ppszInputString,
    OUT PSTR *ppszPattern
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PLW_LIST_LINKS pStateLink = NULL;
    PPVFS_WILDCARD_STATE_ENTRY pState = NULL;

    pStateLink = LwListRemoveAfter(pStack);

    pState = LW_STRUCT_FROM_FIELD(
                 pStateLink,
                 PVFS_WILDCARD_STATE_ENTRY,
                 StackLinks);

    *ppszInputString = pState->pszInputString;
    *ppszPattern     = pState->pszPattern;

    PvfsFreeMemory(OUT_PPVOID(&pState));

    return ntError;
}
Exemplo n.º 9
0
NTSTATUS
NpfsFindFCB(
    PUNICODE_STRING pUnicodeString,
    PNPFS_FCB * ppFCB
    )
{
    NTSTATUS ntStatus = 0;
    PNPFS_FCB pFCB = NULL;
    PLW_LIST_LINKS pLink = NULL;

    for (pLink = gFCBList.Next; pLink != &gFCBList; pLink = pLink->Next)
    {
        pFCB = LW_STRUCT_FROM_FIELD(pLink, NPFS_FCB, link);

        if (RtlUnicodeStringIsEqual(pUnicodeString, &pFCB->PipeName, FALSE))
        {
            NpfsAddRefFCB(pFCB);
            *ppFCB = pFCB;
            goto cleanup;
        }
    }

    ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    return(ntStatus);

error:

    *ppFCB = NULL;

    goto cleanup;
}
Exemplo n.º 10
0
VOID
LsaPcacheReleaseMachinePasswordInfoW(
    IN PLSA_MACHINE_PASSWORD_INFO_W pPasswordInfo
    )
{
    if (pPasswordInfo)
    {
        PLSA_MACHINEPWD_CACHE_ENTRY pEntry = LW_STRUCT_FROM_FIELD(pPasswordInfo, LSA_MACHINEPWD_CACHE_ENTRY, PasswordInfoW);
        LsaPcachepReleaseEntry(pEntry);
    }
}
Exemplo n.º 11
0
VOID
LsaPcacheReleaseMachineAccountInfoW(
    IN PLSA_MACHINE_ACCOUNT_INFO_W pAccountInfo
    )
{
    if (pAccountInfo)
    {
        PLSA_MACHINEPWD_CACHE_ENTRY pEntry = LW_STRUCT_FROM_FIELD(pAccountInfo, LSA_MACHINEPWD_CACHE_ENTRY, PasswordInfoW.Account);
        LsaPcachepReleaseEntry(pEntry);
    }
}
Exemplo n.º 12
0
static
LW_PCVOID
PagedSearchRecordGetKey(
    PLW_HASHTABLE_NODE      pNode,
    PVOID                   pUnused
    )
{
    PVDIR_PAGED_SEARCH_RECORD pSearchRecord = NULL;

    pSearchRecord = LW_STRUCT_FROM_FIELD(pNode, VDIR_PAGED_SEARCH_RECORD, Node);

    return pSearchRecord->pszGuid;
}
Exemplo n.º 13
0
static
NTSTATUS
WorkLoop(
    PLW_WORK_THREAD pThread
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRING pRing = NULL;
    PLW_WORK_ITEM pItem = NULL;
    PLW_WORK_THREADS pThreads = pThread->pThreads;

    LOCK_THREADS(pThread->pThreads);

    for(;;)
    {
        pThreads->ulAvailable++;

        status = WorkWait(pThread);
        GOTO_ERROR_ON_STATUS(status);

        RingDequeue(&pThreads->WorkItems, &pRing);
        pThreads->ulQueued--;
        pThreads->ulAvailable--;

        UNLOCK_THREADS(pThreads);

        pItem = LW_STRUCT_FROM_FIELD(pRing, LW_WORK_ITEM, Ring);
        pItem->pfnFunc(pItem, pItem->pContext);

        LOCK_THREADS(pThreads);
    }

error:

    pThreads->ulAvailable--;
    pThreads->ulStarted--;
    pThread->bStarted = FALSE;

    /* If the thread pool is not being shut down, nothing is
       going to call pthread_join() on this thread, so call
       pthread_detach() now */
    if (!pThreads->bShutdown)
    {
        pthread_detach(pThread->Thread);
        pThread->Thread = INVALID_THREAD_HANDLE;
    }

    UNLOCK_THREADS(pThreads);

    return status;
}
Exemplo n.º 14
0
static
VOID
ScheduleSignalled(
    PEPOLL_THREAD pThread,
    PRING pRunnable,
    PBOOLEAN pbShutdown
    )
{
    PRING pRing = NULL;
    PRING pNext = NULL;
    PLW_TASK pTask = NULL;
    char c = 0;
    int res = 0;

    LOCK_THREAD(pThread);

    if (pThread->bSignalled)
    {
        pThread->bSignalled = FALSE;

        res = read(pThread->SignalFds[0], &c, sizeof(c));
        assert(res == sizeof(c));

        /* Add all signalled tasks to the runnable list */
        for (pRing = pThread->Tasks.pNext; pRing != &pThread->Tasks; pRing = pNext)
        {
            pNext = pRing->pNext;
            pTask = LW_STRUCT_FROM_FIELD(pRing, EPOLL_TASK, SignalRing);

            RingRemove(&pTask->SignalRing);
            RingRemove(&pTask->QueueRing);

            if (pTask->EventSignal != TASK_COMPLETE_MASK)
            {
                RingEnqueue(pRunnable, &pTask->QueueRing);
                /* Transfer the signal bits into the event args */
                pTask->EventArgs |= pTask->EventSignal;
                pTask->EventSignal = 0;
            }
        }

        if (pThread->bShutdown && !*pbShutdown)
        {
            *pbShutdown = pThread->bShutdown;
        }
    }

    UNLOCK_THREAD(pThread);
}
Exemplo n.º 15
0
DWORD
LsaAdBatchMarshalList(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN PCSTR pszDnsDomainName,
    IN PCSTR pszNetbiosDomainName,
    IN OUT PLSA_LIST_LINKS pBatchItemList,
    IN DWORD dwAvailableCount,
    OUT PLSA_SECURITY_OBJECT* ppObjects,
    OUT PDWORD pdwUsedCount
    )
{
    DWORD dwError = 0;
    PLSA_LIST_LINKS pLinks = NULL;
    DWORD dwIndex = 0;

    for (pLinks = pBatchItemList->Next;
         pLinks != pBatchItemList;
         pLinks = pLinks->Next)
    {
        PLSA_AD_BATCH_ITEM pItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);

        if (dwIndex >= dwAvailableCount)
        {
            LSA_ASSERT(FALSE);
            dwError = LW_ERROR_INTERNAL;
            BAIL_ON_LSA_ERROR(dwError);
        }

        dwError = LsaAdBatchMarshal(
                        pState,
                        pszDnsDomainName,
                        pszNetbiosDomainName,
                        pItem,
                        &ppObjects[dwIndex]);
        BAIL_ON_LSA_ERROR(dwError);
        if (ppObjects[dwIndex])
        {
            dwIndex++;
        }
    }

cleanup:
    *pdwUsedCount = dwIndex;
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 16
0
NTSTATUS
NpfsClientCloseHandle(
    PNPFS_CCB pCCB
    )
{
    NTSTATUS ntStatus = 0;
    PNPFS_PIPE pPipe = NULL;
    PNPFS_CCB pSCB = NULL;
    PLW_LIST_LINKS pLink = NULL;
    PNPFS_IRP_CONTEXT pReadContext = NULL;

    pPipe = pCCB->pPipe;

    ENTER_MUTEX(&pPipe->PipeMutex);

    pSCB = pPipe->pSCB;

    pPipe->PipeClientState = PIPE_CLIENT_CLOSED;

    while (pSCB && !LwListIsEmpty(&pSCB->ReadIrpList))
    {
        pLink = pSCB->ReadIrpList.Next;
        LwListRemove(pLink);

        pReadContext = LW_STRUCT_FROM_FIELD(pLink, NPFS_IRP_CONTEXT, Link);

        NpfsServerCompleteReadFile(pSCB, pReadContext);
    }

    pthread_cond_signal(&pPipe->PipeCondition);

    if (pPipe->PipeServerState == PIPE_SERVER_CLOSED)
    {
        ntStatus = NpfsFreePipeContext(pPipe);
        BAIL_ON_NT_STATUS(ntStatus);
    }

error:

    pPipe->pCCB = NULL;

    LEAVE_MUTEX(&pPipe->PipeMutex);

    NpfsReleaseCCB(pCCB);

    return(ntStatus);
}
Exemplo n.º 17
0
VOID
LwRtlWakeTaskGroup(
    PLW_TASK_GROUP group
    )
{
    PRING ring = NULL;
    PLW_TASK pTask = NULL;

    LOCK_GROUP(group);

    for (ring = group->Tasks.pNext; ring != &group->Tasks; ring = ring->pNext)
    {
        pTask = LW_STRUCT_FROM_FIELD(ring, SELECT_TASK, GroupRing);

        LwRtlWakeTask(pTask);
    }

    UNLOCK_GROUP(group);
}
Exemplo n.º 18
0
static
VOID
PvfsNotifyFullReportBuffer(
    PPVFS_FCB pFcb,
    PPVFS_FCB pReportParentFcb,
    PPVFS_NOTIFY_REPORT_RECORD pReport
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    for (pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, NULL);
         pFilterLink;
         pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, pFilterLink))
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        /* Match the filter and depth */

        if ((pFilter->NotifyFilter & pReport->Filter) &&
            ((pFcb == pReportParentFcb) || pFilter->bWatchTree))
        {
            ntError = PvfsNotifyReportBuffer(
                          &pFilter->Buffer,
                          pReport->Action,
                          pReport->pszFilename);
            break;
        }
    }

    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    return;
}
Exemplo n.º 19
0
VOID
IopIrpFreeZctIrpList(
    IN OUT PIO_FILE_OBJECT pFileObject
    )
{
    PLW_LIST_LINKS pLinks = NULL;;
    PIRP_INTERNAL irpInternal = NULL;
    PIRP pIrp = NULL;

    while (!LwListIsEmpty(&pFileObject->ZctCompletionIrpList))
    {
        pLinks = LwListRemoveHead(&pFileObject->ZctCompletionIrpList);
        irpInternal = LW_STRUCT_FROM_FIELD(pLinks, IRP_INTERNAL, CancelLinks);
        pIrp = &irpInternal->Irp;

        LWIO_ASSERT(1 == irpInternal->ReferenceCount);
        LWIO_ASSERT(!pIrp->FileHandle);

        IopIrpDereference(&pIrp);
    }
}
Exemplo n.º 20
0
static
NTSTATUS
LwIoFindPathCreds(
    IN PUNICODE_STRING Path,
    IN BOOLEAN bPrecise,
    OUT PIO_PATH_CREDS* ppCreds
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING normalPath = { 0 };
    PIO_PATH_CREDS pFoundCreds = NULL;
    PLW_LIST_LINKS pLink = NULL;

    status = LwIoNormalizePath(Path, &normalPath);
    GOTO_CLEANUP_ON_STATUS(status);

    while ((pLink = LwListTraverse(&gPathCreds, pLink)))
    {
        PIO_PATH_CREDS pCreds = LW_STRUCT_FROM_FIELD(pLink, IO_PATH_CREDS, link);

        if ((bPrecise && LwRtlUnicodeStringIsEqual(&normalPath, &pCreds->PathPrefix, TRUE)) ||
            (!bPrecise && LwRtlUnicodeStringIsPrefix(&pCreds->PathPrefix, &normalPath, TRUE)))
        {
            pFoundCreds = pCreds;
            break;
        }
    }

cleanup:
    if (status)
    {
        pFoundCreds = NULL;
    }

    LwRtlUnicodeStringFree(&normalPath);

    *ppCreds = pFoundCreds;

    return status;
}
Exemplo n.º 21
0
static
VOID
InsertTimedQueue(
    PRING pTimed,
    PLW_TASK pInsert
    )
{
    PLW_TASK pTask = NULL;
    PRING pRing = NULL;

    /* Find the first task in the queue with a later deadline than the task to insert */
    for (pRing = pTimed->pNext; pRing != pTimed; pRing = pRing->pNext)
    {
        pTask = LW_STRUCT_FROM_FIELD(pRing, EPOLL_TASK, QueueRing);

        if (pTask->llDeadline > pInsert->llDeadline)
            break;
    }

    /* Insert the task */
    RingInsertBefore(pRing, &pInsert->QueueRing);
}
Exemplo n.º 22
0
VOID
VmDirPagedSearchCacheFree(
    VOID
    )
{
    PLW_HASHTABLE_NODE pNode = NULL;
    LW_HASHTABLE_ITER iter = LW_HASHTABLE_ITER_INIT;
    PVDIR_PAGED_SEARCH_RECORD pSearchRecord = NULL;

    if (gPagedSearchCache.pHashTbl != NULL)
    {
        while ((pNode = LwRtlHashTableIterate(gPagedSearchCache.pHashTbl, &iter)))
        {
            pSearchRecord = LW_STRUCT_FROM_FIELD(pNode, VDIR_PAGED_SEARCH_RECORD, Node);
            LwRtlHashTableRemove(gPagedSearchCache.pHashTbl, pNode);
            VmDirPagedSearchCacheRecordFree(pSearchRecord);
        }

        LwRtlFreeHashTable(&gPagedSearchCache.pHashTbl);
    }

    VMDIR_SAFE_FREE_MUTEX(gPagedSearchCache.mutex);
}
Exemplo n.º 23
0
VOID
LwRtlWaitTaskGroup(
    PLW_TASK_GROUP pGroup
    )
{
    PRING pRing = NULL;
    PLW_TASK pTask = NULL;
    BOOLEAN bStillAlive = TRUE;

    LOCK_GROUP(pGroup);

    while (bStillAlive)
    {
        bStillAlive = FALSE;

        LockAllThreads(pGroup->pPool);

        for (pRing = pGroup->Tasks.pNext; !bStillAlive && pRing != &pGroup->Tasks; pRing = pRing->pNext)
        {
            pTask = LW_STRUCT_FROM_FIELD(pRing, EPOLL_TASK, GroupRing);

            if (pTask->EventSignal != TASK_COMPLETE_MASK)
            {
                bStillAlive = TRUE;
            }
        }

        UnlockAllThreads(pGroup->pPool);

        if (bStillAlive)
        {
            pthread_cond_wait(&pGroup->Event, &pGroup->Lock);
        }
    }

    UNLOCK_GROUP(pGroup);
}
Exemplo n.º 24
0
VOID
RdrContinueContextList(
    PLW_LIST_LINKS pList,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_OP_CONTEXT pContext = NULL;
    PLW_LIST_LINKS pLink = NULL;
    PLW_LIST_LINKS pNext = NULL;

    for (pLink = pList->Next; pLink != pList; pLink = pNext)
    {
        pNext = pLink->Next;
        pContext = LW_STRUCT_FROM_FIELD(pLink, RDR_OP_CONTEXT, Link);

        LwListRemove(pLink);

        if (RdrContinueContext(pContext, status, pParam))
        {
            LwListInsertBefore(pNext, pLink);
        }
    }
}
Exemplo n.º 25
0
static
VOID
PvfsNotifyCleanIrpList(
    PVOID pContext
    )
{
    PPVFS_IRP_CONTEXT pIrpCtx = (PPVFS_IRP_CONTEXT)pContext;
    PPVFS_FCB pFcb = NULL;
    BOOLEAN bFcbLocked = FALSE;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    BOOLEAN bFound = FALSE;

    LWIO_ASSERT(pIrpCtx->pScb->pOwnerFcb);

    // We have the IrpCtx->Scb's reference so no need to take another
    pFcb = pIrpCtx->pScb->pOwnerFcb;

    LWIO_LOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

    pFilterLink = PvfsListTraverse(pFcb->pNotifyListIrp, NULL);

    while (pFilterLink)
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        pNextLink = PvfsListTraverse(pFcb->pNotifyListIrp, pFilterLink);

        if (pFilter->pIrpContext != pIrpCtx)
        {
            pFilterLink = pNextLink;
            continue;
        }

        bFound = TRUE;

        PvfsListRemoveItem(pFcb->pNotifyListIrp, pFilterLink);
        pFilterLink = NULL;

        LWIO_UNLOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

        pFilter->pIrpContext->pIrp->IoStatusBlock.Status = STATUS_CANCELLED;

        PvfsCompleteIrpContext(pFilter->pIrpContext);

        PvfsFreeNotifyRecord(&pFilter);

        /* Can only be one IrpContext match so we are done */
    }

    LWIO_UNLOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

    if (!bFound)
    {
        pIrpCtx->pIrp->IoStatusBlock.Status = STATUS_CANCELLED;

        PvfsCompleteIrpContext(pIrpCtx);
    }

    if (pIrpCtx)
    {
        PvfsReleaseIrpContext(&pIrpCtx);
    }

    return;
}
Exemplo n.º 26
0
static
VOID
PvfsNotifyFullReportIrp(
    PPVFS_FCB pFcb,
    PPVFS_FCB pReportParentFcb,
    PPVFS_NOTIFY_REPORT_RECORD pReport
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bActive = FALSE;
    BOOLEAN bLocked =  FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    pFilterLink = PvfsListTraverse(pFcb->pNotifyListIrp, NULL);

    while(pFilterLink)
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        pNextLink = PvfsListTraverse(pFcb->pNotifyListIrp, pFilterLink);

        /* Continue if we don't match the filter and depth */

        if (!((pFilter->NotifyFilter & pReport->Filter) &&
              ((pFcb == pReportParentFcb) || pFilter->bWatchTree)))
        {
            pFilter = NULL;
            pFilterLink = pNextLink;

            continue;
        }

        PvfsListRemoveItem(pFcb->pNotifyListIrp, pFilterLink);

        LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

        pFilterLink = NULL;

        PvfsQueueCancelIrpIfRequested(pFilter->pIrpContext);

        bActive = PvfsIrpContextMarkIfNotSetFlag(
                      pFilter->pIrpContext,
                      PVFS_IRP_CTX_FLAG_CANCELLED,
                      PVFS_IRP_CTX_FLAG_ACTIVE);

        if (!bActive)
        {
            PvfsFreeNotifyRecord(&pFilter);
            pFilterLink = pNextLink;

            continue;
        }

        ntError = PvfsNotifyReportIrp(
                      pFilter->pIrpContext,
                      pReport->Action,
                      pReport->pszFilename);
        BAIL_ON_NT_STATUS(ntError);

        /* If we have been asked to buffer changes, move the Fitler Record
           to the buffer list */

        if (pFilter->Buffer.Length > 0)
        {
            LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);
            ntError = PvfsListAddTail(pFcb->pNotifyListBuffer, pFilterLink);
            LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

            BAIL_ON_NT_STATUS(ntError);

            pFilter = NULL;
        }

        /* We only process on matching IRP */
        break;
    }

cleanup:
    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    if (pFilter)
    {
        PvfsFreeNotifyRecord(&pFilter);
    }

    return;

error:
    goto cleanup;
}
Exemplo n.º 27
0
static
NTSTATUS
ProcessRunnable(
    PEPOLL_THREAD pThread,
    PRING pRunnable,
    PRING pTimed,
    PRING pWaiting,
    LONG64 llNow
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG ulTicks = MAX_TICKS;
    PLW_TASK pTask = NULL;
    PLW_TASK_GROUP pGroup = NULL;
    PRING pRing = NULL;
    PRING pNext = NULL;

    /* We are guaranteed to run each task at least once.  If tasks remain
       on the runnable list by yielding, we will continue to run them
       all in a round robin until our ticks are depleted. */
    while (ulTicks && !RingIsEmpty(pRunnable))
    {
        for (pRing = pRunnable->pNext; pRing != pRunnable; pRing = pNext)
        {
            pNext = pRing->pNext;

            pTask = LW_STRUCT_FROM_FIELD(pRing, EPOLL_TASK, QueueRing);

            RunTask(pTask, llNow);

            if (ulTicks)
            {
                ulTicks--;
            }

            if (pTask->EventWait != LW_TASK_EVENT_COMPLETE)
            {
                /* Task is still waiting to be runnable, update events in epoll set */
                status = UpdateEventWait(
                    pTask,
                    pThread->EpollFd
                    );
                GOTO_ERROR_ON_STATUS(status);

                if (pTask->EventWait & LW_TASK_EVENT_YIELD)
                {
                    /* Task is yielding.  Set YIELD in its trigger arguments and
                       and leave it on the runnable list for the next iteration */
                    pTask->EventArgs |= LW_TASK_EVENT_YIELD;
                }
                else if (pTask->EventWait & LW_TASK_EVENT_TIME)
                {
                    /* If the task is waiting for a timeout, insert it into the timed queue */
                    RingRemove(&pTask->QueueRing);
                    InsertTimedQueue(pTimed, pTask);
                }
                else
                {
                    /* Otherwise, put it in the generic waiting queue */
                    RingRemove(&pTask->QueueRing);
                    RingEnqueue(pWaiting, &pTask->QueueRing);
                }
            }
            else
            {
                /* Task is complete */
                RingRemove(&pTask->QueueRing);

                /* Turn off any fd in the epoll set */
                if (pTask->Fd >= 0)
                {
                    status = LwRtlSetTaskFd(pTask, pTask->Fd, 0);
                    GOTO_ERROR_ON_STATUS(status);
                }

                /* Unsubscribe task from any UNIX signals */
                if (pTask->pUnixSignal)
                {
                    RegisterTaskUnixSignal(pTask, 0, FALSE);
                }

                LOCK_POOL(pThread->pPool);
                pThread->ulLoad--;
                UNLOCK_POOL(pThread->pPool);

                pGroup = pTask->pGroup;

                /* If task was in a task group, remove it and notify anyone waiting
                   on the group */
                if (pGroup)
                {
                    LOCK_GROUP(pGroup);
                    pTask->pGroup = NULL;
                    RingRemove(&pTask->GroupRing);
                    pthread_cond_broadcast(&pGroup->Event);
                    UNLOCK_GROUP(pGroup);
                }

                LOCK_THREAD(pThread);
                if (--pTask->ulRefCount)
                {
                    /* The task still has a reference, so mark it as completed
                       and notify anyone waiting on it */
                    pTask->EventSignal = TASK_COMPLETE_MASK;
                    pthread_cond_broadcast(&pThread->Event);
                    UNLOCK_THREAD(pThread);
                }
                else
                {
                    /* We held the last reference to the task, so delete it */
                    RingRemove(&pTask->SignalRing);
                    UNLOCK_THREAD(pThread);
                    TaskDelete(pTask);
                }
            }
        }
    }

error:

    return status;
}
Exemplo n.º 28
0
static
NTSTATUS
PvfsNotifyReportBufferedChanges(
    PPVFS_CCB pCcb,
    PPVFS_FCB pFcb,
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    FILE_NOTIFY_CHANGE Filter = pIrpContext->pIrp->Args.ReadDirectoryChange.NotifyFilter;
    PVOID pBuffer = pIrpContext->pIrp->Args.ReadDirectoryChange.Buffer;
    ULONG Length = pIrpContext->pIrp->Args.ReadDirectoryChange.Length;
    PLW_LIST_LINKS pFilterLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    /* See if we have any changes to report immediately */

    for (pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, NULL);
         pFilterLink;
         pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, pFilterLink))
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        /* To return the buffered changes, we have to match the handle
           and the filter */

        if ((pFilter->NotifyFilter != Filter) || (pFilter->pCcb != pCcb))
        {
            continue;
        }

        /* We have a match to check to see if we have anything */

        if ((pFilter->Buffer.Length == 0) ||
            (pFilter->Buffer.Offset == 0))
        {
            ntError = STATUS_NOT_FOUND;
            BAIL_ON_NT_STATUS(ntError);
        }

        /* We have changes....Do we have enough space?  Have we already
           overflowed the buffer? */

        ntError = pFilter->Buffer.Status;
        BAIL_ON_NT_STATUS(ntError);

        if (pFilter->Buffer.Offset > Length)
        {
            PvfsNotifyClearBufferedChanges(&pFilter->Buffer);

            ntError = STATUS_NOTIFY_ENUM_DIR;
            BAIL_ON_NT_STATUS(ntError);
        }

        memcpy(pBuffer, pFilter->Buffer.pData, pFilter->Buffer.Offset);
        pIrpContext->pIrp->IoStatusBlock.BytesTransferred = pFilter->Buffer.Offset;

        PvfsNotifyClearBufferedChanges(&pFilter->Buffer);
    }

    if (pFilterLink == NULL)
    {
        ntError = STATUS_NOT_FOUND;
        BAIL_ON_NT_STATUS(ntError);
    }


cleanup:
    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    return ntError;

error:
    goto cleanup;
}
Exemplo n.º 29
0
static
NTSTATUS
EventLoop(
    PEPOLL_THREAD pThread
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    RING timed;
    RING runnable;
    RING waiting;
    CLOCK clock = {0};
    LONG64 llNow = 0;
    LONG64 llNextDeadline = 0;
    struct epoll_event events[MAX_EVENTS];
    int ready = 0;
    BOOLEAN bShutdown = FALSE;
    BOOLEAN bSignalled = FALSE;

    RingInit(&runnable);
    RingInit(&timed);
    RingInit(&waiting);

    for (;;)
    {
        /* Get current time for this iteration */
        status = ClockGetMonotonicTime(&clock, &llNow);
        GOTO_ERROR_ON_STATUS(status);

        /* Schedule any timed tasks that have reached their deadline */
        ScheduleTimedTasks(
            &timed,
            llNow,
            &runnable);

        /* Schedule any waiting tasks that epoll indicated are ready
           and check if the thread received a signal */
        ScheduleWaitingTasks(
            events,
            ready,
            llNow,
            &runnable,
            &bSignalled);

        if (bSignalled)
        {
            /* Schedule explicitly-signalled tasks and check if we
               have been told to shut down */
            ScheduleSignalled(
                pThread,
                &runnable,
                &bShutdown);
        }

        /* Process runnable tasks */
        status = ProcessRunnable(
            pThread,
            &runnable,
            &timed,
            &waiting,
            llNow);
        GOTO_ERROR_ON_STATUS(status);

        if (!RingIsEmpty(&runnable))
        {
            /* If there are still runnable tasks, set the next deadline
               to now so we can check for other tasks becoming runnable but
               do not block in Poll() */
            llNextDeadline = llNow;
        }
        else if (!RingIsEmpty(&timed))
        {
            /* There are timed tasks, so set our next deadline to the
               deadline of the first task in the queue */
            llNextDeadline = LW_STRUCT_FROM_FIELD(timed.pNext, EPOLL_TASK, QueueRing)->llDeadline;
        }
        else if (!RingIsEmpty(&waiting) || !bShutdown)
        {
            /* There are waiting tasks or we are not shutting down, so poll indefinitely */
            llNextDeadline = -1;
        }
        else
        {
            /* We are shutting down and there are no remaining tasks, so leave */
            break;
        }

        /* Wait (or check) for activity */
        status = Poll(
            &clock,
            &llNow,
            pThread->EpollFd,
            events,
            MAX_EVENTS,
            llNextDeadline,
            &ready);
        GOTO_ERROR_ON_STATUS(status);
    }

error:

    return status;
}
Exemplo n.º 30
0
static
NTSTATUS
EventLoop(
    PSELECT_THREAD pThread
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    RING tasks;
    RING runnable;
    PRING pRing = NULL;
    PRING pNext = NULL;
    PSELECT_TASK pTask = NULL;
    CLOCK clock = {0};
    LONG64 llNow;
    LONG64 llNextDeadline;
    fd_set readSet;
    fd_set writeSet;
    fd_set exceptSet;
    int ready = 0;
    int nfds = 0;
    char c = 0;
    int res = 0;
    BOOLEAN bShutdown = FALSE;
    PLW_TASK_GROUP pGroup = NULL;
    BOOLEAN bYielding = FALSE;

    RingInit(&tasks);
    RingInit(&runnable);

    FD_ZERO(&readSet);
    FD_ZERO(&writeSet);
    FD_ZERO(&exceptSet);

    LOCK_THREAD(pThread);

    while (!bShutdown || !RingIsEmpty(&tasks))
    {
        /* Reset variables */
        llNextDeadline = 0;
        nfds = 0;
        bYielding = FALSE;

        /* Get current time for this iteration */
        GOTO_ERROR_ON_STATUS(status = ClockGetMonotonicTime(&clock, &llNow));
        
        /* Figure out which tasks are runnable */
        for (pRing = tasks.pNext; pRing != &tasks; pRing = pNext)
        {
            pNext = pRing->pNext;

            pTask = LW_STRUCT_FROM_FIELD(pRing, SELECT_TASK, EventRing);

            /* Update trigger set with results from select() */
            UpdateTriggerSet(
                pTask,
                &readSet,
                &writeSet,
                &exceptSet,
                llNow);
            
            /* Schedule tasks to run if they have been triggered or were yielding */
            if ((pTask->TriggerWait & LW_TASK_EVENT_YIELD) ||
                ((pTask->TriggerWait | LW_TASK_EVENT_EXPLICIT) & pTask->TriggerSet))
            {
                /* Put task on a separate list to run its trigger function */
                RingRemove(&pTask->EventRing);
                RingInsertBefore(&runnable, &pTask->EventRing);
                /* Update the trigger args with the trigger set */
                pTask->TriggerArgs |= pTask->TriggerSet;
                /* Turn off bits (except cancel) now that we have copied them */
                pTask->TriggerSet &= (LW_TASK_EVENT_CANCEL);

            }
            else
            {
                /* Update select parameters to wait for task to trigger */
                UpdateTriggerWait(
                    pTask,
                    &nfds,
                    &readSet,
                    &writeSet,
                    &exceptSet,
                    &llNextDeadline);
            }
        }

        UNLOCK_THREAD(pThread);

        for (pRing = runnable.pNext; pRing != &runnable; pRing = pNext)
        {
            pNext = pRing->pNext;
            
            pTask = LW_STRUCT_FROM_FIELD(pRing, SELECT_TASK, EventRing);
            
            GOTO_ERROR_ON_STATUS(status = TaskProcessTrigger(pTask, llNow));
            
            if (pTask->TriggerWait != 0)
            {
                /* Task is still waiting to be runnable, update select parameters
                   and put it back in the task list */
                UpdateTriggerWait(
                    pTask,
                    &nfds,
                    &readSet,
                    &writeSet,
                    &exceptSet,
                    &llNextDeadline);
            
                if (pTask->TriggerWait & LW_TASK_EVENT_YIELD)
                {
                    /* Task is yielding temporarily.  Set the yield flag on
                       its trigger arguments.   Leave it on the runnable list */
                    pTask->TriggerArgs |= LW_TASK_EVENT_YIELD;
                }
                else
                {    
                    RingRemove(&pTask->EventRing);
                    RingInsertBefore(&tasks, &pTask->EventRing);
                }
            }
            else
            {
                /* Task is complete, notify and remove from task group
                   if it is in one */
                
                RingRemove(&pTask->EventRing);
                
                /* Unregister task from global signal loop */
                if (pTask->pUnixSignal)
                {
                    RegisterTaskUnixSignal(pTask, 0, FALSE);
                }

                pGroup = pTask->pGroup;
                
                if (pGroup)
                {
                    LOCK_GROUP(pGroup);
                    pTask->pGroup = NULL;
                    RingRemove(&pTask->GroupRing);
                    pthread_cond_broadcast(&pGroup->Event);
                    UNLOCK_GROUP(pGroup);
                }
                
                LOCK_THREAD(pThread);
                if (--pTask->ulRefCount)
                {
                    pTask->TriggerSet = TASK_COMPLETE_MASK;
                    pthread_cond_broadcast(&pThread->Event);
                    UNLOCK_THREAD(pThread);
                }
                else
                {
                    UNLOCK_THREAD(pThread);
                    TaskDelete(pTask);
                }
            }
        }

        if (!RingIsEmpty(&runnable))
        {
            /* We have runnable tasks that are yielding.  Move them
               back to the event list and note the fact. */
            bYielding = TRUE;
            RingMove(&runnable, &tasks);
        }

        if (!bShutdown)
        {
            /* Also wait for a poke on the thread's signal fd */
            FD_SET(pThread->SignalFds[0], &readSet);
            if (pThread->SignalFds[0] >= nfds)
            {
                nfds = pThread->SignalFds[0] + 1;
            }
        }

        if (nfds)
        {
            /* If there are still runnable tasks due to
               LW_TASK_EVENT_YIELD, set the next deadline
               to now so we wake immediately.  This gives other
               tasks the chance to become runnable before we
               proceed */
            if (bYielding)
            {
                llNextDeadline = llNow;
            }

            /* Wait for a task to be runnable */
            GOTO_ERROR_ON_STATUS(status = Sleep(
                              &clock,
                              &llNow,
                              nfds,
                              &readSet,
                              &writeSet,
                              &exceptSet,
                              llNextDeadline,
                              &ready));
        }
        
        LOCK_THREAD(pThread);

        /* Check for a signal to the thread */
        if (FD_ISSET(pThread->SignalFds[0], &readSet))
        {
            FD_CLR(pThread->SignalFds[0], &readSet);
            pThread->bSignalled = FALSE;
            
            res = read(pThread->SignalFds[0], &c, sizeof(c));
            assert(res == sizeof(c));
            
            /* Move all tasks in queue into local task list */
            RingMove(&pThread->Tasks, &tasks);

            if (pThread->bShutdown && !bShutdown)
            {
                bShutdown = pThread->bShutdown;
                
                /* Cancel all outstanding tasks */
                for (pRing = tasks.pNext; pRing != &tasks; pRing = pRing->pNext)
                {
                    pTask = LW_STRUCT_FROM_FIELD(pRing, SELECT_TASK, EventRing);
                    pTask->TriggerSet |= LW_TASK_EVENT_CANCEL | LW_TASK_EVENT_EXPLICIT;
                }
            }
        }
    }

error:

    UNLOCK_THREAD(pThread);

    return status;
}