/**
 * Read a MMIO register.
 *
 * @returns VBox status code suitable for scheduling.
 * @param   pDevIns     The device instance.
 * @param   pvUser      A user argument (ignored).
 * @param   GCPhysAddr  The physical address being written to. (This is within our MMIO memory range.)
 * @param   pv          Where to put the data we read.
 * @param   cb          The size of the read.
 */
PDMBOTHCBDECL(int) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
{
    PDEVOX958 pThis = PDMINS_2_DATA(pDevIns, PDEVOX958);
    uint32_t  offReg = (GCPhysAddr - pThis->GCPhysMMIO);
    int       rc = VINF_SUCCESS;
    RT_NOREF(pThis, pvUser);

    if (offReg < OX958_REG_UART_REGION_OFFSET)
    {
        uint32_t *pu32 = (uint32_t *)pv;
        Assert(cb == 4);

        switch (offReg)
        {
            case OX958_REG_CC_REV_ID:
                *pu32 = 0x00070002;
                break;
            case OX958_REG_UART_CNT:
                *pu32 = pThis->cUarts;
                break;
            case OX958_REG_UART_IRQ_STS:
                *pu32 = ASMAtomicReadU32(&pThis->u32RegIrqStsGlob);
                break;
            case OX958_REG_UART_IRQ_ENABLE:
                *pu32 = ASMAtomicReadU32(&pThis->u32RegIrqEnGlob);
                break;
            case OX958_REG_UART_IRQ_DISABLE:
                *pu32 = ~ASMAtomicReadU32(&pThis->u32RegIrqEnGlob);
                break;
            case OX958_REG_UART_WAKE_IRQ_ENABLE:
                *pu32 = ASMAtomicReadU32(&pThis->u32RegIrqEnWake);
                break;
            case OX958_REG_UART_WAKE_IRQ_DISABLE:
                *pu32 = ~ASMAtomicReadU32(&pThis->u32RegIrqEnWake);
                break;
            default:
                rc = VINF_IOM_MMIO_UNUSED_00;
        }
    }
    else
    {
        /* Figure out the UART accessed from the offset. */
        offReg -= OX958_REG_UART_REGION_OFFSET;
        uint32_t iUart = offReg / OX958_REG_UART_REGION_SIZE;
        uint32_t offUartReg = offReg % OX958_REG_UART_REGION_SIZE;
        if (iUart < pThis->cUarts)
        {
            POX958UART pUart = &pThis->aUarts[iUart];
            rc = ox958UartRegRead(pThis, pUart, offUartReg, pv, cb);
            if (rc == VINF_IOM_R3_IOPORT_READ)
                rc = VINF_IOM_R3_MMIO_READ;
        }
        else
            rc = VINF_IOM_MMIO_UNUSED_00;
    }

    return rc;
}
/**
 * Update IRQ status of the device.
 *
 * @returns nothing.
 * @param   pThis               The OXPCIe958 device instance.
 */
static void ox958IrqUpdate(PDEVOX958 pThis)
{
    uint32_t u32IrqSts = ASMAtomicReadU32(&pThis->u32RegIrqStsGlob);
    uint32_t u32IrqEn  = ASMAtomicReadU32(&pThis->u32RegIrqEnGlob);

    if (u32IrqSts & u32IrqEn)
        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_HIGH);
    else
        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_LOW);
}
Example #3
0
/**
 * Wait for the thread to terminate.
 *
 * @returns     iprt status code.
 * @param       Thread          The thread to wait for.
 * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
 *                              an indefinite wait.
 * @param       prc             Where to store the return code of the thread. Optional.
 * @param       fAutoResume     Whether or not to resume the wait on VERR_INTERRUPTED.
 */
static int rtThreadWait(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc, bool fAutoResume)
{
    int rc = VERR_INVALID_HANDLE;
    if (Thread != NIL_RTTHREAD)
    {
        PRTTHREADINT pThread = rtThreadGet(Thread);
        if (pThread)
        {
            if (pThread->fFlags & RTTHREADFLAGS_WAITABLE)
            {
                if (fAutoResume)
                    rc = RTSemEventMultiWait(pThread->EventTerminated, cMillies);
                else
                    rc = RTSemEventMultiWaitNoResume(pThread->EventTerminated, cMillies);
                if (RT_SUCCESS(rc))
                {
                    if (prc)
                        *prc = pThread->rc;

                    /*
                     * If the thread is marked as waitable, we'll do one additional
                     * release in order to free up the thread structure (see how we
                     * init cRef in rtThreadAlloc()).
                     */
                    if (ASMAtomicBitTestAndClear(&pThread->fFlags, RTTHREADFLAGS_WAITABLE_BIT))
                    {
                        rtThreadRelease(pThread);
#ifdef IN_RING0
                        /*
                         * IPRT termination kludge. Call native code to make sure
                         * the last thread is really out of IPRT to prevent it from
                         * crashing after we destroyed the spinlock in rtThreadTerm.
                         */
                        if (   ASMAtomicReadU32(&g_cThreadInTree) == 1
                            && ASMAtomicReadU32(&pThread->cRefs) > 1)
                            rtThreadNativeWaitKludge(pThread);
#endif
                    }
                }
            }
            else
            {
                rc = VERR_THREAD_NOT_WAITABLE;
                AssertRC(rc);
            }
            rtThreadRelease(pThread);
        }
    }
    return rc;
}
Example #4
0
RTDECL(int)  RTPipeClose(RTPIPE hPipe)
{
    RTPIPEINTERNAL *pThis = hPipe;
    if (pThis == NIL_RTPIPE)
        return VINF_SUCCESS;
    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
    AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);

    /*
     * Do the cleanup.
     */
    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTPIPE_MAGIC, RTPIPE_MAGIC), VERR_INVALID_HANDLE);

    int fd = pThis->fd;
    pThis->fd = -1;
    close(fd);

    if (ASMAtomicReadU32(&pThis->u32State) & RTPIPE_POSIX_USERS_MASK)
    {
        AssertFailed();
        RTThreadSleep(1);
    }

    RTMemFree(pThis);

    return VINF_SUCCESS;
}
static PVBOXDISPMPLOGGER vboxDispMpLoggerGet()
{
    if (ASMAtomicCmpXchgU32((volatile uint32_t *)&g_VBoxDispMpLogger.enmState, VBOXDISPMPLOGGER_STATE_INITIALIZING, VBOXDISPMPLOGGER_STATE_UNINITIALIZED))
    {
        HRESULT hr = vboxDispKmtCallbacksInit(&g_VBoxDispMpLogger.KmtCallbacks);
        if (hr == S_OK)
        {
            /* we are on Vista+
             * check if we can Open Adapter, i.e. WDDM driver is installed */
            VBOXDISPKMT_ADAPTER Adapter;
            hr = vboxDispKmtOpenAdapter(&g_VBoxDispMpLogger.KmtCallbacks, &Adapter);
            if (hr == S_OK)
            {
                ASMAtomicWriteU32((volatile uint32_t *)&g_VBoxDispMpLogger.enmState, VBOXDISPMPLOGGER_STATE_INITIALIZED);
                vboxDispKmtCloseAdapter(&Adapter);
                return &g_VBoxDispMpLogger;
            }
            vboxDispKmtCallbacksTerm(&g_VBoxDispMpLogger.KmtCallbacks);
        }
    }
    else if (ASMAtomicReadU32((volatile uint32_t *)&g_VBoxDispMpLogger.enmState) == VBOXDISPMPLOGGER_STATE_INITIALIZED)
    {
        return &g_VBoxDispMpLogger;
    }
    return NULL;
}
Example #6
0
RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem)
{
    /*
     * Validate input.
     */
    struct RTSEMRWINTERNAL *pThis = hRWSem;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
                    VERR_INVALID_HANDLE);

    /*
     * Check if it's the writer.
     */
    pthread_t Self = pthread_self();
    pthread_t Writer;
    ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
    if (Writer == Self)
    {
        AssertMsgReturn(pThis->cWriterReads > 0, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
#ifdef RTSEMRW_STRICT
        int rc9 = RTLockValidatorRecExclUnwindMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core);
        if (RT_FAILURE(rc9))
            return rc9;
#endif
        pThis->cWriterReads--;
        return VINF_SUCCESS;
    }

    /*
     * Try unlock it.
     */
#ifdef RTSEMRW_STRICT
    int rc9 = RTLockValidatorRecSharedCheckAndRelease(&pThis->ValidatorRead, RTThreadSelf());
    if (RT_FAILURE(rc9))
        return rc9;
#endif
#ifdef RT_OS_LINUX /* glibc (at least 2.8) may screw up when unlocking a lock we don't own. */
    if (ASMAtomicReadU32(&pThis->cReaders) == 0)
    {
        AssertMsgFailed(("Not owner of %p\n", pThis));
        return VERR_NOT_OWNER;
    }
#endif
    ASMAtomicDecU32(&pThis->cReaders);
    int rc = pthread_rwlock_unlock(&pThis->RWLock);
    if (rc)
    {
        ASMAtomicIncU32(&pThis->cReaders);
        AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", hRWSem, rc));
        return RTErrConvertFromErrno(rc);
    }
    return VINF_SUCCESS;
}
Example #7
0
/**
 * Prepare non-blocking mode.
 *
 * @returns VINF_SUCCESS
 * @retval  VERR_WRONG_ORDER
 * @retval  VERR_INTERNAL_ERROR_4
 *
 * @param   pThis               The pipe handle.
 */
static int rtPipeTryNonBlocking(RTPIPEINTERNAL *pThis)
{
    /*
     * Update the state.
     */
    for (;;)
    {
        uint32_t        u32State    = ASMAtomicReadU32(&pThis->u32State);
        uint32_t const  u32StateOld = u32State;
        uint32_t const  cUsers      = (u32State & RTPIPE_POSIX_USERS_MASK);

        if (!(u32State & RTPIPE_POSIX_BLOCKING))
        {
            AssertReturn(cUsers < RTPIPE_POSIX_USERS_MASK / 2, VERR_INTERNAL_ERROR_4);
            u32State &= ~RTPIPE_POSIX_USERS_MASK;
            u32State |= cUsers + 1;
            if (ASMAtomicCmpXchgU32(&pThis->u32State, u32State, u32StateOld))
            {
                if (u32State & RTPIPE_POSIX_SWITCHING)
                    break;
                return VINF_SUCCESS;
            }
        }
        else if (cUsers == 0)
        {
            u32State = 1 | RTPIPE_POSIX_SWITCHING;
            if (ASMAtomicCmpXchgU32(&pThis->u32State, u32State, u32StateOld))
                break;
        }
        else
            return VERR_WRONG_ORDER;
        ASMNopPause();
    }

    /*
     * Do the switching.
     */
    int fFlags = fcntl(pThis->fd, F_GETFL, 0);
    if (fFlags != -1)
    {
        if (    (fFlags & O_NONBLOCK)
            ||  fcntl(pThis->fd, F_SETFL, fFlags | O_NONBLOCK) != -1)
        {
            ASMAtomicBitClear(&pThis->u32State, RTPIPE_POSIX_SWITCHING_BIT);
            return VINF_SUCCESS;
        }
    }

    ASMAtomicDecU32(&pThis->u32State);
    return RTErrConvertFromErrno(errno);
}
Example #8
0
/**
 * Refreshes globals from GIP after one or more CPUs were added.
 *
 * There are potential races here.  We might race other threads and we may race
 * more CPUs being added.
 */
static void rtMpWinRefreshGip(void)
{
    PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
    if (   pGip
        && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC)
    {
        /*
         * Since CPUs cannot be removed, we only have to update the IDs and
         * indexes of CPUs that we think are inactive and the group member counts.
         */
        for (;;)
        {
            unsigned const cbGip          = pGip->cPages * PAGE_SIZE;
            uint32_t const cGipActiveCpus = pGip->cOnlineCpus;
            uint32_t const cMyActiveCpus  = ASMAtomicReadU32(&g_cRtMpWinActiveCpus);
            ASMCompilerBarrier();

            for (uint32_t idxGroup = 0; idxGroup < g_cRtMpWinMaxCpus; idxGroup++)
            {
                unsigned offCpuGroup = pGip->aoffCpuGroup[idxGroup];
                if (offCpuGroup < cbGip)
                {
                    PSUPGIPCPUGROUP pGipCpuGrp  = (PSUPGIPCPUGROUP)((uintptr_t)pGip + offCpuGroup);
                    uint32_t        cMaxMembers = pGipCpuGrp->cMaxMembers;
                    AssertStmt(cMaxMembers < RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers),
                               cMaxMembers = RT_ELEMENTS(g_aRtMpWinCpuGroups[0].aidxCpuSetMembers));
                    for (uint32_t idxMember = g_aRtMpWinCpuGroups[idxGroup].cActiveCpus; idxMember < cMaxMembers; idxMember++)
                    {
                        int16_t idxSet = pGipCpuGrp->aiCpuSetIdxs[idxMember];
                        g_aRtMpWinCpuGroups[idxGroup].aidxCpuSetMembers[idxMember] = idxSet;
                        if ((unsigned)idxSet < RT_ELEMENTS(g_aidRtMpWinByCpuSetIdx))
# ifdef IPRT_WITH_RTCPUID_AS_GROUP_AND_NUMBER
                            g_aidRtMpWinByCpuSetIdx[idxSet] = RTMPCPUID_FROM_GROUP_AND_NUMBER(idxGroup, idxMember);
# else
                            g_aidRtMpWinByCpuSetIdx[idxSet] = idxSet;
# endif
                    }
                    g_aRtMpWinCpuGroups[idxGroup].cMaxCpus    = RT_MIN(pGipCpuGrp->cMembers, cMaxMembers);
                    g_aRtMpWinCpuGroups[idxGroup].cActiveCpus = RT_MIN(pGipCpuGrp->cMembers, cMaxMembers);
                }
                else
                    Assert(g_aRtMpWinCpuGroups[idxGroup].cActiveCpus == 0);
            }

            ASMCompilerBarrier();
            if (cGipActiveCpus == pGip->cOnlineCpus)
                if (ASMAtomicCmpXchgU32(&g_cRtMpWinActiveCpus, cGipActiveCpus, cMyActiveCpus))
                    break;
        }
    }
}
/**
 * Finds an adapter by its name.
 *
 * @returns Pointer to the instance by the given name. NULL if not found.
 * @param   pGlobals        The globals.
 * @param   pszName         The name of the instance.
 */
PVBOXNETADP vboxNetAdpFindByName(const char *pszName)
{
    unsigned i;

    for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
    {
        PVBOXNETADP pThis = &g_aAdapters[i];
        Log2(("VBoxNetAdp: Scanning entry: state=%d name=%s\n", pThis->enmState, pThis->szName));
        if (   strcmp(pThis->szName, pszName) == 0
            && ASMAtomicReadU32((uint32_t volatile *)&pThis->enmState) == kVBoxNetAdpState_Active)
            return pThis;
    }
    return NULL;
}
VBOXDRVTOOL_DECL(VOID) VBoxDrvToolRefWaitEqual(PVBOXDRVTOOL_REF pRef, uint32_t u32Val)
{
    LARGE_INTEGER Interval;
    Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
    uint32_t cRefs;

    while ((cRefs = ASMAtomicReadU32(&pRef->cRefs)) != u32Val)
    {
        Assert(cRefs >= u32Val);
        Assert(cRefs < UINT32_MAX/2);

        KeDelayExecutionThread(KernelMode, FALSE, &Interval);
    }
}
VBOXDISPMPLOGGER_DECL(int) VBoxDispMpLoggerTerm(void)
{
    if (ASMAtomicCmpXchgU32((volatile uint32_t *)&g_VBoxDispMpLogger.enmState, VBOXDISPMPLOGGER_STATE_UNINITIALIZING, VBOXDISPMPLOGGER_STATE_INITIALIZED))
    {
        vboxDispKmtCallbacksTerm(&g_VBoxDispMpLogger.KmtCallbacks);
        ASMAtomicWriteU32((volatile uint32_t *)&g_VBoxDispMpLogger.enmState, VBOXDISPMPLOGGER_STATE_UNINITIALIZED);
        return S_OK;
    }
    else if (ASMAtomicReadU32((volatile uint32_t *)&g_VBoxDispMpLogger.enmState) == VBOXDISPMPLOGGER_STATE_UNINITIALIZED)
    {
        return S_OK;
    }
    return VERR_NOT_SUPPORTED;
}
Example #12
0
static void VBoxDispVHWACommandSubmitAsynchByEvent(PVBOXDISPDEV pDev, VBOXVHWACMD* pCmd, VBOXPEVENT pEvent)
{
    pCmd->GuestVBVAReserved1 = (uintptr_t)pEvent;
    pCmd->GuestVBVAReserved2 = 0;
    /* ensure the command is not removed until we're processing it */
    VBoxDispVHWACommandRetain(pDev, pCmd);

    /* complete it asynchronously by setting event */
    pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT;
    VBoxHGSMIBufferSubmit(&pDev->hgsmi.ctx, pCmd);

    if(!(ASMAtomicReadU32((volatile uint32_t *)&pCmd->Flags)  & VBOXVHWACMD_FLAG_HG_ASYNCH))
    {
        /* the command is completed */
        pDev->vpAPI.VideoPortProcs.pfnSetEvent(pDev->vpAPI.pContext, pEvent);
    }

    VBoxDispVHWACommandRelease(pDev, pCmd);
}
Example #13
0
DECLINLINE(int) shaWaitForManifestThreadFinished(PSHASTORAGEINTERNAL pInt)
{
//    RTPrintf("start\n");
    int rc = VINF_SUCCESS;
    for(;;)
    {
//        RTPrintf(" wait\n");
        uint32_t u32Status = ASMAtomicReadU32(&pInt->u32Status);
        if (!(   u32Status == STATUS_WRITE
              || u32Status == STATUS_WRITING
              || u32Status == STATUS_READ
              || u32Status == STATUS_READING))
            break;
        rc = RTSemEventWait(pInt->workFinishedEvent, 100);
    }
    if (rc == VERR_TIMEOUT)
        rc = VINF_SUCCESS;
    return rc;
}
Example #14
0
/**
 * Hook function for the thread-free event.
 *
 * @param   pvThreadCtxInt      Opaque pointer to the internal thread-context
 *                              object.
 * @param   fIsExec             Whether this event is triggered due to exec().
 */
static void rtThreadCtxHooksSolFree(void *pvThreadCtxInt, int fIsExec)
{
    PRTTHREADCTXINT pThis = (PRTTHREADCTXINT)pvThreadCtxInt;
    AssertPtrReturnVoid(pThis);
    AssertMsgReturnVoid(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));

    uint32_t cRefs = ASMAtomicReadU32(&pThis->cRefs);
    if (RT_UNLIKELY(!cRefs))
    {
        /* Should never happen. */
        AssertMsgFailed(("rtThreadCtxHooksSolFree with cRefs=0 pThis=%p\n", pThis));
        return;
    }

    cRefs = ASMAtomicDecU32(&pThis->cRefs);
    if (!cRefs)
    {
        Assert(!pThis->fRegistered);
        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
        RTMemFree(pThis);
    }
}
Example #15
0
RTDECL(bool)  RTSemRWIsReadOwner(RTSEMRW hRWSem, bool fWannaHear)
{
    /*
     * Validate handle.
     */
    struct RTSEMRWINTERNAL *pThis = hRWSem;
    AssertPtrReturn(pThis, false);
    AssertReturn(pThis->u32Magic == RTSEMRW_MAGIC, false);

    /*
     * Check write ownership.  The writer is also a valid reader.
     */
    pthread_t Self = pthread_self();
    pthread_t Writer;
    ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
    if (Writer == Self)
        return true;
    if (Writer != (pthread_t)-1)
        return false;

    /*
     * If there are no readers, we cannot be one of them, can we?
     */
    if (ASMAtomicReadU32(&pThis->cReaders) == 0)
        return false;

#ifdef RTSEMRW_STRICT
    /*
     * Ask the lock validator.
     */
    NOREF(fWannaHear);
    return RTLockValidatorRecSharedIsOwner(&pThis->ValidatorRead, NIL_RTTHREAD);
#else
    /*
     * Just tell the caller what he want to hear.
     */
    return fWannaHear;
#endif
}
VBOXDRVTOOL_DECL(VOID) VBoxDrvToolRefWaitEqual(PVBOXDRVTOOL_REF pRef, uint32_t u32Val)
{
    LARGE_INTEGER Interval;
    Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
    uint32_t cRefs;
    size_t loops = 0; 
    KTIMER kTimer;
    NTSTATUS status = STATUS_SUCCESS;

    KeInitializeTimer(&kTimer);
    
    while ((cRefs = ASMAtomicReadU32(&pRef->cRefs)) > u32Val && loops < 256)
    {
        Assert(cRefs >= u32Val);
        Assert(cRefs < UINT32_MAX/2);

        KeSetTimer(&kTimer, Interval, NULL);
        status = KeWaitForSingleObject(&kTimer, Executive, KernelMode, false, NULL);
        Assert(NT_SUCCESS(status));
        loops++;
    }
}
Example #17
0
/* Map device framebuffer and VRAM to our virtual address space */
int VBoxDispMPMapMemory(PVBOXDISPDEV pDev, PVIDEO_MEMORY_INFORMATION pMemInfo)
{
    DWORD dwrc;
    ULONG cbReturned;
    VIDEO_MEMORY vMem;
    VIDEO_MEMORY_INFORMATION vMemInfo;
    LOGF_ENTER();

    Assert(!pDev->memInfo.FrameBufferBase && !pDev->memInfo.VideoRamBase);

    vMem.RequestedVirtualAddress = NULL;
    dwrc = EngDeviceIoControl(pDev->hDriver, IOCTL_VIDEO_MAP_VIDEO_MEMORY, &vMem, sizeof(vMem), &vMemInfo, sizeof(vMemInfo), &cbReturned);
    VBOX_CHECK_WINERR_RETRC(dwrc, VERR_DEV_IO_ERROR);
    VBOX_WARN_IOCTLCB_RETRC("IOCTL_VIDEO_MAP_VIDEO_MEMORY", cbReturned, sizeof(vMemInfo), VERR_DEV_IO_ERROR);

    if (vMemInfo.FrameBufferBase != vMemInfo.VideoRamBase)
    {
        WARN(("FrameBufferBase!=VideoRamBase."));
        return VERR_GENERAL_FAILURE;
    }

    /* Check if we can access mapped memory */
    uint32_t magic = (*(ULONG *)vMemInfo.FrameBufferBase == 0xDEADF00D) ? 0xBAADF00D : 0xDEADF00D;

    ASMAtomicWriteU32((uint32_t *)vMemInfo.FrameBufferBase, magic);
    if (ASMAtomicReadU32((uint32_t *)vMemInfo.FrameBufferBase) != magic)
    {
        WARN(("can't write to framebuffer memory!"));
        return VERR_GENERAL_FAILURE;
    }

    memcpy(pMemInfo, &vMemInfo, sizeof(vMemInfo));

    LOGF_LEAVE();
    return VINF_SUCCESS;
}
Example #18
0
DECLCALLBACK(int) shaCalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
{
    /* Validate input. */
    AssertPtrReturn(pvUser, VERR_INVALID_POINTER);

    PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvUser;

    PVDINTERFACEIO pIfIo = VDIfIoGet(pInt->pShaStorage->pVDImageIfaces);
    AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);

    int rc = VINF_SUCCESS;
    bool fLoop = true;
    while(fLoop)
    {
        /* What should we do next? */
        uint32_t u32Status = ASMAtomicReadU32(&pInt->u32Status);
//        RTPrintf("status: %d\n", u32Status);
        switch (u32Status)
        {
            case STATUS_WAIT:
            {
                /* Wait for new work. */
                rc = RTSemEventWait(pInt->newStatusEvent, 100);
                if (   RT_FAILURE(rc)
                    && rc != VERR_TIMEOUT)
                    fLoop = false;
                break;
            }
            case STATUS_WRITE:
            {
                ASMAtomicCmpXchgU32(&pInt->u32Status, STATUS_WRITING, STATUS_WRITE);
                size_t cbAvail = RTCircBufUsed(pInt->pCircBuf);
                size_t cbMemAllRead = 0;
                /* First loop over all the free memory in the circular
                 * memory buffer (could be turn around at the end). */
                for(;;)
                {
                    if (   cbMemAllRead == cbAvail
                        || fLoop == false)
                        break;
                    char *pcBuf;
                    size_t cbMemToRead = cbAvail - cbMemAllRead;
                    size_t cbMemRead = 0;
                    /* Try to acquire all the used space of the circular buffer. */
                    RTCircBufAcquireReadBlock(pInt->pCircBuf, cbMemToRead, (void**)&pcBuf, &cbMemRead);
                    size_t cbAllWritten = 0;
                    /* Second, write as long as used memory is there. The write
                     * method could also split the writes up into to smaller
                     * parts. */
                    for(;;)
                    {
                        if (cbAllWritten == cbMemRead)
                            break;
                        size_t cbToWrite = cbMemRead - cbAllWritten;
                        size_t cbWritten = 0;
                        rc = vdIfIoFileWriteSync(pIfIo, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllWritten], cbToWrite, &cbWritten);
//                        RTPrintf ("%lu %lu %lu %Rrc\n", pInt->cbCurFile, cbToRead, cbRead, rc);
                        if (RT_FAILURE(rc))
                        {
                            fLoop = false;
                            break;
                        }
                        cbAllWritten += cbWritten;
                        pInt->cbCurFile += cbWritten;
                    }
                    /* Update the SHA1/SHA256 context with the next data block. */
                    if (   RT_SUCCESS(rc)
                        && pInt->pShaStorage->fCreateDigest)
                    {
                        if (pInt->pShaStorage->fSha256)
                            RTSha256Update(&pInt->ctx.Sha256, pcBuf, cbAllWritten);
                        else
                            RTSha1Update(&pInt->ctx.Sha1, pcBuf, cbAllWritten);
                    }
                    /* Mark the block as empty. */
                    RTCircBufReleaseReadBlock(pInt->pCircBuf, cbAllWritten);
                    cbMemAllRead += cbAllWritten;
                }
                /* Reset the thread status and signal the main thread that we
                 * are finished. Use CmpXchg, so we not overwrite other states
                 * which could be signaled in the meantime. */
                if (ASMAtomicCmpXchgU32(&pInt->u32Status, STATUS_WAIT, STATUS_WRITING))
                    rc = RTSemEventSignal(pInt->workFinishedEvent);
                break;
            }
            case STATUS_READ:
            {
                ASMAtomicCmpXchgU32(&pInt->u32Status, STATUS_READING, STATUS_READ);
                size_t cbAvail = RTCircBufFree(pInt->pCircBuf);
                size_t cbMemAllWrite = 0;
                /* First loop over all the available memory in the circular
                 * memory buffer (could be turn around at the end). */
                for(;;)
                {
                    if (   cbMemAllWrite == cbAvail
                        || fLoop == false)
                        break;
                    char *pcBuf;
                    size_t cbMemToWrite = cbAvail - cbMemAllWrite;
                    size_t cbMemWrite = 0;
                    /* Try to acquire all the free space of the circular buffer. */
                    RTCircBufAcquireWriteBlock(pInt->pCircBuf, cbMemToWrite, (void**)&pcBuf, &cbMemWrite);
                    /* Second, read as long as we filled all the memory. The
                     * read method could also split the reads up into to
                     * smaller parts. */
                    size_t cbAllRead = 0;
                    for(;;)
                    {
                        if (cbAllRead == cbMemWrite)
                            break;
                        size_t cbToRead = cbMemWrite - cbAllRead;
                        size_t cbRead = 0;
                        rc = vdIfIoFileReadSync(pIfIo, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllRead], cbToRead, &cbRead);
//                        RTPrintf ("%lu %lu %lu %Rrc\n", pInt->cbCurFile, cbToRead, cbRead, rc);
                        if (RT_FAILURE(rc))
                        {
                            fLoop = false;
                            break;
                        }
                        /* This indicates end of file. Stop reading. */
                        if (cbRead == 0)
                        {
                            fLoop = false;
                            ASMAtomicWriteBool(&pInt->fEOF, true);
                            break;
                        }
                        cbAllRead += cbRead;
                        pInt->cbCurFile += cbRead;
                    }
                    /* Update the SHA1/SHA256 context with the next data block. */
                    if (   RT_SUCCESS(rc)
                        && pInt->pShaStorage->fCreateDigest)
                    {
                        if (pInt->pShaStorage->fSha256)
                            RTSha256Update(&pInt->ctx.Sha256, pcBuf, cbAllRead);
                        else
                            RTSha1Update(&pInt->ctx.Sha1, pcBuf, cbAllRead);
                    }
                    /* Mark the block as full. */
                    RTCircBufReleaseWriteBlock(pInt->pCircBuf, cbAllRead);
                    cbMemAllWrite += cbAllRead;
                }
                /* Reset the thread status and signal the main thread that we
                 * are finished. Use CmpXchg, so we not overwrite other states
                 * which could be signaled in the meantime. */
                if (ASMAtomicCmpXchgU32(&pInt->u32Status, STATUS_WAIT, STATUS_READING))
                    rc = RTSemEventSignal(pInt->workFinishedEvent);
                break;
            }
            case STATUS_END:
            {
                /* End signaled */
                fLoop = false;
                break;
            }
        }
    }
    /* Cleanup any status changes to indicate we are finished. */
    ASMAtomicWriteU32(&pInt->u32Status, STATUS_END);
    rc = RTSemEventSignal(pInt->workFinishedEvent);
    return rc;
}
Example #19
0
RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx)
{
    PRTTHREADCTXINT pThis = hThreadCtx;
    if (pThis == NIL_RTTHREADCTX)
        return 0;

    RTTHREADCTX_VALID_RETURN_RC(hThreadCtx, UINT32_MAX);
    Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD));

    pThis->fRegistered = false;
    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);

    if (   pThis->hOwner == RTThreadNativeSelf()
        && cRefs == 1)
    {
        /*
         * removectx() will invoke rtThreadCtxHooksSolFree() and there is no way to bypass it and still use
         * rtThreadCtxHooksSolFree() at the same time.  Hence the convulated reference counting.
         *
         * When this function is called from the owner thread and is the last reference, we call removectx() which
         * will invoke rtThreadCtxHooksSolFree() with cRefs = 1 and that will then free the hook object.
         *
         * When the function is called from a different thread, we simply decrement the reference. Whenever the
         * ring-0 thread dies, Solaris will call rtThreadCtxHooksSolFree() which will free the hook object.
         */
        int rc;
        if (g_frtSolOldThreadCtx)
        {
            rc = g_rtSolThreadCtx.Remove.pfnSol_removectx_old(curthread,
                                                              pThis,
                                                              rtThreadCtxHooksSolPreempting,
                                                              rtThreadCtxHooksSolResumed,
                                                              NULL,                          /* fork */
                                                              NULL,                          /* lwp_create */
                                                              rtThreadCtxHooksSolFree);
        }
        else
        {
            rc = g_rtSolThreadCtx.Remove.pfnSol_removectx(curthread,
                                                          pThis,
                                                          rtThreadCtxHooksSolPreempting,
                                                          rtThreadCtxHooksSolResumed,
                                                          NULL,                              /* fork */
                                                          NULL,                              /* lwp_create */
                                                          NULL,                              /* exit */
                                                          rtThreadCtxHooksSolFree);
        }
        AssertMsg(rc, ("removectx failed. rc=%d\n", rc));
        NOREF(rc);

#ifdef VBOX_STRICT
        cRefs = ASMAtomicReadU32(&pThis->cRefs);
        Assert(!cRefs);
#endif
        cRefs = 0;
    }
    else if (!cRefs)
    {
        /*
         * The ring-0 thread for this hook object has already died. Free up the object as we have no more references.
         */
        Assert(pThis->hOwner != RTThreadNativeSelf());
        ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC);
        RTMemFree(pThis);
    }

    return cRefs;
}
Example #20
0
RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
{
    IPRT_LINUX_SAVE_EFL_AC();
    int rc;
    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;

    AssertReturn(idCpu1 != idCpu2, VERR_INVALID_PARAMETER);
    AssertReturn(!(fFlags & RTMPON_F_VALID_MASK), VERR_INVALID_FLAGS);

    /*
     * Check that both CPUs are online before doing the broadcast call.
     */
    RTThreadPreemptDisable(&PreemptState);
    if (   RTMpIsCpuOnline(idCpu1)
        && RTMpIsCpuOnline(idCpu2))
    {
        /*
         * Use the smp_call_function variant taking a cpu mask where available,
         * falling back on broadcast with filter.  Slight snag if one of the
         * CPUs is the one we're running on, we must do the call and the post
         * call wait ourselves.
         */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
        cpumask_t   DstCpuMask;
#endif
        RTCPUID     idCpuSelf = RTMpCpuId();
        bool const  fCallSelf = idCpuSelf == idCpu1 || idCpuSelf == idCpu2;
        RTMPARGS    Args;
        Args.pfnWorker = pfnWorker;
        Args.pvUser1 = pvUser1;
        Args.pvUser2 = pvUser2;
        Args.idCpu   = idCpu1;
        Args.idCpu2  = idCpu2;
        Args.cHits   = 0;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
        cpumask_clear(&DstCpuMask);
        cpumask_set_cpu(idCpu1, &DstCpuMask);
        cpumask_set_cpu(idCpu2, &DstCpuMask);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
        cpus_clear(DstCpuMask);
        cpu_set(idCpu1, DstCpuMask);
        cpu_set(idCpu2, DstCpuMask);
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
        smp_call_function_many(&DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
        rc = 0;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
        rc = smp_call_function_many(&DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
        rc = smp_call_function_mask(DstCpuMask, rtmpLinuxWrapperPostInc, &Args, !fCallSelf /* wait */);
#else /* older kernels */
        rc = smp_call_function(rtMpLinuxOnPairWrapper, &Args, 0 /* retry */, !fCallSelf /* wait */);
#endif /* older kernels */
        Assert(rc == 0);

        /* Call ourselves if necessary and wait for the other party to be done. */
        if (fCallSelf)
        {
            uint32_t cLoops = 0;
            rtmpLinuxWrapper(&Args);
            while (ASMAtomicReadU32(&Args.cHits) < 2)
            {
                if ((cLoops & 0x1ff) == 0 && !RTMpIsCpuOnline(idCpuSelf == idCpu1 ? idCpu2 : idCpu1))
                    break;
                cLoops++;
                ASMNopPause();
            }
        }

        Assert(Args.cHits <= 2);
        if (Args.cHits == 2)
            rc = VINF_SUCCESS;
        else if (Args.cHits == 1)
            rc = VERR_NOT_ALL_CPUS_SHOWED;
        else if (Args.cHits == 0)
            rc = VERR_CPU_OFFLINE;
        else
            rc = VERR_CPU_IPE_1;
    }
    /*
     * A CPU must be present to be considered just offline.
     */
    else if (   RTMpIsCpuPresent(idCpu1)
             && RTMpIsCpuPresent(idCpu2))
        rc = VERR_CPU_OFFLINE;
    else
        rc = VERR_CPU_NOT_FOUND;
    RTThreadPreemptRestore(&PreemptState);;
    IPRT_LINUX_RESTORE_EFL_AC();
    return rc;
}
Example #21
0
/* For contiguous chunks just return the address in the buffer.
 * For crossing boundary - allocate a buffer from heap.
 */
static bool i_vbvaFetchCmd(VIDEOACCEL *pVideoAccel, VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
{
    VBVAMEMORY *pVbvaMemory = pVideoAccel->pVbvaMemory;

    uint32_t indexRecordFirst = pVbvaMemory->indexRecordFirst;
    uint32_t indexRecordFree = pVbvaMemory->indexRecordFree;

#ifdef DEBUG_sunlover
    LogFlowFunc(("first = %d, free = %d\n",
                 indexRecordFirst, indexRecordFree));
#endif /* DEBUG_sunlover */

    if (!i_vbvaVerifyRingBuffer(pVbvaMemory))
    {
        return false;
    }

    if (indexRecordFirst == indexRecordFree)
    {
        /* No records to process. Return without assigning output variables. */
        return true;
    }

    uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVbvaMemory->aRecords[indexRecordFirst].cbRecord);

#ifdef DEBUG_sunlover
    LogFlowFunc(("cbRecord = 0x%08X\n", cbRecordCurrent));
#endif /* DEBUG_sunlover */

    uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;

    if (pVideoAccel->cbVbvaPartial)
    {
        /* There is a partial read in process. Continue with it. */

        Assert(pVideoAccel->pu8VbvaPartial);

        LogFlowFunc(("continue partial record cbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
                      pVideoAccel->cbVbvaPartial, cbRecordCurrent, indexRecordFirst, indexRecordFree));

        if (cbRecord > pVideoAccel->cbVbvaPartial)
        {
            /* New data has been added to the record. */
            if (!i_vbvaPartialRead(&pVideoAccel->pu8VbvaPartial, &pVideoAccel->cbVbvaPartial, cbRecord, pVbvaMemory))
            {
                return false;
            }
        }

        if (!(cbRecordCurrent & VBVA_F_RECORD_PARTIAL))
        {
            /* The record is completed by guest. Return it to the caller. */
            *ppHdr = (VBVACMDHDR *)pVideoAccel->pu8VbvaPartial;
            *pcbCmd = pVideoAccel->cbVbvaPartial;

            pVideoAccel->pu8VbvaPartial = NULL;
            pVideoAccel->cbVbvaPartial = 0;

            /* Advance the record index. */
            pVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;

#ifdef DEBUG_sunlover
            LogFlowFunc(("partial done ok, data = %d, free = %d\n",
                         pVbvaMemory->off32Data, pVbvaMemory->off32Free));
#endif /* DEBUG_sunlover */
        }

        return true;
    }

    /* A new record need to be processed. */
    if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL)
    {
        /* Current record is being written by guest. '=' is important here. */
        if (cbRecord >= VBVA_RING_BUFFER_SIZE - VBVA_RING_BUFFER_THRESHOLD)
        {
            /* Partial read must be started. */
            if (!i_vbvaPartialRead(&pVideoAccel->pu8VbvaPartial, &pVideoAccel->cbVbvaPartial, cbRecord, pVbvaMemory))
            {
                return false;
            }

            LogFlowFunc(("started partial record cbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
                          pVideoAccel->cbVbvaPartial, cbRecordCurrent, indexRecordFirst, indexRecordFree));
        }

        return true;
    }

    /* Current record is complete. If it is not empty, process it. */
    if (cbRecord)
    {
        /* The size of largest contiguous chunk in the ring biffer. */
        uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - pVbvaMemory->off32Data;

        /* The ring buffer pointer. */
        uint8_t *au8RingBuffer = &pVbvaMemory->au8RingBuffer[0];

        /* The pointer to data in the ring buffer. */
        uint8_t *src = &au8RingBuffer[pVbvaMemory->off32Data];

        /* Fetch or point the data. */
        if (u32BytesTillBoundary >= cbRecord)
        {
            /* The command does not cross buffer boundary. Return address in the buffer. */
            *ppHdr = (VBVACMDHDR *)src;

            /* Advance data offset. */
            pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
        }
        else
        {
            /* The command crosses buffer boundary. Rare case, so not optimized. */
            uint8_t *dst = (uint8_t *)RTMemAlloc(cbRecord);

            if (!dst)
            {
                LogRelFlowFunc(("could not allocate %d bytes from heap!!!\n", cbRecord));
                pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
                return false;
            }

            i_vbvaFetchBytes(pVbvaMemory, dst, cbRecord);

            *ppHdr = (VBVACMDHDR *)dst;

#ifdef DEBUG_sunlover
            LogFlowFunc(("Allocated from heap %p\n", dst));
#endif /* DEBUG_sunlover */
        }
    }

    *pcbCmd = cbRecord;

    /* Advance the record index. */
    pVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;

#ifdef DEBUG_sunlover
    LogFlowFunc(("done ok, data = %d, free = %d\n",
                 pVbvaMemory->off32Data, pVbvaMemory->off32Free));
#endif /* DEBUG_sunlover */

    return true;
}
Example #22
0
/**
 * Worker for RTAssertMsg2V and RTAssertMsg2AddV
 *
 * @param   fInitial            True if it's RTAssertMsg2V, otherwise false.
 * @param   pszFormat           The message format string.
 * @param   va                  The format arguments.
 */
static void rtAssertMsg2Worker(bool fInitial, const char *pszFormat, va_list va)
{
    va_list vaCopy;
    size_t  cch;

    /*
     * The global first.
     */
    if (fInitial)
    {
        va_copy(vaCopy, va);
        cch = RTStrPrintfV(g_szRTAssertMsg2, sizeof(g_szRTAssertMsg2), pszFormat, vaCopy);
        ASMAtomicWriteU32(&g_cchRTAssertMsg2, (uint32_t)cch);
        va_end(vaCopy);
    }
    else
    {
        cch = ASMAtomicReadU32(&g_cchRTAssertMsg2);
        if (cch < sizeof(g_szRTAssertMsg2) - 4)
        {
            va_copy(vaCopy, va);
            cch += RTStrPrintfV(&g_szRTAssertMsg2[cch], sizeof(g_szRTAssertMsg2) - cch, pszFormat, vaCopy);
            ASMAtomicWriteU32(&g_cchRTAssertMsg2, (uint32_t)cch);
            va_end(vaCopy);
        }
    }

    /*
     * If not quiet, make some noise.
     */
    if (!RTAssertAreQuiet())
    {
        RTERRVARS SavedErrVars;
        RTErrVarsSave(&SavedErrVars);

#ifdef IN_RING0
# ifdef IN_GUEST_R0
        va_copy(vaCopy, va);
        RTLogBackdoorPrintfV(pszFormat, vaCopy);
        va_end(vaCopy);
# endif
        /** @todo fully integrate this with the logger... play safe a bit for now.  */
        rtR0AssertNativeMsg2V(fInitial, pszFormat, va);

#else  /* !IN_RING0 */
# if !defined(IN_RING3) && !defined(LOG_NO_COM)
#  if 0 /* Enable this iff you have a COM port and really want this debug info. */
        va_copy(vaCopy, va);
        RTLogComPrintfV(pszFormat, vaCopy);
        va_end(vaCopy);
#  endif
# endif

        PRTLOGGER pLog = RTLogRelGetDefaultInstance();
        if (pLog)
        {
            va_copy(vaCopy, va);
            RTLogRelPrintfV(pszFormat, vaCopy);
            va_end(vaCopy);
# ifndef IN_RC /* flushing is done automatically in RC */
            RTLogFlush(pLog);
# endif
        }

        pLog = RTLogDefaultInstance();
        if (pLog)
        {
            va_copy(vaCopy, va);
            RTLogPrintfV(pszFormat, vaCopy);
            va_end(vaCopy);
# ifndef IN_RC /* flushing is done automatically in RC */
            RTLogFlush(pLog);
#endif
        }

# ifdef IN_RING3
        /* print to stderr, helps user and gdb debugging. */
        char szMsg[sizeof(g_szRTAssertMsg2)];
        va_copy(vaCopy, va);
        RTStrPrintfV(szMsg, sizeof(szMsg), pszFormat, vaCopy);
        va_end(vaCopy);
        fprintf(stderr, "%s", szMsg);
        fflush(stderr);
# endif
#endif /* !IN_RING0 */

        RTErrVarsRestore(&SavedErrVars);
    }
}
Example #23
0
bool RTCALL VBoxOglIsOfflineRenderingAppropriate()
{
    /* It is assumed that it is makes sense to enable offline rendering
       only in case if host has more than one GPU installed. This routine
       counts all the PCI devices in IORegistry which have IOName property
       set to "display". If the amount of such devices if greater than one,
       it returns TRUE or FALSE otherwise. */

    kern_return_t   krc;
    io_iterator_t   matchingServices;
    CFDictionaryRef pMatchingDictionary;
    static bool     fAppropriate = false;

    /* In order to do not slowdown 3D engine which can ask about offline rendering several times,
       let's cache the result and assume that renderers amount value is constant. Also prevent threads race
       on startup. */

#define VBOX_OGL_CHECK_UNINITIALIZED    (0)
#define VBOX_OGL_CHECK_INITIALIZING     (1)
#define VBOX_OGL_CHECK_INITIALIZED      (2)

    /* Transition VBOX_OGL_CHECK_UNINITIALIZED -> VBOX_OGL_CHECK_INITIALIZING means the current thread
       is the first one who entered the routine. In this case, it should detect number of GPUs, cache result
       and return it. If it's not TRUE, then fInitialized is VBOX_OGL_CHECK_INITIALIZING (another thread is performing
       the check; current thread should wait till result will be cached and return it) or VBOX_OGL_CHECK_INITIALIZED
       (result is already cached; just return it.) */

    static uint32_t volatile fInitialized = VBOX_OGL_CHECK_UNINITIALIZED;
    if (!ASMAtomicCmpXchgU32(&fInitialized, VBOX_OGL_CHECK_INITIALIZING, VBOX_OGL_CHECK_UNINITIALIZED))
    {
        while (ASMAtomicReadU32(&fInitialized) != VBOX_OGL_CHECK_INITIALIZED)
            RTThreadSleep(5);

        return fAppropriate;
    }

#define VBOX_OGL_RENDERER_MATCH_KEYS_NUM    (2)

    CFStringRef ppDictionaryKeys[VBOX_OGL_RENDERER_MATCH_KEYS_NUM] = { CFSTR(kIOProviderClassKey), CFSTR(kIONameMatchKey) };
    CFStringRef ppDictionaryVals[VBOX_OGL_RENDERER_MATCH_KEYS_NUM] = { CFSTR("IOPCIDevice"),       CFSTR("display") };

    pMatchingDictionary = CFDictionaryCreate(kCFAllocatorDefault,
                                             (const void **)ppDictionaryKeys,
                                             (const void **)ppDictionaryVals,
                                             VBOX_OGL_RENDERER_MATCH_KEYS_NUM,
                                             &kCFTypeDictionaryKeyCallBacks,
                                             &kCFTypeDictionaryValueCallBacks);
    if (pMatchingDictionary)
    {
        /* The reference to pMatchingDictionary is consumed by the function below => no IORelease(pMatchingDictionary)! */
        krc = IOServiceGetMatchingServices(kIOMasterPortDefault, pMatchingDictionary, &matchingServices);
        if (krc == kIOReturnSuccess)
        {
            io_object_t matchingService;
            int         cMatchingServices = 0;

            while ((matchingService = IOIteratorNext(matchingServices)) != 0)
            {
                cMatchingServices++;
                IOObjectRelease(matchingService);
            }

            fAppropriate = (cMatchingServices > 1);

            IOObjectRelease(matchingServices);
        }

    }

    LogRel(("OpenGL: Offline rendering support is %s (PID=%d)\n", fAppropriate ? "ON" : "OFF", (int)getpid()));

    ASMAtomicWriteU32(&fInitialized, VBOX_OGL_CHECK_INITIALIZED);

    return fAppropriate;
}
uint32_t vscsiIoReqOutstandingCountGet(PVSCSILUNINT pVScsiLun)
{
    return ASMAtomicReadU32(&pVScsiLun->IoReq.cReqOutstanding);
}
Example #25
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);
        }
    }
}
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;

            /* Check if we should delay completion of the request. */
            if (   ASMAtomicReadU32(&pEpFile->msDelay) > 0
                && ASMAtomicCmpXchgPtr(&pEpFile->pReqDelayed, pTaskFile, NULL))
            {
                /* Arm the delay. */
                pEpFile->tsDelayEnd = RTTimeProgramMilliTS() + pEpFile->msDelay;
                LogRel(("AIOMgr: Delaying request %#p for %u ms\n", pTaskFile, pEpFile->msDelay));
                return;
            }
#endif
            pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core, pTaskFile->rc, true);

#if PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
            /* Check for an expired delay. */
            if (   pEpFile->pReqDelayed != NULL
                && RTTimeProgramMilliTS() >= pEpFile->tsDelayEnd)
            {
                pTaskFile = ASMAtomicXchgPtrT(&pEpFile->pReqDelayed, NULL, PPDMASYNCCOMPLETIONTASKFILE);
                ASMAtomicXchgU32(&pEpFile->msDelay, 0);
                LogRel(("AIOMgr: Delayed request %#p completed\n", pTaskFile));
                pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core, pTaskFile->rc, true);
            }
#endif
        }
    }
}
Example #27
0
/**
 * Reap URBs in-flight on a device.
 *
 * @returns Pointer to a completed URB.
 * @returns NULL if no URB was completed.
 * @param   pProxyDev   The device.
 * @param   cMillies    Number of milliseconds to wait. Use 0 to not
 *                      wait at all.
 */
static DECLCALLBACK(PVUSBURB) usbProxyWinUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
{
    PPRIV_USBW32 pPriv = USBPROXYDEV_2_DATA(pProxyDev, PPRIV_USBW32);
    AssertReturn(pPriv, NULL);

    /*
     * There are some unnecessary calls, just return immediately or
     * WaitForMultipleObjects will fail.
     */
    if (   pPriv->cQueuedUrbs <= 0
        && pPriv->cPendingUrbs == 0)
    {
        if (   cMillies != 0
            && pPriv->cPendingUrbs == 0)
        {
            /* Wait for the wakeup call. */
            DWORD cMilliesWait = cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies;
            DWORD rc = WaitForMultipleObjects(1, &pPriv->hEventWakeup, FALSE, cMilliesWait);
        }

        return NULL;
    }

again:
    /* Check for pending URBs. */
    if (pPriv->cPendingUrbs)
    {
        RTCritSectEnter(&pPriv->CritSect);

        /* Ensure we've got sufficient space in the arrays. */
        if (pPriv->cQueuedUrbs + pPriv->cPendingUrbs + 1 > pPriv->cAllocatedUrbs)
        {
            unsigned cNewMax = pPriv->cAllocatedUrbs + pPriv->cPendingUrbs + 1;
            void *pv = RTMemRealloc(pPriv->paHandles, sizeof(pPriv->paHandles[0]) * (cNewMax + 1)); /* One extra for the wakeup event. */
            if (!pv)
            {
                AssertMsgFailed(("RTMemRealloc failed for paHandles[%d]", cNewMax));
                //break;
            }
            pPriv->paHandles = (PHANDLE)pv;

            pv = RTMemRealloc(pPriv->paQueuedUrbs, sizeof(pPriv->paQueuedUrbs[0]) * cNewMax);
            if (!pv)
            {
                AssertMsgFailed(("RTMemRealloc failed for paQueuedUrbs[%d]", cNewMax));
                //break;
            }
            pPriv->paQueuedUrbs = (PQUEUED_URB *)pv;
            pPriv->cAllocatedUrbs = cNewMax;
        }

        /* Copy the pending URBs over. */
        for (unsigned i = 0; i < pPriv->cPendingUrbs; i++)
        {
            pPriv->paHandles[pPriv->cQueuedUrbs + i] = pPriv->aPendingUrbs[i]->overlapped.hEvent;
            pPriv->paQueuedUrbs[pPriv->cQueuedUrbs + i] = pPriv->aPendingUrbs[i];
        }
        pPriv->cQueuedUrbs += pPriv->cPendingUrbs;
        pPriv->cPendingUrbs = 0;
        pPriv->paHandles[pPriv->cQueuedUrbs] = pPriv->hEventWakeup;
        pPriv->paHandles[pPriv->cQueuedUrbs + 1] = INVALID_HANDLE_VALUE;

        RTCritSectLeave(&pPriv->CritSect);
    }

    /*
     * Wait/poll.
     *
     * ASSUMPTIONS:
     *   1. The usbProxyWinUrbReap can not be run concurrently with each other
     *      so racing the cQueuedUrbs access/modification can not occur.
     *   2. The usbProxyWinUrbReap can not be run concurrently with
     *      usbProxyWinUrbQueue so they can not race the pPriv->paHandles
     *      access/realloc.
     */
    unsigned cQueuedUrbs = ASMAtomicReadU32((volatile uint32_t *)&pPriv->cQueuedUrbs);
    DWORD cMilliesWait = cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies;
    PVUSBURB pUrb = NULL;
    DWORD rc = WaitForMultipleObjects(cQueuedUrbs + 1, pPriv->paHandles, FALSE, cMilliesWait);

    /* If the wakeup event fired return immediately. */
    if (rc == WAIT_OBJECT_0 + cQueuedUrbs)
    {
        if (pPriv->cPendingUrbs)
            goto again;
        return NULL;
    }

    if (rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + cQueuedUrbs)
    {
        RTCritSectEnter(&pPriv->CritSect);
        unsigned iUrb = rc - WAIT_OBJECT_0;
        PQUEUED_URB pQUrbWin = pPriv->paQueuedUrbs[iUrb];
        pUrb = pQUrbWin->urb;

        /*
         * Remove it from the arrays.
         */
        cQueuedUrbs = --pPriv->cQueuedUrbs;
        if (cQueuedUrbs != iUrb)
        {
            /* Move the array forward */
            for (unsigned i=iUrb;i<cQueuedUrbs;i++)
            {
                pPriv->paHandles[i]    = pPriv->paHandles[i+1];
                pPriv->paQueuedUrbs[i] = pPriv->paQueuedUrbs[i+1];
            }
        }
        pPriv->paHandles[cQueuedUrbs] = pPriv->hEventWakeup;
        pPriv->paHandles[cQueuedUrbs + 1] = INVALID_HANDLE_VALUE;
        pPriv->paQueuedUrbs[cQueuedUrbs] = NULL;
        RTCritSectLeave(&pPriv->CritSect);
        Assert(cQueuedUrbs == pPriv->cQueuedUrbs);

        /*
         * Update the urb.
         */
        pUrb->enmStatus = usbProxyWinStatusToVUsbStatus(pQUrbWin->urbwin.error);
        pUrb->cbData = (uint32_t)pQUrbWin->urbwin.len;
        if (pUrb->enmType == VUSBXFERTYPE_ISOC)
        {
            for (unsigned i = 0; i < pUrb->cIsocPkts; ++i)
            {
                /* NB: Windows won't change the packet offsets, but the packets may
                 * be only partially filled or completely empty.
                 */
                pUrb->aIsocPkts[i].enmStatus = usbProxyWinStatusToVUsbStatus(pQUrbWin->urbwin.aIsoPkts[i].stat);
                pUrb->aIsocPkts[i].cb = pQUrbWin->urbwin.aIsoPkts[i].cb;
            }
        }
        Log(("usbproxy: pUrb=%p (#%d) ep=%d cbData=%d status=%d cIsocPkts=%d ready\n",
             pUrb, rc - WAIT_OBJECT_0, pQUrbWin->urb->EndPt, pQUrbWin->urb->cbData, pUrb->enmStatus, pUrb->cIsocPkts));

        /* free the urb queuing structure */
        if (pQUrbWin->overlapped.hEvent != INVALID_HANDLE_VALUE)
        {
            CloseHandle(pQUrbWin->overlapped.hEvent);
            pQUrbWin->overlapped.hEvent = INVALID_HANDLE_VALUE;
        }
        RTMemFree(pQUrbWin);
    }
    else if (   rc == WAIT_FAILED
             || (rc >= WAIT_ABANDONED_0 && rc < WAIT_ABANDONED_0 + cQueuedUrbs))
        AssertMsgFailed(("USB: WaitForMultipleObjects %d objects failed with rc=%d and last error %d\n", cQueuedUrbs, rc, GetLastError()));

    return pUrb;
}
Example #28
0
BOOLEAN vboxVhwaHlpOverlayListIsEmpty(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
{
    PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
    return !ASMAtomicReadU32(&pSource->cOverlays);
}