Changeset 32648 in vbox for trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
- Timestamp:
- Sep 20, 2010 4:17:03 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
r32611 r32648 28 28 * Header Files * 29 29 *******************************************************************************/ 30 #include <iprt/mem.h> 31 30 #include <iprt/timer.h> 31 32 #include <iprt/asm.h> 32 33 #include <iprt/err.h> 33 34 #include <iprt/param.h> 35 #include <iprt/string.h> 36 #include <iprt/thread.h> 34 37 #include <iprt/time.h> 35 #include <iprt/string.h>36 38 #include <VBox/sup.h> 37 39 #include "tstRTR0Timer.h" 38 40 #include "tstRTR0Common.h" 41 42 /******************************************************************************* 43 * Structures and Typedefs * 44 *******************************************************************************/ 45 typedef struct 46 { 47 /** Array of nano second timestamp of the first few shots. */ 48 uint64_t volatile aShotNsTSes[10]; 49 /** The number of shots. */ 50 uint32_t volatile cShots; 51 } TSTRTR0TIMERS1; 52 typedef TSTRTR0TIMERS1 *PTSTRTR0TIMERS1; 53 54 55 /** 56 * Callback which increments restarts a timer once. 57 * 58 * @param pTimer The timer. 59 * @param iTick The current tick. 60 * @param pvUser The user argument. 61 */ 62 static DECLCALLBACK(void) tstRTR0TimerCallbackRestartOnce(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 63 { 64 PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser; 65 uint32_t iShot = ASMAtomicIncU32(&pState->cShots); 66 67 if (iShot <= RT_ELEMENTS(pState->aShotNsTSes)) 68 pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS(); 69 70 if (iShot == 1) 71 RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 10000000 /* 10ms */), VINF_SUCCESS); 72 } 73 74 75 /** 76 * Callback which increments a 32-bit counter. 77 * 78 * @param pTimer The timer. 79 * @param iTick The current tick. 80 * @param pvUser The user argument. 81 */ 82 static DECLCALLBACK(void) tstRTR0TimerCallbackU32Counter(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 83 { 84 PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser; 85 uint32_t iShot = ASMAtomicIncU32(&pState->cShots); 86 87 if (iShot <= RT_ELEMENTS(pState->aShotNsTSes)) 88 pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS(); 89 } 90 91 92 /** 93 * Checks that the interval between two timer shots are within the specified 94 * range. 95 * 96 * @returns 0 if ok, 1 if bad. 97 * @param iShot The shot number (for bitching). 98 * @param uPrevTS The time stamp of the previous shot (ns). 99 * @param uThisTS The timer stamp of this shot (ns). 100 * @param uMin The minimum interval (ns). 101 * @param uMax The maximum interval (ns). 102 */ 103 static int tstRTR0TimerCheckShotInterval(uint32_t iShot, uint64_t uPrevTS, uint64_t uThisTS, uint32_t uMin, uint32_t uMax) 104 { 105 uint64_t uDelta = uThisTS - uPrevTS; 106 RTR0TESTR0_CHECK_MSG_RET(uDelta >= uMin, ("iShot=%u uDelta=%lld uMin=%u\n", iShot, uDelta, uMin), 1); 107 RTR0TESTR0_CHECK_MSG_RET(uDelta <= uMax, ("iShot=%u uDelta=%lld uMax=%u\n", iShot, uDelta, uMax), 1); 108 return 0; 109 } 110 111 112 /** 113 * Checks that the interval between timer shots are within a certain range. 114 * 115 * @returns Number of violations (i.e. 0 is ok). 116 * @param pState The state. 117 * @param uStartNsTS The start time stamp (ns). 118 * @param uMin The minimum interval (ns). 119 * @param uMax The maximum interval (ns). 120 */ 121 static int tstRTR0TimerCheckShotIntervals(PTSTRTR0TIMERS1 pState, uint64_t uStartNsTS, uint32_t uMin, uint32_t uMax) 122 { 123 uint64_t uMaxDelta = 0; 124 uint64_t uMinDelta = UINT64_MAX; 125 uint32_t cBadShots = 0; 126 uint32_t cShots = pState->cShots; 127 uint64_t uPrevTS = uStartNsTS; 128 for (uint32_t iShot = 0; iShot < cShots; iShot++) 129 { 130 uint64_t uThisTS = pState->aShotNsTSes[iShot]; 131 uint64_t uDelta = uThisTS - uPrevTS; 132 if (uDelta > uMaxDelta) 133 uMaxDelta = uDelta; 134 if (uDelta < uMinDelta) 135 uMinDelta = uDelta; 136 cBadShots += !(uDelta >= uMin && uDelta <= uMax); 137 138 RTR0TESTR0_CHECK_MSG(uDelta >= uMin, ("iShot=%u uDelta=%lld uMin=%u\n", iShot, uDelta, uMin)); 139 RTR0TESTR0_CHECK_MSG(uDelta <= uMax, ("iShot=%u uDelta=%lld uMax=%u\n", iShot, uDelta, uMax)); 140 141 uPrevTS = uThisTS; 142 } 143 144 RTR0TestR0Info("uMaxDelta=%llu uMinDelta=%llu\n", uMaxDelta, uMinDelta); 145 return cBadShots; 146 } 39 147 40 148 … … 50 158 uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr) 51 159 { 52 if (!VALID_PTR(pReqHdr)) 53 return VERR_INVALID_PARAMETER; 54 char *pszErr = (char *)(pReqHdr + 1); 55 size_t cchErr = pReqHdr->cbReq - sizeof(*pReqHdr); 56 if (cchErr < 32 || cchErr >= 0x10000) 57 return VERR_INVALID_PARAMETER; 58 *pszErr = '\0'; 59 160 RTR0TESTR0_SRV_REQ_PROLOG_RET(pReqHdr); 60 161 if (u64Arg) 61 162 return VERR_INVALID_PARAMETER; … … 64 165 * The big switch. 65 166 */ 167 TSTRTR0TIMERS1 State; 66 168 switch (uOperation) 67 169 { 68 case TSTRTR0TIMER_SANITY_OK: 69 break; 70 71 case TSTRTR0TIMER_SANITY_FAILURE: 72 RTStrPrintf(pszErr, cchErr, "!42failure42%1024s", ""); 73 break; 74 75 #if 0 76 case TSTRTR0TIMER_BASIC: 170 RTR0TESTR0_IMPLEMENT_SANITY_CASES(); 171 RTR0TESTR0_IMPLEMENT_DEFAULT_CASE(uOperation); 172 173 case TSTRTR0TIMER_ONE_SHOT_BASIC: 174 case TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES: 77 175 { 78 int rc = RTR0MemUserCopyFrom(pbKrnlBuf, R3Ptr, PAGE_SIZE); 79 if (rc == VINF_SUCCESS) 176 /* Create a one-shot timer and take one shot. */ 177 PRTTIMER pTimer; 178 uint32_t fFlags = uOperation != TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES ? RTTIMER_FLAGS_HIGH_RES : 0; 179 RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackU32Counter, &State), 180 VINF_SUCCESS); 181 182 do /* break loop */ 80 183 { 81 rc = RTR0MemUserCopyTo(R3Ptr, pbKrnlBuf, PAGE_SIZE); 82 if (rc == VINF_SUCCESS) 83 { 84 if (RTR0MemUserIsValidAddr(R3Ptr)) 85 { 86 if (RTR0MemKernelIsValidAddr(pbKrnlBuf)) 87 { 88 if (RTR0MemAreKrnlAndUsrDifferent()) 89 { 90 RTStrPrintf(pszErr, cchErr, "RTR0MemAreKrnlAndUsrDifferent returns true"); 91 if (!RTR0MemUserIsValidAddr((uintptr_t)pbKrnlBuf)) 92 { 93 if (!RTR0MemKernelIsValidAddr((void *)R3Ptr)) 94 { 95 /* done */ 96 } 97 else 98 RTStrPrintf(pszErr, cchErr, "! #5 - RTR0MemKernelIsValidAddr -> true, expected false"); 99 } 100 else 101 RTStrPrintf(pszErr, cchErr, "! #5 - RTR0MemUserIsValidAddr -> true, expected false"); 102 } 103 else 104 RTStrPrintf(pszErr, cchErr, "RTR0MemAreKrnlAndUsrDifferent returns false"); 105 } 106 else 107 RTStrPrintf(pszErr, cchErr, "! #4 - RTR0MemKernelIsValidAddr -> false, expected true"); 108 } 109 else 110 RTStrPrintf(pszErr, cchErr, "! #3 - RTR0MemUserIsValidAddr -> false, expected true"); 111 } 112 else 113 RTStrPrintf(pszErr, cchErr, "! #2 - RTR0MemUserCopyTo -> %Rrc expected %Rrc", rc, VINF_SUCCESS); 114 } 115 else 116 RTStrPrintf(pszErr, cchErr, "! #1 - RTR0MemUserCopyFrom -> %Rrc expected %Rrc", rc, VINF_SUCCESS); 184 RT_ZERO(State); 185 RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS); 186 for (uint32_t i = 0; i < 1000 && !ASMAtomicUoReadU32(&State.cShots); i++) 187 RTThreadSleep(5); 188 RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots)); 189 190 /* check that it is restartable. */ 191 RT_ZERO(State); 192 RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS); 193 for (uint32_t i = 0; i < 1000 && !ASMAtomicUoReadU32(&State.cShots); i++) 194 RTThreadSleep(5); 195 RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots)); 196 197 /* check that it respects the timeout value and can be cancelled. */ 198 RT_ZERO(State); 199 RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 5*UINT64_C(1000000000)), VINF_SUCCESS); 200 RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VINF_SUCCESS); 201 RTThreadSleep(1); 202 RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 0, ("cShots=%u\n", State.cShots)); 203 204 /* Check some double starts and stops (shall not assert). */ 205 RT_ZERO(State); 206 RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 5*UINT64_C(1000000000)), VINF_SUCCESS); 207 RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 0), VERR_TIMER_ACTIVE); 208 RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VINF_SUCCESS); 209 RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VERR_TIMER_SUSPENDED); 210 RTThreadSleep(1); 211 RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 0, ("cShots=%u\n", State.cShots)); 212 } while (0); 213 RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS); 214 RTR0TESTR0_CHECK_RC(RTTimerDestroy(NULL), VINF_SUCCESS); 117 215 break; 118 216 } 119 217 120 case TSTRTR0TIMER_GOOD: 218 #if 1 /* might have to disable this for some host... */ 219 case TSTRTR0TIMER_ONE_SHOT_RESTART: 220 case TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES: 121 221 { 122 for (unsigned off = 0; off < 16 && !*pszErr; off++) 123 for (unsigned cb = 0; cb < PAGE_SIZE - 16; cb++) 124 TEST_OFF_SIZE(off, cb, VINF_SUCCESS); 125 break; 126 } 127 128 case TSTRTR0TIMER_BAD: 129 { 130 for (unsigned off = 0; off < 16 && !*pszErr; off++) 131 for (unsigned cb = 0; cb < PAGE_SIZE - 16; cb++) 132 TEST_OFF_SIZE(off, cb, cb > 0 ? VERR_ACCESS_DENIED : VINF_SUCCESS); 133 break; 134 } 135 136 case TSTRTR0TIMER_INVALID_ADDRESS: 137 { 138 if ( !RTR0MemUserIsValidAddr(R3Ptr) 139 && RTR0MemKernelIsValidAddr((void *)R3Ptr)) 222 /* Create a one-shot timer and restart it in the callback handler. */ 223 PRTTIMER pTimer; 224 uint32_t fFlags = uOperation != TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES ? RTTIMER_FLAGS_HIGH_RES : 0; 225 RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackRestartOnce, &State), 226 VINF_SUCCESS); 227 228 do /* break loop */ 140 229 { 141 for (unsigned off = 0; off < 16 && !*pszErr; off++) 142 for (unsigned cb = 0; cb < PAGE_SIZE - 16; cb++) 143 TEST_OFF_SIZE(off, cb, cb > 0 ? VERR_ACCESS_DENIED : VINF_SUCCESS); /* ... */ 144 } 145 else 146 RTStrPrintf(pszErr, cchErr, "RTR0MemUserIsValidAddr returns true"); 230 RT_ZERO(State); 231 RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS); 232 for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 2; i++) 233 RTThreadSleep(5); 234 RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 2, ("cShots=%u\n", State.cShots)); 235 } while (0); 236 RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS); 147 237 break; 148 238 } 149 239 #endif 150 240 151 default: 152 RTStrPrintf(pszErr, cchErr, "!Unknown test #%d", uOperation); 241 case TSTRTR0TIMER_PERIODIC_BASIC: 242 case TSTRTR0TIMER_PERIODIC_BASIC_HIRES: 243 { 244 /* Create a periodic timer running at 10 HZ. */ 245 uint32_t const u10HzAsNs = 100000000; 246 uint32_t const u10HzAsNsMin = u10HzAsNs - u10HzAsNs / 2; 247 uint32_t const u10HzAsNsMax = u10HzAsNs + u10HzAsNs / 2; 248 PRTTIMER pTimer; 249 uint32_t fFlags = uOperation != TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES ? RTTIMER_FLAGS_HIGH_RES : 0; 250 RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, u10HzAsNs, fFlags, tstRTR0TimerCallbackU32Counter, &State), 251 VINF_SUCCESS); 252 253 for (uint32_t iTest = 0; iTest < 2; iTest++) 254 { 255 RT_ZERO(State); 256 uint64_t uStartNsTS = RTTimeSystemNanoTS(); 257 RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, u10HzAsNs), VINF_SUCCESS); 258 for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 10; i++) 259 RTThreadSleep(10); 260 RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS); 261 RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 10, ("cShots=%u\n", State.cShots)); 262 if (tstRTR0TimerCheckShotIntervals(&State, uStartNsTS, u10HzAsNsMin, u10HzAsNsMax)) 263 break; 264 } 265 RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS); 266 RTR0TESTR0_CHECK_RC(RTTimerDestroy(NULL), VINF_SUCCESS); 153 267 break; 268 } 154 269 } 155 270 271 RTR0TESTR0_SRV_REQ_EPILOG(pReqHdr); 156 272 /* The error indicator is the '!' in the message buffer. */ 157 273 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.