VirtualBox

Changeset 53787 in vbox


Ignore:
Timestamp:
Jan 13, 2015 4:16:07 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
97594
Message:

Replaced ugly RTThreadSleep(50) on EMT with a yeild + a wait on a event sempahore that the FIFO thread will signal on when done.

Location:
trunk/src/VBox/Devices/Graphics
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp

    r53783 r53787  
    6767
    6868/*******************************************************************************
     69*   Defined Constants And Macros                                               *
     70*******************************************************************************/
     71/**
     72 * Macro for checking if a fixed FIFO register is valid according to the
     73 * current FIFO configuration.
     74 *
     75 * @returns true / false.
     76 * @param   a_iIndex        The fifo register index (like SVGA_FIFO_CAPABILITIES).
     77 * @param   a_offFifoMin    A valid SVGA_FIFO_MIN value.
     78 */
     79#define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
     80
     81
     82/*******************************************************************************
    6983*   Structures and Typedefs                                                    *
    7084*******************************************************************************/
     
    106120    } Cursor;
    107121    SVGAColorBGRX           colorAnnotation;
     122
     123    /** Number of EMTs waiting on hBusyDelayedEmts. */
     124    uint32_t volatile       cBusyDelayedEmts;
     125    /** Semaphore that EMTs wait on when reading SVGA_REG_BUSY and the FIFO is
     126     *  busy (ugly).  */
     127    RTSEMEVENTMULTI         hBusyDelayedEmts;
     128    /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
     129    STAMPROFILE             StatBusyDelayEmts;
     130
    108131    STAMPROFILE             StatR3CmdPresent;
    109132    STAMPROFILE             StatR3CmdDrawPrimitive;
     
    158181    SSMFIELD_ENTRY_IGN_HCPTR(   VMSVGASTATE, Cursor.pData),
    159182    SSMFIELD_ENTRY(             VMSVGASTATE, colorAnnotation),
     183    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, cBusyDelayedEmts),
     184    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, hBusyDelayedEmts),
     185    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatBusyDelayEmts),
    160186    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatR3CmdPresent),
    161187    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatR3CmdDrawPrimitive),
    162188    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatR3CmdSurfaceDMA),
     189    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatFifoCommands),
     190    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatFifoErrors),
     191    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatFifoUnkCmds),
     192    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatFifoTodoTimeout),
     193    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatFifoTodoWoken),
     194    SSMFIELD_ENTRY_IGNORE(      VMSVGASTATE, StatFifoStalls),
    163195    SSMFIELD_ENTRY_TERM()
    164196};
     
    744776        {
    745777#ifndef IN_RING3
     778            /* Go to ring-3 and yield the CPU a bit. */
    746779            rc = VINF_IOM_R3_IOPORT_READ;
    747780            break;
    748781#else
    749             /** @todo bit crude */
    750             RTThreadSleep(50);
     782            /* Delay the EMT a bit so the FIFO and others can get some work done.
     783               This used to be a crude 50 ms sleep. The current code tries to be
     784               more efficient, but the consept is still very crude. */
     785            PVMSVGASTATE pSVGAState = (PVMSVGASTATE)pThis->svga.pSVGAState;
     786            STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
     787            RTThreadYield();
     788            if (pThis->svga.fBusy)
     789            {
     790                uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
     791
     792                if (pThis->svga.fBusy && cRefs == 1)
     793                    RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
     794                if (pThis->svga.fBusy)
     795                    RTSemEventMultiWait(pSVGAState->hBusyDelayedEmts, 50);
     796
     797                ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
     798            }
     799            STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    751800#endif
    752801        }
    753         *pu32 = pThis->svga.fBusy;
     802        *pu32 = pThis->svga.fBusy != 0;
    754803        break;
    755804
     
    922971}
    923972#endif /* IN_RING3 */
     973
     974#if defined(IN_RING0) || defined(IN_RING3)
     975/**
     976 * Safely updates the SVGA_FIFO_BUSY register (in shared memory).
     977 *
     978 * @param   pThis               The VMSVGA state.
     979 * @param   fState              The busy state.
     980 */
     981DECLINLINE(void) vmsvgaSafeFifoBusyRegUpdate(PVGASTATE pThis, bool fState)
     982{
     983    ASMAtomicWriteU32(&pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY], fState);
     984
     985    if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
     986    {
     987        /* Race / unfortunately scheduling. Highly unlikly. */
     988        uint32_t cLoops = 64;
     989        do
     990        {
     991            ASMNopPause();
     992            fState = (pThis->svga.fBusy != 0);
     993            ASMAtomicWriteU32(&pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY], fState != 0);
     994        } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
     995    }
     996}
     997#endif
    924998
    925999/**
     
    10941168#if defined(IN_RING3) || defined(IN_RING0)
    10951169            Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY]));
    1096             pThis->svga.fBusy = true;
    1097             pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
     1170            ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
     1171            if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_MIN]))
     1172                vmsvgaSafeFifoBusyRegUpdate(pThis, true);
    10981173
    10991174            /* Kick the FIFO thread to start processing commands again. */
     
    18761951
    18771952/**
     1953 * Marks the FIFO non-busy, notifying any waiting EMTs.
     1954 *
     1955 * @param   pThis           The VGA state.
     1956 * @param   pSVGAState      Pointer to the ring-3 only SVGA state data.
     1957 * @param   offFifoMin      The start byte offset of the command FIFO.
     1958 */
     1959static void vmsvgaFifoSetNotBusy(PVGASTATE pThis, PVMSVGASTATE pSVGAState, uint32_t offFifoMin)
     1960{
     1961    ASMAtomicAndU32(&pThis->svga.fBusy, ~VMSVGA_BUSY_F_FIFO);
     1962    if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
     1963        vmsvgaSafeFifoBusyRegUpdate(pThis, pThis->svga.fBusy != 0);
     1964
     1965    /* Wake up any waiting EMTs. */
     1966    if (pSVGAState->cBusyDelayedEmts > 0)
     1967    {
     1968        int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
     1969        AssertRC(rc2);
     1970    }
     1971}
     1972
     1973/**
    18781974 * Reads (more) payload into the command buffer.
    18791975 *
     
    18921988 *                          buffer. (We will NEVER re-read anything.)
    18931989 * @param   pThread         The calling PDM thread handle.
     1990 * @param   pThis           The VGA state.
    18941991 * @param   pSVGAState      Pointer to the ring-3 only SVGA state data. For
    18951992 *                          statistics collection.
     
    20292126}
    20302127
    2031 /**
    2032  * Macro for checking if a fixed FIFO register is valid according to the
    2033  * current FIFO configuration.
    2034  *
    2035  * @returns true / false.
    2036  * @param   a_iIndex        The fifo register index (like SVGA_FIFO_CAPABILITIES).
    2037  * @param   a_offFifoMin    A valid SVGA_FIFO_MIN value.
    2038  */
    2039 #define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
    2040 
    20412128/* The async FIFO handling thread. */
    20422129static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     
    20672154    {
    20682155
    2069         /* Wait for at most 250 ms to start polling. */
     2156        /*
     2157         * Wait for at most 250 ms to start polling.
     2158         */
    20702159        rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, 250);
    20712160        AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
     
    20902179        Log(("vmsvgaFIFOLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    20912180
     2181        /*
     2182         * Handle external commands.
     2183         */
    20922184        if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
    20932185        {
     
    21442236            ||  !pThis->svga.fConfigured)
    21452237        {
    2146             pThis->svga.fBusy = false;
    2147             if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pFIFO[SVGA_FIFO_MIN]))
    2148                 pThis->svga.pFIFOR3[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
     2238            vmsvgaFifoSetNotBusy(pThis, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
    21492239            continue;   /* device not enabled. */
    21502240        }
     
    21622252                        || offFifoMax <= offFifoMin
    21632253                        || offFifoMax > VMSVGA_FIFO_SIZE
     2254                        || (offFifoMax & 3) != 0
     2255                        || (offFifoMin & 3) != 0
    21642256                        || offCurrentCmd < offFifoMin
    21652257                        || offCurrentCmd > offFifoMax))
    21662258        {
     2259            STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    21672260            LogRelMax(8, ("vmsvgaFIFOLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
    2168             /** @todo Should we clear SVGA_FIFO_BUSY here like we do above? */
     2261            vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
     2262            continue;
     2263        }
     2264        if (RT_UNLIKELY(offCurrentCmd & 3))
     2265        {
    21692266            STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    2170             continue;
    2171         }
    2172         if (RT_UNLIKELY(offCurrentCmd & 3))
    2173         {
    21742267            LogRelMax(8, ("vmsvgaFIFOLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
    21752268            offCurrentCmd = ~UINT32_C(3);
     
    22062299         * Mark the FIFO as busy.
    22072300         */
    2208         pThis->svga.fBusy = true;
     2301        ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO);
    22092302        if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
    2210             pFIFO[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
     2303            ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
    22112304
    22122305        /*
     
    30743167        {
    30753168            Log(("vmsvgaFIFOLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
    3076             pThis->svga.fBusy = false;
    3077             if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
    3078                 pThis->svga.pFIFOR3[SVGA_FIFO_BUSY] = pThis->svga.fBusy;
     3169            vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
    30793170        }
    30803171    }
     
    31713262        }
    31723263
    3173         if (    pThis->svga.cbScanline == cbDestPitch
    3174             &&  cbWidth == cbDestPitch
    3175             &&  cbSrcPitch == cbDestPitch)
     3264        if (   pThis->svga.cbScanline == (uint32_t)cbDestPitch
     3265            && cbWidth                == (uint32_t)cbDestPitch
     3266            && cbSrcPitch            == cbDestPitch)
    31763267        {
    31773268            memcpy(pbDst, pSrc, cbWidth * cHeight);
     
    36663757    if (pSVGAState)
    36673758    {
     3759        if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
     3760        {
     3761            RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
     3762            pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
     3763        }
     3764
    36683765        if (pSVGAState->Cursor.fActive)
    36693766            RTMemFree(pSVGAState->Cursor.pData);
     
    37343831    }
    37353832
     3833    /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
     3834    rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
     3835    AssertRCReturn(rc, rc);
     3836
    37363837    /* Register caps. */
    37373838    pThis->svga.u32RegCaps = SVGA_CAP_GMR | SVGA_CAP_GMR2 | SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | SVGA_CAP_EXTENDED_FIFO | SVGA_CAP_IRQMASK | SVGA_CAP_PITCHLOCK | SVGA_CAP_TRACES | SVGA_CAP_SCREEN_OBJECT_2 | SVGA_CAP_ALPHA_CURSOR;
     
    37913892    STAM_REG(pVM, &pSVGAState->StatR3CmdDrawPrimitive,  STAMTYPE_PROFILE, "/Devices/VMSVGA/3d/Cmd/DrawPrimitive",  STAMUNIT_TICKS_PER_CALL, "Profiling of DrawPrimitive.");
    37923893    STAM_REG(pVM, &pSVGAState->StatR3CmdSurfaceDMA,     STAMTYPE_PROFILE, "/Devices/VMSVGA/3d/Cmd/SurfaceDMA",  STAMUNIT_TICKS_PER_CALL, "Profiling of SurfaceDMA.");
     3894    STAM_REL_REG(pVM, &pSVGAState->StatBusyDelayEmts,   STAMTYPE_PROFILE, "/Devices/VMSVGA/EmtDelayOnBusyFifo",  STAMUNIT_TICKS_PER_CALL, "Time we've delayed EMTs because of busy FIFO thread.");
    37933895    STAM_REL_REG(pVM, &pSVGAState->StatFifoCommands,    STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoCommands",  STAMUNIT_OCCURENCES, "FIFO command counter.");
    37943896    STAM_REL_REG(pVM, &pSVGAState->StatFifoErrors,      STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoErrors",  STAMUNIT_OCCURENCES, "FIFO error counter.");
  • trunk/src/VBox/Devices/Graphics/DevVGA.h

    r53752 r53787  
    254254    /** SVGA memory area configured status. */
    255255    uint32_t                    fConfigured;
    256     /** Device is busy handling FIFO requests. */
    257     uint32_t                    fBusy;
     256    /** Device is busy handling FIFO requests (VMSVGA_BUSY_F_FIFO,
     257     *  VMSVGA_BUSY_F_EMT_FORCE). */
     258    uint32_t volatile           fBusy;
     259#define VMSVGA_BUSY_F_FIFO          RT_BIT_32(0) /**< The normal true/false busy FIFO bit. */
     260#define VMSVGA_BUSY_F_EMT_FORCE     RT_BIT_32(1) /**< Bit preventing race status flickering when EMT kicks the FIFO thread. */
    258261    /** Traces (dirty page detection) enabled or not. */
    259262    uint32_t                    fTraces;
     
    274277    /** Register caps. */
    275278    uint32_t                    u32RegCaps;
    276     uint32_t                    Padding2;
    277279    /** Physical address of command mmio range. */
    278280    RTIOPORT                    BasePort;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette