VirtualBox

Changeset 37527 in vbox


Ignore:
Timestamp:
Jun 17, 2011 10:18:02 AM (14 years ago)
Author:
vboxsync
Message:

TM: Virtual sync timer locking fixes and assertions.

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/TMAll.cpp

    r37517 r37527  
    7272
    7373
    74 #ifndef tmTimerLock
    75 
    76 /**
    77  * Try take the timer lock, wait in ring-3 return VERR_SEM_BUSY in R0/RC.
    78  *
    79  * @retval  VINF_SUCCESS on success (always in ring-3).
    80  * @retval  VERR_SEM_BUSY in RC and R0 if the semaphore is busy.
    81  *
     74/**
     75 * Gets the current warp drive percent.
     76 *
     77 * @returns The warp drive percent.
    8278 * @param   pVM         The VM handle.
    83  *
    84  * @thread  EMTs for the time being.
    85  */
    86 int tmTimerLock(PVM pVM)
    87 {
    88     VM_ASSERT_EMT(pVM);
    89     int rc = PDMCritSectEnter(&pVM->tm.s.TimerCritSect, VERR_SEM_BUSY);
    90     return rc;
    91 }
    92 
    93 
    94 /**
    95  * Try take the timer lock, no waiting.
    96  *
    97  * @retval  VINF_SUCCESS on success.
    98  * @retval  VERR_SEM_BUSY if busy.
    99  *
    100  * @param   pVM         The VM handle.
    101  */
    102 int tmTimerTryLock(PVM pVM)
    103 {
    104     int rc = PDMCritSectTryEnter(&pVM->tm.s.TimerCritSect);
    105     return rc;
    106 }
    107 
    108 
    109 /**
    110  * Release the EMT/TM lock.
    111  *
    112  * @param   pVM         The VM handle.
    113  */
    114 void tmTimerUnlock(PVM pVM)
    115 {
    116     PDMCritSectLeave(&pVM->tm.s.TimerCritSect);
    117 }
    118 
    119 
    120 /**
    121  * Try take the VirtualSync lock, wait in ring-3 return VERR_SEM_BUSY in R0/RC.
    122  *
    123  * @retval  VINF_SUCCESS on success (always in ring-3).
    124  * @retval  VERR_SEM_BUSY in RC and R0 if the semaphore is busy.
    125  *
    126  * @param   pVM         The VM handle.
    127  */
    128 int tmVirtualSyncLock(PVM pVM)
    129 {
    130     VM_ASSERT_EMT(pVM);
    131     int rc = PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_SEM_BUSY);
    132     return rc;
    133 }
    134 
    135 
    136 /**
    137  * Try take the VirtualSync lock, no waiting.
    138  *
    139  * @retval  VINF_SUCCESS on success.
    140  * @retval  VERR_SEM_BUSY if busy.
    141  *
    142  * @param   pVM         The VM handle.
    143  */
    144 int tmVirtualSyncTryLock(PVM pVM)
    145 {
    146     VM_ASSERT_EMT(pVM);
    147     int rc = PDMCritSectTryEnter(&pVM->tm.s.VirtualSyncLock);
    148     return rc;
    149 }
    150 
    151 
    152 /**
    153  * Release the VirtualSync lock.
    154  *
    155  * @param   pVM         The VM handle.
    156  */
    157 void tmVirtualSyncUnlock(PVM pVM)
    158 {
    159     PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    160 }
    161 
    162 #endif /* ! macros */
     79 */
     80VMMDECL(uint32_t) TMGetWarpDrive(PVM pVM)
     81{
     82    return pVM->tm.s.u32VirtualWarpDrivePercentage;
     83}
     84
    16385
    16486/**
     
    327249    PVM pVM = pTimer->CTX_SUFF(pVM);
    328250    if (    VM_IS_EMT(pVM)
    329         &&  RT_SUCCESS(tmTimerTryLock(pVM)))
     251        &&  RT_SUCCESS(TM_TRY_LOCK_TIMERS(pVM)))
    330252    {
    331253        STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatScheduleOne), a);
     
    336258#endif
    337259        STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatScheduleOne), a);
    338         tmTimerUnlock(pVM);
     260        TM_UNLOCK_TIMERS(pVM);
    339261    }
    340262    else
     
    568490void tmTimerQueueSchedule(PVM pVM, PTMTIMERQUEUE pQueue)
    569491{
    570     TM_ASSERT_LOCK(pVM);
     492    TM_ASSERT_TIMER_LOCK_OWNERSHIP(pVM);
    571493
    572494    /*
     
    609531void tmTimerQueuesSanityChecks(PVM pVM, const char *pszWhere)
    610532{
    611     TM_ASSERT_LOCK(pVM);
     533    TM_ASSERT_TIMER_LOCK_OWNERSHIP(pVM);
    612534
    613535    /*
     
    11951117
    11961118    STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetOpt);
    1197     tmTimerUnlock(pVM);
     1119    TM_UNLOCK_TIMERS(pVM);
    11981120    return VINF_SUCCESS;
    11991121}
     
    12151137    STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatTimerSetVs), a);
    12161138    VM_ASSERT_EMT(pVM);
     1139    Assert(PDMCritSectIsOwner(&pVM->tm.s.VirtualSyncLock));
    12171140    int rc = PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VINF_SUCCESS);
    12181141    AssertRCReturn(rc, rc);
     
    13201243    {
    13211244        /* Try take the TM lock and check the state again. */
    1322         if (RT_SUCCESS_NP(tmTimerTryLock(pVM)))
     1245        if (RT_SUCCESS_NP(TM_TRY_LOCK_TIMERS(pVM)))
    13231246        {
    13241247            if (RT_LIKELY(tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, enmState1)))
     
    13281251                return VINF_SUCCESS;
    13291252            }
    1330             tmTimerUnlock(pVM);
     1253            TM_UNLOCK_TIMERS(pVM);
    13311254        }
    13321255    }
     
    14921415
    14931416    STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeOpt);
    1494     tmTimerUnlock(pVM);
     1417    TM_UNLOCK_TIMERS(pVM);
    14951418    return VINF_SUCCESS;
    14961419}
     
    15131436    STAM_PROFILE_START(pVM->tm.s.CTX_SUFF_Z(StatTimerSetRelativeVs), a);
    15141437    VM_ASSERT_EMT(pVM);
     1438    Assert(PDMCritSectIsOwner(&pVM->tm.s.VirtualSyncLock));
    15151439    int rc = PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VINF_SUCCESS);
    15161440    AssertRCReturn(rc, rc);
     
    16261550     *       get the innermost locks.
    16271551     */
    1628     bool fOwnTMLock = RT_SUCCESS_NP(tmTimerTryLock(pVM));
     1552    bool fOwnTMLock = RT_SUCCESS_NP(TM_TRY_LOCK_TIMERS(pVM));
    16291553#if 1
    16301554    if (    fOwnTMLock
     
    17781702         */
    17791703        if (!fOwnTMLock)
    1780             fOwnTMLock = RT_SUCCESS_NP(tmTimerTryLock(pVM));
     1704            fOwnTMLock = RT_SUCCESS_NP(TM_TRY_LOCK_TIMERS(pVM));
    17811705
    17821706    } /* for (;;) */
     
    17861710     */
    17871711    if (fOwnTMLock)
    1788         tmTimerUnlock(pVM);
     1712        TM_UNLOCK_TIMERS(pVM);
    17891713
    17901714    STAM_PROFILE_STOP(&pTimer->CTX_SUFF(pVM)->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a);
    17911715    return rc;
    1792 }
    1793 
    1794 
    1795 /**
    1796  * Arm a timer with a (new) expire time relative to current time.
    1797  *
    1798  * @returns VBox status.
    1799  * @param   pTimer          Timer handle as returned by one of the create functions.
    1800  * @param   cMilliesToNext  Number of milliseconds to the next tick.
    1801  */
    1802 VMMDECL(int) TMTimerSetMillies(PTMTIMER pTimer, uint32_t cMilliesToNext)
    1803 {
    1804     PVM    pVM   = pTimer->CTX_SUFF(pVM);
    1805     PVMCPU pVCpu = &pVM->aCpus[0];  /* just take the first VCPU */
    1806 
    1807     switch (pTimer->enmClock)
    1808     {
    1809         case TMCLOCK_VIRTUAL:
    1810             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    1811             return TMTimerSetRelative(pTimer, cMilliesToNext * UINT64_C(1000000), NULL);
    1812 
    1813         case TMCLOCK_VIRTUAL_SYNC:
    1814             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    1815             return TMTimerSetRelative(pTimer, cMilliesToNext * UINT64_C(1000000), NULL);
    1816 
    1817         case TMCLOCK_REAL:
    1818             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    1819             return TMTimerSetRelative(pTimer, cMilliesToNext, NULL);
    1820 
    1821         default:
    1822             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    1823             return VERR_INTERNAL_ERROR;
    1824     }
    1825 }
    1826 
    1827 
    1828 /**
    1829  * Arm a timer with a (new) expire time relative to current time.
    1830  *
    1831  * @returns VBox status.
    1832  * @param   pTimer          Timer handle as returned by one of the create functions.
    1833  * @param   cMicrosToNext   Number of microseconds to the next tick.
    1834  */
    1835 VMMDECL(int) TMTimerSetMicro(PTMTIMER pTimer, uint64_t cMicrosToNext)
    1836 {
    1837     PVM    pVM   = pTimer->CTX_SUFF(pVM);
    1838     PVMCPU pVCpu = &pVM->aCpus[0];  /* just take the first VCPU */
    1839 
    1840     switch (pTimer->enmClock)
    1841     {
    1842         case TMCLOCK_VIRTUAL:
    1843             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    1844             return TMTimerSetRelative(pTimer, cMicrosToNext * 1000, NULL);
    1845 
    1846         case TMCLOCK_VIRTUAL_SYNC:
    1847             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    1848             return TMTimerSetRelative(pTimer, cMicrosToNext * 1000, NULL);
    1849 
    1850         case TMCLOCK_REAL:
    1851             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    1852             return TMTimerSetRelative(pTimer, cMicrosToNext / 1000, NULL);
    1853 
    1854         default:
    1855             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    1856             return VERR_INTERNAL_ERROR;
    1857     }
    1858 }
    1859 
    1860 
    1861 /**
    1862  * Arm a timer with a (new) expire time relative to current time.
    1863  *
    1864  * @returns VBox status.
    1865  * @param   pTimer          Timer handle as returned by one of the create functions.
    1866  * @param   cNanosToNext    Number of nanoseconds to the next tick.
    1867  */
    1868 VMMDECL(int) TMTimerSetNano(PTMTIMER pTimer, uint64_t cNanosToNext)
    1869 {
    1870     PVM    pVM   = pTimer->CTX_SUFF(pVM);
    1871     PVMCPU pVCpu = &pVM->aCpus[0];  /* just take the first VCPU */
    1872 
    1873     switch (pTimer->enmClock)
    1874     {
    1875         case TMCLOCK_VIRTUAL:
    1876             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    1877             return TMTimerSetRelative(pTimer, cNanosToNext, NULL);
    1878 
    1879         case TMCLOCK_VIRTUAL_SYNC:
    1880             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    1881             return TMTimerSetRelative(pTimer, cNanosToNext, NULL);
    1882 
    1883         case TMCLOCK_REAL:
    1884             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    1885             return TMTimerSetRelative(pTimer, cNanosToNext / 1000000, NULL);
    1886 
    1887         default:
    1888             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    1889             return VERR_INTERNAL_ERROR;
    1890     }
    18911716}
    18921717
     
    19381763    STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatTimerStopVs), a);
    19391764    VM_ASSERT_EMT(pVM);
     1765    Assert(PDMCritSectIsOwner(&pVM->tm.s.VirtualSyncLock));
    19401766    int rc = PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VINF_SUCCESS);
    19411767    AssertRCReturn(rc, rc);
     
    21491975        case TMCLOCK_REAL:
    21501976            return TMCLOCK_FREQ_REAL;
    2151 
    2152         default:
    2153             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    2154             return 0;
    2155     }
    2156 }
    2157 
    2158 
    2159 /**
    2160  * Get the current clock time as nanoseconds.
    2161  *
    2162  * @returns The timer clock as nanoseconds.
    2163  * @param   pTimer          Timer handle as returned by one of the create functions.
    2164  */
    2165 VMMDECL(uint64_t) TMTimerGetNano(PTMTIMER pTimer)
    2166 {
    2167     return TMTimerToNano(pTimer, TMTimerGet(pTimer));
    2168 }
    2169 
    2170 
    2171 /**
    2172  * Get the current clock time as microseconds.
    2173  *
    2174  * @returns The timer clock as microseconds.
    2175  * @param   pTimer          Timer handle as returned by one of the create functions.
    2176  */
    2177 VMMDECL(uint64_t) TMTimerGetMicro(PTMTIMER pTimer)
    2178 {
    2179     return TMTimerToMicro(pTimer, TMTimerGet(pTimer));
    2180 }
    2181 
    2182 
    2183 /**
    2184  * Get the current clock time as milliseconds.
    2185  *
    2186  * @returns The timer clock as milliseconds.
    2187  * @param   pTimer          Timer handle as returned by one of the create functions.
    2188  */
    2189 VMMDECL(uint64_t) TMTimerGetMilli(PTMTIMER pTimer)
    2190 {
    2191     return TMTimerToMilli(pTimer, TMTimerGet(pTimer));
    2192 }
    2193 
    2194 
    2195 /**
    2196  * Converts the specified timer clock time to nanoseconds.
    2197  *
    2198  * @returns nanoseconds.
    2199  * @param   pTimer          Timer handle as returned by one of the create functions.
    2200  * @param   u64Ticks        The clock ticks.
    2201  * @remark  There could be rounding errors here. We just do a simple integer divide
    2202  *          without any adjustments.
    2203  */
    2204 VMMDECL(uint64_t) TMTimerToNano(PTMTIMER pTimer, uint64_t u64Ticks)
    2205 {
    2206     switch (pTimer->enmClock)
    2207     {
    2208         case TMCLOCK_VIRTUAL:
    2209         case TMCLOCK_VIRTUAL_SYNC:
    2210             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    2211             return u64Ticks;
    2212 
    2213         case TMCLOCK_REAL:
    2214             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    2215             return u64Ticks * 1000000;
    2216 
    2217         default:
    2218             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    2219             return 0;
    2220     }
    2221 }
    2222 
    2223 
    2224 /**
    2225  * Converts the specified timer clock time to microseconds.
    2226  *
    2227  * @returns microseconds.
    2228  * @param   pTimer          Timer handle as returned by one of the create functions.
    2229  * @param   u64Ticks        The clock ticks.
    2230  * @remark  There could be rounding errors here. We just do a simple integer divide
    2231  *          without any adjustments.
    2232  */
    2233 VMMDECL(uint64_t) TMTimerToMicro(PTMTIMER pTimer, uint64_t u64Ticks)
    2234 {
    2235     switch (pTimer->enmClock)
    2236     {
    2237         case TMCLOCK_VIRTUAL:
    2238         case TMCLOCK_VIRTUAL_SYNC:
    2239             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    2240             return u64Ticks / 1000;
    2241 
    2242         case TMCLOCK_REAL:
    2243             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    2244             return u64Ticks * 1000;
    2245 
    2246         default:
    2247             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    2248             return 0;
    2249     }
    2250 }
    2251 
    2252 
    2253 /**
    2254  * Converts the specified timer clock time to milliseconds.
    2255  *
    2256  * @returns milliseconds.
    2257  * @param   pTimer          Timer handle as returned by one of the create functions.
    2258  * @param   u64Ticks        The clock ticks.
    2259  * @remark  There could be rounding errors here. We just do a simple integer divide
    2260  *          without any adjustments.
    2261  */
    2262 VMMDECL(uint64_t) TMTimerToMilli(PTMTIMER pTimer, uint64_t u64Ticks)
    2263 {
    2264     switch (pTimer->enmClock)
    2265     {
    2266         case TMCLOCK_VIRTUAL:
    2267         case TMCLOCK_VIRTUAL_SYNC:
    2268             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    2269             return u64Ticks / 1000000;
    2270 
    2271         case TMCLOCK_REAL:
    2272             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    2273             return u64Ticks;
    2274 
    2275         default:
    2276             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    2277             return 0;
    2278     }
    2279 }
    2280 
    2281 
    2282 /**
    2283  * Converts the specified nanosecond timestamp to timer clock ticks.
    2284  *
    2285  * @returns timer clock ticks.
    2286  * @param   pTimer          Timer handle as returned by one of the create functions.
    2287  * @param   cNanoSecs       The nanosecond value ticks to convert.
    2288  * @remark  There could be rounding and overflow errors here.
    2289  */
    2290 VMMDECL(uint64_t) TMTimerFromNano(PTMTIMER pTimer, uint64_t cNanoSecs)
    2291 {
    2292     switch (pTimer->enmClock)
    2293     {
    2294         case TMCLOCK_VIRTUAL:
    2295         case TMCLOCK_VIRTUAL_SYNC:
    2296             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    2297             return cNanoSecs;
    2298 
    2299         case TMCLOCK_REAL:
    2300             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    2301             return cNanoSecs / 1000000;
    2302 
    2303         default:
    2304             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    2305             return 0;
    2306     }
    2307 }
    2308 
    2309 
    2310 /**
    2311  * Converts the specified microsecond timestamp to timer clock ticks.
    2312  *
    2313  * @returns timer clock ticks.
    2314  * @param   pTimer          Timer handle as returned by one of the create functions.
    2315  * @param   cMicroSecs      The microsecond value ticks to convert.
    2316  * @remark  There could be rounding and overflow errors here.
    2317  */
    2318 VMMDECL(uint64_t) TMTimerFromMicro(PTMTIMER pTimer, uint64_t cMicroSecs)
    2319 {
    2320     switch (pTimer->enmClock)
    2321     {
    2322         case TMCLOCK_VIRTUAL:
    2323         case TMCLOCK_VIRTUAL_SYNC:
    2324             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    2325             return cMicroSecs * 1000;
    2326 
    2327         case TMCLOCK_REAL:
    2328             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    2329             return cMicroSecs / 1000;
    2330 
    2331         default:
    2332             AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
    2333             return 0;
    2334     }
    2335 }
    2336 
    2337 
    2338 /**
    2339  * Converts the specified millisecond timestamp to timer clock ticks.
    2340  *
    2341  * @returns timer clock ticks.
    2342  * @param   pTimer          Timer handle as returned by one of the create functions.
    2343  * @param   cMilliSecs      The millisecond value ticks to convert.
    2344  * @remark  There could be rounding and overflow errors here.
    2345  */
    2346 VMMDECL(uint64_t) TMTimerFromMilli(PTMTIMER pTimer, uint64_t cMilliSecs)
    2347 {
    2348     switch (pTimer->enmClock)
    2349     {
    2350         case TMCLOCK_VIRTUAL:
    2351         case TMCLOCK_VIRTUAL_SYNC:
    2352             AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
    2353             return cMilliSecs * 1000000;
    2354 
    2355         case TMCLOCK_REAL:
    2356             AssertCompile(TMCLOCK_FREQ_REAL == 1000);
    2357             return cMilliSecs;
    23581977
    23591978        default:
     
    24722091
    24732092
    2474 /**
    2475  * Gets the current warp drive percent.
    2476  *
    2477  * @returns The warp drive percent.
    2478  * @param   pVM         The VM handle.
    2479  */
    2480 VMMDECL(uint32_t) TMGetWarpDrive(PVM pVM)
    2481 {
    2482     return pVM->tm.s.u32VirtualWarpDrivePercentage;
     2093/* -=-=-=-=-=-=- Convenience APIs -=-=-=-=-=-=- */
     2094
     2095
     2096/**
     2097 * Arm a timer with a (new) expire time relative to current time.
     2098 *
     2099 * @returns VBox status.
     2100 * @param   pTimer          Timer handle as returned by one of the create functions.
     2101 * @param   cMilliesToNext  Number of milliseconds to the next tick.
     2102 */
     2103VMMDECL(int) TMTimerSetMillies(PTMTIMER pTimer, uint32_t cMilliesToNext)
     2104{
     2105    PVM    pVM   = pTimer->CTX_SUFF(pVM);
     2106    PVMCPU pVCpu = &pVM->aCpus[0];  /* just take the first VCPU */
     2107
     2108    switch (pTimer->enmClock)
     2109    {
     2110        case TMCLOCK_VIRTUAL:
     2111            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2112            return TMTimerSetRelative(pTimer, cMilliesToNext * UINT64_C(1000000), NULL);
     2113
     2114        case TMCLOCK_VIRTUAL_SYNC:
     2115            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2116            return TMTimerSetRelative(pTimer, cMilliesToNext * UINT64_C(1000000), NULL);
     2117
     2118        case TMCLOCK_REAL:
     2119            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2120            return TMTimerSetRelative(pTimer, cMilliesToNext, NULL);
     2121
     2122        default:
     2123            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2124            return VERR_INTERNAL_ERROR;
     2125    }
     2126}
     2127
     2128
     2129/**
     2130 * Arm a timer with a (new) expire time relative to current time.
     2131 *
     2132 * @returns VBox status.
     2133 * @param   pTimer          Timer handle as returned by one of the create functions.
     2134 * @param   cMicrosToNext   Number of microseconds to the next tick.
     2135 */
     2136VMMDECL(int) TMTimerSetMicro(PTMTIMER pTimer, uint64_t cMicrosToNext)
     2137{
     2138    PVM    pVM   = pTimer->CTX_SUFF(pVM);
     2139    PVMCPU pVCpu = &pVM->aCpus[0];  /* just take the first VCPU */
     2140
     2141    switch (pTimer->enmClock)
     2142    {
     2143        case TMCLOCK_VIRTUAL:
     2144            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2145            return TMTimerSetRelative(pTimer, cMicrosToNext * 1000, NULL);
     2146
     2147        case TMCLOCK_VIRTUAL_SYNC:
     2148            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2149            return TMTimerSetRelative(pTimer, cMicrosToNext * 1000, NULL);
     2150
     2151        case TMCLOCK_REAL:
     2152            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2153            return TMTimerSetRelative(pTimer, cMicrosToNext / 1000, NULL);
     2154
     2155        default:
     2156            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2157            return VERR_INTERNAL_ERROR;
     2158    }
     2159}
     2160
     2161
     2162/**
     2163 * Arm a timer with a (new) expire time relative to current time.
     2164 *
     2165 * @returns VBox status.
     2166 * @param   pTimer          Timer handle as returned by one of the create functions.
     2167 * @param   cNanosToNext    Number of nanoseconds to the next tick.
     2168 */
     2169VMMDECL(int) TMTimerSetNano(PTMTIMER pTimer, uint64_t cNanosToNext)
     2170{
     2171    PVM    pVM   = pTimer->CTX_SUFF(pVM);
     2172    PVMCPU pVCpu = &pVM->aCpus[0];  /* just take the first VCPU */
     2173
     2174    switch (pTimer->enmClock)
     2175    {
     2176        case TMCLOCK_VIRTUAL:
     2177            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2178            return TMTimerSetRelative(pTimer, cNanosToNext, NULL);
     2179
     2180        case TMCLOCK_VIRTUAL_SYNC:
     2181            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2182            return TMTimerSetRelative(pTimer, cNanosToNext, NULL);
     2183
     2184        case TMCLOCK_REAL:
     2185            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2186            return TMTimerSetRelative(pTimer, cNanosToNext / 1000000, NULL);
     2187
     2188        default:
     2189            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2190            return VERR_INTERNAL_ERROR;
     2191    }
     2192}
     2193
     2194
     2195/**
     2196 * Get the current clock time as nanoseconds.
     2197 *
     2198 * @returns The timer clock as nanoseconds.
     2199 * @param   pTimer          Timer handle as returned by one of the create functions.
     2200 */
     2201VMMDECL(uint64_t) TMTimerGetNano(PTMTIMER pTimer)
     2202{
     2203    return TMTimerToNano(pTimer, TMTimerGet(pTimer));
     2204}
     2205
     2206
     2207/**
     2208 * Get the current clock time as microseconds.
     2209 *
     2210 * @returns The timer clock as microseconds.
     2211 * @param   pTimer          Timer handle as returned by one of the create functions.
     2212 */
     2213VMMDECL(uint64_t) TMTimerGetMicro(PTMTIMER pTimer)
     2214{
     2215    return TMTimerToMicro(pTimer, TMTimerGet(pTimer));
     2216}
     2217
     2218
     2219/**
     2220 * Get the current clock time as milliseconds.
     2221 *
     2222 * @returns The timer clock as milliseconds.
     2223 * @param   pTimer          Timer handle as returned by one of the create functions.
     2224 */
     2225VMMDECL(uint64_t) TMTimerGetMilli(PTMTIMER pTimer)
     2226{
     2227    return TMTimerToMilli(pTimer, TMTimerGet(pTimer));
     2228}
     2229
     2230
     2231/**
     2232 * Converts the specified timer clock time to nanoseconds.
     2233 *
     2234 * @returns nanoseconds.
     2235 * @param   pTimer          Timer handle as returned by one of the create functions.
     2236 * @param   u64Ticks        The clock ticks.
     2237 * @remark  There could be rounding errors here. We just do a simple integer divide
     2238 *          without any adjustments.
     2239 */
     2240VMMDECL(uint64_t) TMTimerToNano(PTMTIMER pTimer, uint64_t u64Ticks)
     2241{
     2242    switch (pTimer->enmClock)
     2243    {
     2244        case TMCLOCK_VIRTUAL:
     2245        case TMCLOCK_VIRTUAL_SYNC:
     2246            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2247            return u64Ticks;
     2248
     2249        case TMCLOCK_REAL:
     2250            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2251            return u64Ticks * 1000000;
     2252
     2253        default:
     2254            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2255            return 0;
     2256    }
     2257}
     2258
     2259
     2260/**
     2261 * Converts the specified timer clock time to microseconds.
     2262 *
     2263 * @returns microseconds.
     2264 * @param   pTimer          Timer handle as returned by one of the create functions.
     2265 * @param   u64Ticks        The clock ticks.
     2266 * @remark  There could be rounding errors here. We just do a simple integer divide
     2267 *          without any adjustments.
     2268 */
     2269VMMDECL(uint64_t) TMTimerToMicro(PTMTIMER pTimer, uint64_t u64Ticks)
     2270{
     2271    switch (pTimer->enmClock)
     2272    {
     2273        case TMCLOCK_VIRTUAL:
     2274        case TMCLOCK_VIRTUAL_SYNC:
     2275            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2276            return u64Ticks / 1000;
     2277
     2278        case TMCLOCK_REAL:
     2279            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2280            return u64Ticks * 1000;
     2281
     2282        default:
     2283            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2284            return 0;
     2285    }
     2286}
     2287
     2288
     2289/**
     2290 * Converts the specified timer clock time to milliseconds.
     2291 *
     2292 * @returns milliseconds.
     2293 * @param   pTimer          Timer handle as returned by one of the create functions.
     2294 * @param   u64Ticks        The clock ticks.
     2295 * @remark  There could be rounding errors here. We just do a simple integer divide
     2296 *          without any adjustments.
     2297 */
     2298VMMDECL(uint64_t) TMTimerToMilli(PTMTIMER pTimer, uint64_t u64Ticks)
     2299{
     2300    switch (pTimer->enmClock)
     2301    {
     2302        case TMCLOCK_VIRTUAL:
     2303        case TMCLOCK_VIRTUAL_SYNC:
     2304            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2305            return u64Ticks / 1000000;
     2306
     2307        case TMCLOCK_REAL:
     2308            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2309            return u64Ticks;
     2310
     2311        default:
     2312            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2313            return 0;
     2314    }
     2315}
     2316
     2317
     2318/**
     2319 * Converts the specified nanosecond timestamp to timer clock ticks.
     2320 *
     2321 * @returns timer clock ticks.
     2322 * @param   pTimer          Timer handle as returned by one of the create functions.
     2323 * @param   cNanoSecs       The nanosecond value ticks to convert.
     2324 * @remark  There could be rounding and overflow errors here.
     2325 */
     2326VMMDECL(uint64_t) TMTimerFromNano(PTMTIMER pTimer, uint64_t cNanoSecs)
     2327{
     2328    switch (pTimer->enmClock)
     2329    {
     2330        case TMCLOCK_VIRTUAL:
     2331        case TMCLOCK_VIRTUAL_SYNC:
     2332            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2333            return cNanoSecs;
     2334
     2335        case TMCLOCK_REAL:
     2336            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2337            return cNanoSecs / 1000000;
     2338
     2339        default:
     2340            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2341            return 0;
     2342    }
     2343}
     2344
     2345
     2346/**
     2347 * Converts the specified microsecond timestamp to timer clock ticks.
     2348 *
     2349 * @returns timer clock ticks.
     2350 * @param   pTimer          Timer handle as returned by one of the create functions.
     2351 * @param   cMicroSecs      The microsecond value ticks to convert.
     2352 * @remark  There could be rounding and overflow errors here.
     2353 */
     2354VMMDECL(uint64_t) TMTimerFromMicro(PTMTIMER pTimer, uint64_t cMicroSecs)
     2355{
     2356    switch (pTimer->enmClock)
     2357    {
     2358        case TMCLOCK_VIRTUAL:
     2359        case TMCLOCK_VIRTUAL_SYNC:
     2360            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2361            return cMicroSecs * 1000;
     2362
     2363        case TMCLOCK_REAL:
     2364            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2365            return cMicroSecs / 1000;
     2366
     2367        default:
     2368            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2369            return 0;
     2370    }
     2371}
     2372
     2373
     2374/**
     2375 * Converts the specified millisecond timestamp to timer clock ticks.
     2376 *
     2377 * @returns timer clock ticks.
     2378 * @param   pTimer          Timer handle as returned by one of the create functions.
     2379 * @param   cMilliSecs      The millisecond value ticks to convert.
     2380 * @remark  There could be rounding and overflow errors here.
     2381 */
     2382VMMDECL(uint64_t) TMTimerFromMilli(PTMTIMER pTimer, uint64_t cMilliSecs)
     2383{
     2384    switch (pTimer->enmClock)
     2385    {
     2386        case TMCLOCK_VIRTUAL:
     2387        case TMCLOCK_VIRTUAL_SYNC:
     2388            AssertCompile(TMCLOCK_FREQ_VIRTUAL == 1000000000);
     2389            return cMilliSecs * 1000000;
     2390
     2391        case TMCLOCK_REAL:
     2392            AssertCompile(TMCLOCK_FREQ_REAL == 1000);
     2393            return cMilliSecs;
     2394
     2395        default:
     2396            AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
     2397            return 0;
     2398    }
    24832399}
    24842400
     
    25352451    if (RT_UNLIKELY(ASMAtomicReadBool(&pVM->tm.s.fHzHintNeedsUpdating)))
    25362452    {
    2537         if (RT_SUCCESS(tmTimerTryLock(pVM)))
     2453        if (RT_SUCCESS(TM_TRY_LOCK_TIMERS(pVM)))
    25382454        {
    25392455            ASMAtomicWriteBool(&pVM->tm.s.fHzHintNeedsUpdating, false);
     
    25762492            ASMAtomicWriteU32(&pVM->tm.s.uMaxHzHint, uMaxHzHint);
    25772493            Log(("tmGetFrequencyHint: New value %u Hz\n", uMaxHzHint));
    2578             tmTimerUnlock(pVM);
     2494            TM_UNLOCK_TIMERS(pVM);
    25792495        }
    25802496    }
  • trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp

    r37517 r37527  
    488488            *pcNsToDeadline = tmVirtualVirtToNsDeadline(pVM, cNsToDeadline);
    489489        }
    490         tmVirtualSyncUnlock(pVM);
     490        PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    491491    }
    492492    else
     
    501501        Log5(("TMAllVirtual(%u): FF: %d -> 1\n", __LINE__, VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
    502502        Log4(("TM: %'RU64/-%'8RU64: exp tmr=>ff [vsghcul]\n", u64, pVM->tm.s.offVirtualSync - pVM->tm.s.offVirtualSyncGivenUp));
    503         tmVirtualSyncUnlock(pVM);
     503        PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    504504
    505505        if (pcNsToDeadline)
     
    538538    {
    539539        u64 = ASMAtomicUoReadU64(&pVM->tm.s.u64VirtualSync);
    540         tmVirtualSyncUnlock(pVM);
     540        PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    541541        if (pcNsToDeadline)
    542542            *pcNsToDeadline = 0;
     
    572572    {
    573573        ASMAtomicWriteU64(&pVM->tm.s.u64VirtualSync, u64);
    574         tmVirtualSyncUnlock(pVM);
     574        PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    575575        if (pcNsToDeadline)
    576576            *pcNsToDeadline = tmVirtualVirtToNsDeadline(pVM, u64Expire - u64);
     
    587587        Log5(("TMAllVirtual(%u): FF: %d -> 1\n", __LINE__, !!VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
    588588        Log4(("TM: %'RU64/-%'8RU64: exp tmr=>ff [vsgl]\n", u64, pVM->tm.s.offVirtualSync - pVM->tm.s.offVirtualSyncGivenUp));
    589         tmVirtualSyncUnlock(pVM);
     589        PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    590590
    591591#ifdef IN_RING3
     
    658658     *       which is less picky or hasn't been adjusted yet
    659659     */
    660     if (tmVirtualSyncTryLock(pVM) == VINF_SUCCESS)
     660    if (PDMCritSectTryEnter(&pVM->tm.s.VirtualSyncLock) == VINF_SUCCESS)
    661661        return tmVirtualSyncGetLocked(pVM, u64, pcNsToDeadline);
    662662
     
    726726    {
    727727        /* Try grab the lock, things get simpler when owning the lock. */
    728         int rcLock = tmVirtualSyncTryLock(pVM);
     728        int rcLock = PDMCritSectTryEnter(&pVM->tm.s.VirtualSyncLock);
    729729        if (RT_SUCCESS_NP(rcLock))
    730730            return tmVirtualSyncGetLocked(pVM, u64, pcNsToDeadline);
  • trunk/src/VBox/VMM/VMMR3/TM.cpp

    r37518 r37527  
    10381038    LogFlow(("TMR3Reset:\n"));
    10391039    VM_ASSERT_EMT(pVM);
    1040     tmTimerLock(pVM);
     1040    TM_LOCK_TIMERS(pVM);
    10411041
    10421042    /*
     
    10731073    PVMCPU pVCpuDst = &pVM->aCpus[pVM->tm.s.idTimerCpu];
    10741074    VMCPU_FF_CLEAR(pVCpuDst, VMCPU_FF_TIMER); /** @todo FIXME: this isn't right. */
    1075     tmTimerUnlock(pVM);
     1075    TM_UNLOCK_TIMERS(pVM);
    10761076}
    10771077
     
    13021302
    13031303    /* insert into the list of created timers. */
    1304     tmTimerLock(pVM);
     1304    TM_LOCK_TIMERS(pVM);
    13051305    pTimer->pBigPrev        = NULL;
    13061306    pTimer->pBigNext        = pVM->tm.s.pCreated;
     
    13111311    tmTimerQueuesSanityChecks(pVM, "tmR3TimerCreate");
    13121312#endif
    1313     tmTimerUnlock(pVM);
     1313    TM_UNLOCK_TIMERS(pVM);
    13141314
    13151315    *ppTimer = pTimer;
     
    15311531     * like create does. All the work is done here.
    15321532     */
    1533     tmTimerLock(pVM);
     1533    TM_LOCK_TIMERS(pVM);
    15341534    for (int cRetries = 1000;; cRetries--)
    15351535    {
     
    15691569            case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:
    15701570                AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc));
    1571                 tmTimerUnlock(pVM);
     1571                TM_UNLOCK_TIMERS(pVM);
    15721572                if (!RTThreadYield())
    15731573                    RTThreadSleep(1);
    15741574                AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc),
    15751575                                VERR_TM_UNSTABLE_STATE);
    1576                 tmTimerLock(pVM);
     1576                TM_LOCK_TIMERS(pVM);
    15771577                continue;
    15781578
     
    15821582            case TMTIMERSTATE_FREE:
    15831583            case TMTIMERSTATE_DESTROY:
    1584                 tmTimerUnlock(pVM);
     1584                TM_UNLOCK_TIMERS(pVM);
    15851585                AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE);
    15861586
    15871587            default:
    15881588                AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc)));
    1589                 tmTimerUnlock(pVM);
     1589                TM_UNLOCK_TIMERS(pVM);
    15901590                return VERR_TM_UNKNOWN_STATE;
    15911591        }
     
    16001600            break;
    16011601        AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc));
    1602         tmTimerUnlock(pVM);
     1602        TM_UNLOCK_TIMERS(pVM);
    16031603        AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc),
    16041604                        VERR_TM_UNSTABLE_STATE);
    1605         tmTimerLock(pVM);
     1605        TM_LOCK_TIMERS(pVM);
    16061606    }
    16071607
     
    16611661    tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy");
    16621662#endif
    1663     tmTimerUnlock(pVM);
     1663    TM_UNLOCK_TIMERS(pVM);
    16641664    return VINF_SUCCESS;
    16651665}
     
    16791679        return VERR_INVALID_PARAMETER;
    16801680
    1681     tmTimerLock(pVM);
     1681    TM_LOCK_TIMERS(pVM);
    16821682    PTMTIMER    pCur = pVM->tm.s.pCreated;
    16831683    while (pCur)
     
    16921692        }
    16931693    }
    1694     tmTimerUnlock(pVM);
     1694    TM_UNLOCK_TIMERS(pVM);
    16951695
    16961696    LogFlow(("TMR3TimerDestroyDevice: returns VINF_SUCCESS\n"));
     
    17121712        return VERR_INVALID_PARAMETER;
    17131713
    1714     tmTimerLock(pVM);
     1714    TM_LOCK_TIMERS(pVM);
    17151715    PTMTIMER    pCur = pVM->tm.s.pCreated;
    17161716    while (pCur)
     
    17251725        }
    17261726    }
    1727     tmTimerUnlock(pVM);
     1727    TM_UNLOCK_TIMERS(pVM);
    17281728
    17291729    LogFlow(("TMR3TimerDestroyUsb: returns VINF_SUCCESS\n"));
     
    17451745        return VERR_INVALID_PARAMETER;
    17461746
    1747     tmTimerLock(pVM);
     1747    TM_LOCK_TIMERS(pVM);
    17481748    PTMTIMER    pCur = pVM->tm.s.pCreated;
    17491749    while (pCur)
     
    17581758        }
    17591759    }
    1760     tmTimerUnlock(pVM);
     1760    TM_UNLOCK_TIMERS(pVM);
    17611761
    17621762    LogFlow(("TMR3TimerDestroyDriver: returns VINF_SUCCESS\n"));
     
    19021902    Assert(!pVM->tm.s.fRunningQueues);
    19031903    ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, true);
    1904     tmTimerLock(pVM);
     1904    TM_LOCK_TIMERS(pVM);
    19051905
    19061906    /*
     
    19111911    /* TMCLOCK_VIRTUAL_SYNC (see also TMR3VirtualSyncFF) */
    19121912    STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], s1);
    1913     tmVirtualSyncLock(pVM);
     1913    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
    19141914    ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, true);
    19151915    VMCPU_FF_CLEAR(pVCpuDst, VMCPU_FF_TIMER);   /* Clear the FF once we started working for real. */
     
    19211921
    19221922    ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false);
    1923     tmVirtualSyncUnlock(pVM);
     1923    PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    19241924    STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], s1);
    19251925
     
    19491949    Log2(("TMR3TimerQueuesDo: returns void\n"));
    19501950    ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, false);
    1951     tmTimerUnlock(pVM);
     1951    TM_UNLOCK_TIMERS(pVM);
    19521952    STAM_PROFILE_STOP(&pVM->tm.s.StatDoQueues, a);
    19531953}
     
    23792379    {
    23802380        STAM_PROFILE_START(&pVM->tm.s.StatVirtualSyncFF, a);
    2381         tmVirtualSyncLock(pVM);
     2381        PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
    23822382        if (pVM->tm.s.fVirtualSyncTicking)
    23832383        {
    23842384            STAM_PROFILE_STOP(&pVM->tm.s.StatVirtualSyncFF, a); /* before the unlock! */
    2385             tmVirtualSyncUnlock(pVM);
     2385            PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    23862386            Log2(("TMR3VirtualSyncFF: ticking\n"));
    23872387        }
    23882388        else
    23892389        {
    2390             tmVirtualSyncUnlock(pVM);
     2390            PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
    23912391
    23922392            /* try run it. */
    2393             tmTimerLock(pVM);
    2394             tmVirtualSyncLock(pVM);
     2393            TM_LOCK_TIMERS(pVM);
     2394            PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
    23952395            if (pVM->tm.s.fVirtualSyncTicking)
    23962396                Log2(("TMR3VirtualSyncFF: ticking (2)\n"));
     
    24082408            }
    24092409            STAM_PROFILE_STOP(&pVM->tm.s.StatVirtualSyncFF, a); /* before the unlock! */
    2410             tmVirtualSyncUnlock(pVM);
    2411             tmTimerUnlock(pVM);
     2410            PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
     2411            TM_UNLOCK_TIMERS(pVM);
    24122412        }
    24132413    }
     
    24952495    }
    24962496
    2497     /* Enter the critical section to make TMTimerSet/Stop happy. */
     2497    /* Enter the critical sections to make TMTimerSet/Stop happy. */
     2498    if (pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC)
     2499        PDMCritSectEnter(&pTimer->pVMR3->tm.s.VirtualSyncLock, VERR_IGNORED);
    24982500    PPDMCRITSECT pCritSect = pTimer->pCritSect;
    24992501    if (pCritSect)
    2500         PDMCritSectEnter(pCritSect, VERR_INTERNAL_ERROR);
     2502        PDMCritSectEnter(pCritSect, VERR_IGNORED);
    25012503
    25022504    if (u8State == TMTIMERSTATE_SAVED_PENDING_SCHEDULE)
     
    25272529    if (pCritSect)
    25282530        PDMCritSectLeave(pCritSect);
     2531    if (pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC)
     2532        PDMCritSectLeave(&pTimer->pVMR3->tm.s.VirtualSyncLock);
    25292533
    25302534    /*
     
    26112615     * The shared virtual clock (includes virtual sync which is tied to it).
    26122616     */
    2613     tmTimerLock(pVM);                           /* Paranoia: Exploiting the timer lock here. */
     2617    TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
    26142618    int rc = tmVirtualPauseLocked(pVM);
    2615     tmTimerUnlock(pVM);
     2619    TM_UNLOCK_TIMERS(pVM);
    26162620    if (RT_FAILURE(rc))
    26172621        return rc;
     
    26752679     * The shared virtual clock (includes virtual sync which is tied to it).
    26762680     */
    2677     tmTimerLock(pVM);                           /* Paranoia: Exploiting the timer lock here. */
     2681    TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
    26782682    rc = tmVirtualResumeLocked(pVM);
    2679     tmTimerUnlock(pVM);
     2683    TM_UNLOCK_TIMERS(pVM);
    26802684
    26812685    return rc;
     
    27222726     * the warp drive settings.
    27232727     */
    2724     tmTimerLock(pVM);                           /* Paranoia: Exploiting the timer lock here. */
     2728    TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
    27252729    bool fPaused = !!pVM->tm.s.cVirtualTicking;
    27262730    if (fPaused) /** @todo this isn't really working, but wtf. */
     
    27342738    if (fPaused)
    27352739        TMR3NotifyResume(pVM, pVCpu);
    2736     tmTimerUnlock(pVM);
     2740    TM_UNLOCK_TIMERS(pVM);
    27372741    return VINF_SUCCESS;
    27382742}
     
    29632967                                                "HzHint",
    29642968                                                "State");
    2965     tmTimerLock(pVM);
     2969    TM_LOCK_TIMERS(pVM);
    29662970    for (PTMTIMERR3 pTimer = pVM->tm.s.pCreated; pTimer; pTimer = pTimer->pBigNext)
    29672971    {
     
    29792983                        pTimer->pszDesc);
    29802984    }
    2981     tmTimerUnlock(pVM);
     2985    TM_UNLOCK_TIMERS(pVM);
    29822986}
    29832987
     
    30073011    for (unsigned iQueue = 0; iQueue < TMCLOCK_MAX; iQueue++)
    30083012    {
    3009         tmTimerLock(pVM);
     3013        TM_LOCK_TIMERS(pVM);
    30103014        for (PTMTIMERR3 pTimer = TMTIMER_GET_HEAD(&pVM->tm.s.paTimerQueuesR3[iQueue]);
    30113015             pTimer;
     
    30253029                            pTimer->pszDesc);
    30263030        }
    3027         tmTimerUnlock(pVM);
     3031        TM_UNLOCK_TIMERS(pVM);
    30283032    }
    30293033}
  • trunk/src/VBox/VMM/include/TMInternal.h

    r37517 r37527  
    722722typedef TMCPU *PTMCPU;
    723723
    724 #if 0 /* enable this to rule out locking bugs on single cpu guests. */
    725 # define tmTimerLock(pVM)                VINF_SUCCESS
    726 # define tmTimerTryLock(pVM)             VINF_SUCCESS
    727 # define tmTimerUnlock(pVM)              ((void)0)
    728 # define tmVirtualSyncLock(pVM)     VINF_SUCCESS
    729 # define tmVirtualSyncTryLock(pVM)  VINF_SUCCESS
    730 # define tmVirtualSyncUnlock(pVM)   ((void)0)
    731 # define TM_ASSERT_LOCK(pVM)        VM_ASSERT_EMT(pVM)
    732 #else
    733 int                     tmTimerLock(PVM pVM);
    734 int                     tmTimerTryLock(PVM pVM);
    735 void                    tmTimerUnlock(PVM pVM);
    736 /** Checks that the caller owns the timer lock.  */
    737 #define TM_ASSERT_LOCK(pVM) Assert(PDMCritSectIsOwner(&pVM->tm.s.TimerCritSect))
    738 int                     tmVirtualSyncLock(PVM pVM);
    739 int                     tmVirtualSyncTryLock(PVM pVM);
    740 void                    tmVirtualSyncUnlock(PVM pVM);
    741 #endif
    742 
    743724const char             *tmTimerState(TMTIMERSTATE enmState);
    744725void                    tmTimerQueueSchedule(PVM pVM, PTMTIMERQUEUE pQueue);
     
    756737
    757738
     739/**
     740 * Try take the timer lock, wait in ring-3 return VERR_SEM_BUSY in R0/RC.
     741 *
     742 * @retval  VINF_SUCCESS on success (always in ring-3).
     743 * @retval  VERR_SEM_BUSY in RC and R0 if the semaphore is busy.
     744 *
     745 * @param   a_pVM       The VM handle.
     746 *
     747 * @remarks The virtual sync timer queue requires the virtual sync lock.
     748 */
     749#define TM_LOCK_TIMERS(a_pVM)       PDMCritSectEnter(&(a_pVM)->tm.s.TimerCritSect, VERR_SEM_BUSY)
     750
     751/**
     752 * Try take the timer lock, no waiting.
     753 *
     754 * @retval  VINF_SUCCESS on success.
     755 * @retval  VERR_SEM_BUSY if busy.
     756 *
     757 * @param   a_pVM       The VM handle.
     758 *
     759 * @remarks The virtual sync timer queue requires the virtual sync lock.
     760 */
     761#define TM_TRY_LOCK_TIMERS(a_pVM)   PDMCritSectTryEnter(&(a_pVM)->tm.s.TimerCritSect)
     762
     763/** Lock the timers (sans the virtual sync queue). */
     764#define TM_UNLOCK_TIMERS(a_pVM)     do { PDMCritSectLeave(&(a_pVM)->tm.s.TimerCritSect); } while (0)
     765
     766/** Checks that the caller owns the timer lock.  */
     767#define TM_ASSERT_TIMER_LOCK_OWNERSHIP(a_pVM) \
     768    Assert(PDMCritSectIsOwner(&(a_pVM)->tm.s.TimerCritSect))
     769
     770
    758771/** @} */
    759772
Note: See TracChangeset for help on using the changeset viewer.

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