コード例 #1
0
static DECLCALLBACK(void) pdmacR3TimerCallback(PVM pVM, PTMTIMER pTimer, void *pvUser)
{
    uint64_t tsCur = RTTimeProgramMilliTS();
    uint64_t cMilliesNext = UINT64_MAX;
    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pvUser;

    ASMAtomicWriteU64(&pEpClassFile->cMilliesNext, UINT64_MAX);

    /* Go through all endpoints and check for expired requests. */
    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEpClassFile->Core.pEndpointsHead;

    while (pEpFile)
    {
        /* Check for an expired delay. */
        if (pEpFile->pDelayedHead != NULL)
        {
            PPDMASYNCCOMPLETIONTASKFILE pTaskFile = ASMAtomicXchgPtrT(&pEpFile->pDelayedHead, NULL, PPDMASYNCCOMPLETIONTASKFILE);

            while (pTaskFile)
            {
                PPDMASYNCCOMPLETIONTASKFILE pTmp = pTaskFile;
                pTaskFile = pTaskFile->pDelayedNext;

                if (tsCur >= pTmp->tsDelayEnd)
                {
                    LogRel(("AIOMgr: Delayed request %#p completed\n", pTmp));
                    pdmR3AsyncCompletionCompleteTask(&pTmp->Core, pTmp->rc, true);
                }
                else
                {
                    /* Prepend to the delayed list again. */
                    PPDMASYNCCOMPLETIONTASKFILE pHead = NULL;

                    if (pTmp->tsDelayEnd - tsCur < cMilliesNext)
                        cMilliesNext = pTmp->tsDelayEnd - tsCur;

                    do
                    {
                        pHead = ASMAtomicReadPtrT(&pEpFile->pDelayedHead, PPDMASYNCCOMPLETIONTASKFILE);
                        pTmp->pDelayedNext = pHead;
                    } while (!ASMAtomicCmpXchgPtr(&pEpFile->pDelayedHead, pTmp, pHead));
                }
            }
        }

        pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEpFile->Core.pNext;
    }

    if (cMilliesNext < pEpClassFile->cMilliesNext)
    {
        ASMAtomicWriteU64(&pEpClassFile->cMilliesNext, cMilliesNext);
        TMTimerSetMillies(pEpClassFile->pTimer, cMilliesNext);
    }
}
コード例 #2
0
RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval)
{
    /*
     * Validate.
     */
    RTTIMER_ASSERT_VALID_RET(pTimer);
    AssertReturn(u64NanoInterval > 0, VERR_INVALID_PARAMETER);
    AssertReturn(u64NanoInterval < UINT64_MAX / 8, VERR_INVALID_PARAMETER);
    AssertReturn(pTimer->cNsInterval, VERR_INVALID_STATE);

    if (pTimer->fSuspended || pTimer->fSuspendedFromTimer)
        pTimer->cNsInterval = u64NanoInterval;
    else
    {
        ASMAtomicWriteU64(&pTimer->cNsInterval, u64NanoInterval);
        ASMAtomicWriteBool(&pTimer->fIntervalChanged, true);

        if (   !pTimer->fAllCpus
            && !pTimer->u.Single.nsNextTick
            && pTimer->hCyclicId != CYCLIC_NONE
            && rtTimerSolIsCallingFromTimerProc(pTimer))
            pTimer->u.Single.nsNextTick = RTTimeSystemNanoTS();
    }

    return VINF_SUCCESS;
}
コード例 #3
0
static int pdmacFileEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize)
{
    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;

    ASMAtomicWriteU64(&pEpFile->cbFile, cbSize);
    return RTFileSetSize(pEpFile->hFile, cbSize);
}
コード例 #4
0
static int pdmacFileEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize)
{
    int rc;
    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;

    rc = RTFileSetSize(pEpFile->hFile, cbSize);
    if (RT_SUCCESS(rc))
        ASMAtomicWriteU64(&pEpFile->cbFile, cbSize);

    return rc;
}
コード例 #5
0
void pdmacFileEpTaskCompleted(PPDMACTASKFILE pTask, void *pvUser, int rc)
{
    PPDMASYNCCOMPLETIONTASKFILE pTaskFile = (PPDMASYNCCOMPLETIONTASKFILE)pvUser;

    LogFlowFunc(("pTask=%#p pvUser=%#p rc=%Rrc\n", pTask, pvUser, rc));

    if (pTask->enmTransferType == PDMACTASKFILETRANSFER_FLUSH)
        pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core, rc, true);
    else
    {
        Assert((uint32_t)pTask->DataSeg.cbSeg == pTask->DataSeg.cbSeg && (int32_t)pTask->DataSeg.cbSeg >= 0);
        uint32_t uOld = ASMAtomicSubS32(&pTaskFile->cbTransferLeft, (int32_t)pTask->DataSeg.cbSeg);

        /* The first error will be returned. */
        if (RT_FAILURE(rc))
            ASMAtomicCmpXchgS32(&pTaskFile->rc, rc, VINF_SUCCESS);
#ifdef VBOX_WITH_DEBUGGER
        else
        {
            PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pTaskFile->Core.pEndpoint;

            /* Overwrite with injected error code. */
            if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ)
                rc = ASMAtomicXchgS32(&pEpFile->rcReqRead, VINF_SUCCESS);
            else
                rc = ASMAtomicXchgS32(&pEpFile->rcReqWrite, VINF_SUCCESS);

            if (RT_FAILURE(rc))
                ASMAtomicCmpXchgS32(&pTaskFile->rc, rc, VINF_SUCCESS);
        }
#endif

        if (!(uOld - pTask->DataSeg.cbSeg)
            && !ASMAtomicXchgBool(&pTaskFile->fCompleted, true))
        {
#ifdef PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
            PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pTaskFile->Core.pEndpoint;
            PPDMASYNCCOMPLETIONEPCLASSFILE  pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEpFile->Core.pEpClass;

            /* Check if we should delay completion of the request. */
            if (   ASMAtomicReadU32(&pEpFile->msDelay) > 0
                && ASMAtomicReadU32(&pEpFile->cReqsDelay) > 0)
            {
                uint64_t tsDelay = pEpFile->msDelay;

                if (pEpFile->msJitter)
                    tsDelay = (RTRandU32() % 100) > 50 ? pEpFile->msDelay + (RTRandU32() % pEpFile->msJitter)
                                                       : pEpFile->msDelay - (RTRandU32() % pEpFile->msJitter);
                ASMAtomicDecU32(&pEpFile->cReqsDelay);

                /* Arm the delay. */
                pTaskFile->tsDelayEnd = RTTimeProgramMilliTS() + tsDelay;

                /* Append to the list. */
                PPDMASYNCCOMPLETIONTASKFILE pHead = NULL;
                do
                {
                    pHead = ASMAtomicReadPtrT(&pEpFile->pDelayedHead, PPDMASYNCCOMPLETIONTASKFILE);
                    pTaskFile->pDelayedNext = pHead;
                } while (!ASMAtomicCmpXchgPtr(&pEpFile->pDelayedHead, pTaskFile, pHead));

                if (tsDelay < pEpClassFile->cMilliesNext)
                {
                    ASMAtomicWriteU64(&pEpClassFile->cMilliesNext, tsDelay);
                    TMTimerSetMillies(pEpClassFile->pTimer, tsDelay);
                }

                LogRel(("AIOMgr: Delaying request %#p for %u ms\n", pTaskFile, tsDelay));
            }
            else
#endif
                pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core, pTaskFile->rc, true);
        }
    }
}
コード例 #6
0
/**
 * Processes a given task list for assigned to the given endpoint.
 */
static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMACEPFILEMGR pAioMgr,
                                                          PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
                                                          PPDMACTASKFILE pTasks)
{
    int rc = VINF_SUCCESS;

    while (pTasks)
    {
        RTMSINTERVAL msWhenNext;
        PPDMACTASKFILE pCurr = pTasks;

        if (!pdmacEpIsTransferAllowed(&pEndpoint->Core, (uint32_t)pCurr->DataSeg.cbSeg, &msWhenNext))
        {
            pAioMgr->msBwLimitExpired = RT_MIN(pAioMgr->msBwLimitExpired, msWhenNext);
            break;
        }

        pTasks = pTasks->pNext;

        switch (pCurr->enmTransferType)
        {
            case PDMACTASKFILETRANSFER_FLUSH:
            {
                rc = RTFileFlush(pEndpoint->hFile);
                break;
            }
            case PDMACTASKFILETRANSFER_READ:
            case PDMACTASKFILETRANSFER_WRITE:
            {
                if (pCurr->enmTransferType == PDMACTASKFILETRANSFER_READ)
                {
                    rc = RTFileReadAt(pEndpoint->hFile, pCurr->Off,
                                      pCurr->DataSeg.pvSeg,
                                      pCurr->DataSeg.cbSeg,
                                      NULL);
                }
                else
                {
                    if (RT_UNLIKELY((uint64_t)pCurr->Off + pCurr->DataSeg.cbSeg > pEndpoint->cbFile))
                    {
                        ASMAtomicWriteU64(&pEndpoint->cbFile, pCurr->Off + pCurr->DataSeg.cbSeg);
                        RTFileSetSize(pEndpoint->hFile, pCurr->Off + pCurr->DataSeg.cbSeg);
                    }

                    rc = RTFileWriteAt(pEndpoint->hFile, pCurr->Off,
                                       pCurr->DataSeg.pvSeg,
                                       pCurr->DataSeg.cbSeg,
                                       NULL);
                }

                break;
            }
            default:
                AssertMsgFailed(("Invalid transfer type %d\n", pTasks->enmTransferType));
        }

        pCurr->pfnCompleted(pCurr, pCurr->pvUser, rc);
        pdmacFileTaskFree(pEndpoint, pCurr);
    }

    if (pTasks)
    {
        /* Add the rest of the tasks to the pending list */
        pdmacFileAioMgrEpAddTaskList(pEndpoint, pTasks);
    }

    return VINF_SUCCESS;
}