Changeset 53787 in vbox
- Timestamp:
- Jan 13, 2015 4:16:07 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 97594
- Location:
- trunk/src/VBox/Devices/Graphics
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
r53783 r53787 67 67 68 68 /******************************************************************************* 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 /******************************************************************************* 69 83 * Structures and Typedefs * 70 84 *******************************************************************************/ … … 106 120 } Cursor; 107 121 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 108 131 STAMPROFILE StatR3CmdPresent; 109 132 STAMPROFILE StatR3CmdDrawPrimitive; … … 158 181 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGASTATE, Cursor.pData), 159 182 SSMFIELD_ENTRY( VMSVGASTATE, colorAnnotation), 183 SSMFIELD_ENTRY_IGNORE( VMSVGASTATE, cBusyDelayedEmts), 184 SSMFIELD_ENTRY_IGNORE( VMSVGASTATE, hBusyDelayedEmts), 185 SSMFIELD_ENTRY_IGNORE( VMSVGASTATE, StatBusyDelayEmts), 160 186 SSMFIELD_ENTRY_IGNORE( VMSVGASTATE, StatR3CmdPresent), 161 187 SSMFIELD_ENTRY_IGNORE( VMSVGASTATE, StatR3CmdDrawPrimitive), 162 188 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), 163 195 SSMFIELD_ENTRY_TERM() 164 196 }; … … 744 776 { 745 777 #ifndef IN_RING3 778 /* Go to ring-3 and yield the CPU a bit. */ 746 779 rc = VINF_IOM_R3_IOPORT_READ; 747 780 break; 748 781 #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); 751 800 #endif 752 801 } 753 *pu32 = pThis->svga.fBusy ;802 *pu32 = pThis->svga.fBusy != 0; 754 803 break; 755 804 … … 922 971 } 923 972 #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 */ 981 DECLINLINE(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 924 998 925 999 /** … … 1094 1168 #if defined(IN_RING3) || defined(IN_RING0) 1095 1169 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); 1098 1173 1099 1174 /* Kick the FIFO thread to start processing commands again. */ … … 1876 1951 1877 1952 /** 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 */ 1959 static 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 /** 1878 1974 * Reads (more) payload into the command buffer. 1879 1975 * … … 1892 1988 * buffer. (We will NEVER re-read anything.) 1893 1989 * @param pThread The calling PDM thread handle. 1990 * @param pThis The VGA state. 1894 1991 * @param pSVGAState Pointer to the ring-3 only SVGA state data. For 1895 1992 * statistics collection. … … 2029 2126 } 2030 2127 2031 /**2032 * Macro for checking if a fixed FIFO register is valid according to the2033 * 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 2041 2128 /* The async FIFO handling thread. */ 2042 2129 static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread) … … 2067 2154 { 2068 2155 2069 /* Wait for at most 250 ms to start polling. */ 2156 /* 2157 * Wait for at most 250 ms to start polling. 2158 */ 2070 2159 rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, 250); 2071 2160 AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED); … … 2090 2179 Log(("vmsvgaFIFOLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP])); 2091 2180 2181 /* 2182 * Handle external commands. 2183 */ 2092 2184 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE) 2093 2185 { … … 2144 2236 || !pThis->svga.fConfigured) 2145 2237 { 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]); 2149 2239 continue; /* device not enabled. */ 2150 2240 } … … 2162 2252 || offFifoMax <= offFifoMin 2163 2253 || offFifoMax > VMSVGA_FIFO_SIZE 2254 || (offFifoMax & 3) != 0 2255 || (offFifoMin & 3) != 0 2164 2256 || offCurrentCmd < offFifoMin 2165 2257 || offCurrentCmd > offFifoMax)) 2166 2258 { 2259 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors); 2167 2260 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 { 2169 2266 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors); 2170 continue;2171 }2172 if (RT_UNLIKELY(offCurrentCmd & 3))2173 {2174 2267 LogRelMax(8, ("vmsvgaFIFOLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd)); 2175 2268 offCurrentCmd = ~UINT32_C(3); … … 2206 2299 * Mark the FIFO as busy. 2207 2300 */ 2208 pThis->svga.fBusy = true;2301 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO); 2209 2302 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); 2211 2304 2212 2305 /* … … 3074 3167 { 3075 3168 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); 3079 3170 } 3080 3171 } … … 3171 3262 } 3172 3263 3173 if ( pThis->svga.cbScanline ==cbDestPitch3174 && cbWidth ==cbDestPitch3175 && cbSrcPitch== cbDestPitch)3264 if ( pThis->svga.cbScanline == (uint32_t)cbDestPitch 3265 && cbWidth == (uint32_t)cbDestPitch 3266 && cbSrcPitch == cbDestPitch) 3176 3267 { 3177 3268 memcpy(pbDst, pSrc, cbWidth * cHeight); … … 3666 3757 if (pSVGAState) 3667 3758 { 3759 if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI) 3760 { 3761 RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts); 3762 pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT; 3763 } 3764 3668 3765 if (pSVGAState->Cursor.fActive) 3669 3766 RTMemFree(pSVGAState->Cursor.pData); … … 3734 3831 } 3735 3832 3833 /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */ 3834 rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts); 3835 AssertRCReturn(rc, rc); 3836 3736 3837 /* Register caps. */ 3737 3838 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; … … 3791 3892 STAM_REG(pVM, &pSVGAState->StatR3CmdDrawPrimitive, STAMTYPE_PROFILE, "/Devices/VMSVGA/3d/Cmd/DrawPrimitive", STAMUNIT_TICKS_PER_CALL, "Profiling of DrawPrimitive."); 3792 3893 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."); 3793 3895 STAM_REL_REG(pVM, &pSVGAState->StatFifoCommands, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoCommands", STAMUNIT_OCCURENCES, "FIFO command counter."); 3794 3896 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 254 254 /** SVGA memory area configured status. */ 255 255 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. */ 258 261 /** Traces (dirty page detection) enabled or not. */ 259 262 uint32_t fTraces; … … 274 277 /** Register caps. */ 275 278 uint32_t u32RegCaps; 276 uint32_t Padding2;277 279 /** Physical address of command mmio range. */ 278 280 RTIOPORT BasePort;
Note:
See TracChangeset
for help on using the changeset viewer.