static DECLCALLBACK(int) test1Thread1(RTTHREAD ThreadSelf, void *pvUser)
{
    RTSEMEVENTMULTI hSem = *(PRTSEMEVENTMULTI)pvUser;

    uint64_t u64 = RTTimeSystemMilliTS();
    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(hSem, 1000), VERR_TIMEOUT);
    u64 = RTTimeSystemMilliTS() - u64;
    RTTEST_CHECK_MSG(g_hTest, u64 < 1500 && u64 > 950, (g_hTest, "u64=%llu\n", u64));

    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(hSem, 2000), VINF_SUCCESS);
    return VINF_SUCCESS;
}
示例#2
0
/**
 * Thread checking for expired requests.
 *
 * @returns IPRT status code.
 * @param   pThread    Thread handle.
 * @param   pvUser     Opaque user data.
 */
static int drvdiskIntIoReqExpiredCheck(RTTHREAD pThread, void *pvUser)
{
    PDRVDISKINTEGRITY pThis = (PDRVDISKINTEGRITY)pvUser;

    while (pThis->fRunning)
    {
        int rc = RTSemEventWait(pThis->SemEvent, pThis->uCheckIntervalMs);

        if (!pThis->fRunning)
            break;

        Assert(rc == VERR_TIMEOUT);

        /* Get current timestamp for comparison. */
        uint64_t tsCurr = RTTimeSystemMilliTS();

        /* Go through the array and check for expired requests. */
        for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
        {
            PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[i];
            PDRVDISKAIOREQ pIoReq = ASMAtomicReadPtrT(&pReqActive->pIoReq, PDRVDISKAIOREQ);

            if (   pIoReq
                && (tsCurr > pReqActive->tsStart)
                && (tsCurr - pReqActive->tsStart) >= pThis->uExpireIntervalMs)
            {
                RTMsgError("Request %#p expired (active for %llu ms already)\n",
                           pIoReq, tsCurr - pReqActive->tsStart);
                RTAssertDebugBreak();
            }
        }
    }

    return VINF_SUCCESS;
}
示例#3
0
/**
 * Free a async I/O request.
 *
 * @returns nothing.
 * @param   pThis     Disk driver.
 * @param   pIoReq    The I/O request to free.
 */
static void drvdiskintIoReqFree(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
{
    if (pThis->fCheckDoubleCompletion)
    {
        /* Search if the I/O request completed already. */
        for (unsigned i = 0; i < pThis->cEntries; i++)
        {
            if (RT_UNLIKELY(pThis->papIoReq[i] == pIoReq))
            {
                RTMsgError("Request %#p completed already!\n", pIoReq);
                RTMsgError("Start timestamp %llu Completion timestamp %llu (completed after %llu ms)\n",
                           pIoReq->tsStart, pIoReq->tsComplete, pIoReq->tsComplete - pIoReq->tsStart);
                RTAssertDebugBreak();
            }
        }

        pIoReq->tsComplete = RTTimeSystemMilliTS();
        Assert(!pThis->papIoReq[pThis->iEntry]);
        pThis->papIoReq[pThis->iEntry] = pIoReq;

        pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
        if (pThis->papIoReq[pThis->iEntry])
        {
            RTMemFree(pThis->papIoReq[pThis->iEntry]);
            pThis->papIoReq[pThis->iEntry] = NULL;
        }
    }
    else
        RTMemFree(pIoReq);
}
static void testBasicsWaitSuccess(RTSEMEVENTMULTI hSem, unsigned i)
{
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWait(hSem, 0), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
#if 0
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitNoResume(hSem, 0), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitNoResume(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
#else
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
                          0),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME   | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          RTTimeSystemNanoTS() + 1000*i),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          RTTimeNanoTS() + 1000*i),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          0),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          _1G),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          UINT64_MAX),
                          VINF_SUCCESS);


    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          RTTimeSystemMilliTS() + 1000*i),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          RTTimeMilliTS() + 1000*i),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          0),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          _1M),
                          VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiWaitEx(hSem,
                          RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
                          UINT64_MAX),
                          VINF_SUCCESS);
#endif
}
示例#5
0
/**
 * Allocate a new I/O request.
 *
 * @returns New I/O request.
 * @param   enmTxDir      Transfer direction.
 * @param   off           Start offset.
 * @param   paSeg         Segment array.
 * @param   cSeg          Number of segments.
 * @param   cbTransfer    Number of bytes to transfer.
 * @param   pvUser        User argument.
 */
static PDRVDISKAIOREQ drvdiskintIoReqAlloc(DRVDISKAIOTXDIR enmTxDir, uint64_t off, PCRTSGSEG paSeg,
                                           unsigned cSeg, size_t cbTransfer, void *pvUser)
{
    PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)RTMemAlloc(sizeof(DRVDISKAIOREQ));

    if (RT_LIKELY(pIoReq))
    {
        pIoReq->enmTxDir    = enmTxDir;
        pIoReq->off         = off;
        pIoReq->cbTransfer  = cbTransfer;
        pIoReq->paSeg       = paSeg;
        pIoReq->cSeg        = cSeg;
        pIoReq->pvUser      = pvUser;
        pIoReq->iSlot       = 0;
        pIoReq->tsStart     = RTTimeSystemMilliTS();
        pIoReq->tsComplete  = 0;
        pIoReq->hIoLogEntry = NULL;
    }

    return pIoReq;
}
示例#6
0
/**
 * Service request callback function.
 *
 * @returns VBox status code.
 * @param   pSession    The caller's session.
 * @param   u64Arg      64-bit integer argument.
 * @param   pReqHdr     The request header. Input / Output. Optional.
 */
DECLEXPORT(int) TSTRTR0SemMutexSrvReqHandler(PSUPDRVSESSION pSession, uint32_t uOperation,
                                             uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
{
    NOREF(pSession);
    if (!VALID_PTR(pReqHdr))
        return VERR_INVALID_PARAMETER;
    char   *pszErr = (char *)(pReqHdr + 1);
    size_t  cchErr = pReqHdr->cbReq - sizeof(*pReqHdr);
    if (cchErr < 32 || cchErr >= 0x10000)
        return VERR_INVALID_PARAMETER;
    *pszErr = '\0';

#define SET_ERROR(szFmt)                do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt); } while (0)
#define SET_ERROR1(szFmt, a1)           do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1); } while (0)
#define SET_ERROR2(szFmt, a1, a2)       do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1, a2); } while (0)
#define SET_ERROR3(szFmt, a1, a2, a3)   do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1, a2, a3); } while (0)
#define CHECK_RC_BREAK(rc, rcExpect, szOp) \
        if ((rc) != (rcExpect)) \
        { \
            RTStrPrintf(pszErr, cchErr, "!%s -> %Rrc, expected %Rrc. line %u", szOp, rc, rcExpect, __LINE__); \
            SUPR0Printf("%s -> %d, expected %d. line %u", szOp, rc, rcExpect, __LINE__); \
            break; \
        }

    /*
     * Set up test timeout (when applicable).
     */
    if (u64Arg > 120)
    {
        SET_ERROR1("Timeout is too large (max 120): %lld",  u64Arg);
        return VINF_SUCCESS;
    }
    uint64_t const  StartTS = RTTimeSystemMilliTS();
    uint32_t const  cMsMax  = (uint32_t)u64Arg * 1000;

    /*
     * The big switch.
     */
    RTSEMMUTEX      hMtx;
    int             rc;
    switch (uOperation)
    {
        case TSTRTR0SEMMUTEX_SANITY_OK:
            break;

        case TSTRTR0SEMMUTEX_SANITY_FAILURE:
            SET_ERROR1("42failure42%1024s", "");
            break;

        case TSTRTR0SEMMUTEX_BASIC:
            rc = RTSemMutexCreate(&hMtx);
            CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
            do
            {
                /*
                 * The interruptible version first.
                 */
                /* simple request and release, polling. */
                rc = RTSemMutexRequestNoResume(hMtx, 0);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                /* simple request and release, wait for ever. */
                rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(indef_wait)");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                /* simple request and release, wait a tiny while. */
                rc = RTSemMutexRequestNoResume(hMtx, 133);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(133)");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                /* nested request and release. */
                rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#1");
                rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#2");
                rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#3");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3");
                rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#3b");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3b");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#2");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#1");

                /*
                 * The uninterruptible variant.
                 */
                /* simple request and release, polling. */
                rc = RTSemMutexRequest(hMtx, 0);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                /* simple request and release, wait for ever. */
                rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest(indef_wait)");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                /* simple request and release, wait a tiny while. */
                rc = RTSemMutexRequest(hMtx, 133);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest(133)");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                /* nested request and release. */
                rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#1");
                rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#2");
                rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#3");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3");
                rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#3b");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3b");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#2");
                rc = RTSemMutexRelease(hMtx);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#1");

            } while (false);

            rc = RTSemMutexDestroy(hMtx);
            CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexDestroy");
            break;

        case TSTRTR0SEMMUTEX_TEST2_SETUP:
        case TSTRTR0SEMMUTEX_TEST3_SETUP:
        case TSTRTR0SEMMUTEX_TEST4_SETUP:
            rc = RTSemMutexCreate(&g_hMtxTest2);
            CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
            break;

        case TSTRTR0SEMMUTEX_TEST2_DO:
            for (unsigned i = 0; i < 200; i++)
            {
                if (i & 1)
                {
                    rc = RTSemMutexRequestNoResume(g_hMtxTest2, RT_INDEFINITE_WAIT);
                    CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,indef_wait)");
                }
                else
                {
                    rc = RTSemMutexRequestNoResume(g_hMtxTest2, 30000);
                    CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,30000)");
                }
                RTThreadSleep(1);
                rc = RTSemMutexRelease(g_hMtxTest2);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                if ((i % 16) == 15 && RTTimeSystemMilliTS() - StartTS >= cMsMax)
                    break;
            }
            break;


        case TSTRTR0SEMMUTEX_TEST3_DO:
            for (unsigned i = 0; i < 1000000; i++)
            {
                if (i & 1)
                {
                    rc = RTSemMutexRequestNoResume(g_hMtxTest2, RT_INDEFINITE_WAIT);
                    CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,indef_wait)");
                }
                else
                {
                    rc = RTSemMutexRequestNoResume(g_hMtxTest2, 30000);
                    CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,30000)");
                }
                rc = RTSemMutexRelease(g_hMtxTest2);
                CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");

                if ((i % 256) == 255 && RTTimeSystemMilliTS() - StartTS >= cMsMax)
                    break;
            }
            break;

        case TSTRTR0SEMMUTEX_TEST4_DO:
            for (unsigned i = 0; i < 1024; i++)
            {
                rc = RTSemMutexRequestNoResume(g_hMtxTest2, (i % 32));
                if (rc != VERR_TIMEOUT)
                {
                    CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume");
                    RTThreadSleep(1000);

                    rc = RTSemMutexRelease(g_hMtxTest2);
                    CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
                }

                if (RTTimeSystemMilliTS() - StartTS >= cMsMax)
                    break;
            }
            break;

        case TSTRTR0SEMMUTEX_TEST2_CLEANUP:
        case TSTRTR0SEMMUTEX_TEST3_CLEANUP:
        case TSTRTR0SEMMUTEX_TEST4_CLEANUP:
            rc = RTSemMutexDestroy(g_hMtxTest2);
            CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
            g_hMtxTest2 = NIL_RTSEMMUTEX;
            break;


        default:
            SET_ERROR1("Unknown test #%d", uOperation);
            break;
    }

    /* The error indicator is the '!' in the message buffer. */
    return VINF_SUCCESS;
}
示例#7
0
/**
 * Gets the current millisecond timestamp.
 *
 * @returns millisecond timestamp.
 */
RTDECL(uint64_t) RTTimeMilliTS(void)
{
    return RTTimeSystemMilliTS();
}