儲存庫 vbox 的更動 89762
- 時間撮記:
- 2021-6-17 上午09:39:11 (4 年 以前)
- svn:sync-xref-src-repo-rev:
- 145213
- 位置:
- trunk/src/VBox/Runtime
- 檔案:
-
- 修改 3 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Runtime/Makefile.kmk
r88215 r89762 934 934 generic/RTSemMutexRequest-generic.cpp \ 935 935 generic/RTSemMutexRequestDebug-generic.cpp \ 936 generic/RTTimerCreate-generic.cpp \ 936 937 generic/RTThreadSetAffinityToCpu-generic.cpp \ 937 938 generic/mppresent-generic-online.cpp \ -
trunk/src/VBox/Runtime/r3/win/timer-win.cpp
r83739 r89762 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 26 26 27 27 28 /* Which code to use is determined here...29 *30 * The default is to use wait on NT timers directly with no APC since this31 * is supposed to give the shortest kernel code paths.32 *33 * The USE_APC variation will do as above except that an APC routine is34 * handling the callback action.35 *36 * The USE_WINMM version will use the NT timer wrappers in WinMM which may37 * result in some 0.1% better correctness in number of delivered ticks. However,38 * this codepath have more overhead (it uses APC among other things), and I'm not39 * quite sure if it's actually any more correct.40 *41 * The USE_CATCH_UP will play catch up when the timer lags behind. However this42 * requires a monotonous time source.43 *44 * The default mode which we are using is using relative periods of time and thus45 * will never suffer from errors in the time source. Neither will it try catch up46 * missed ticks. This suits our current purposes best I'd say.47 */48 #undef USE_APC49 #undef USE_WINMM50 #undef USE_CATCH_UP51 52 53 28 /********************************************************************************************************************************* 54 29 * Header Files * … … 89 64 * This is RTTIMER_MAGIC, but changes to something else before the timer 90 65 * is destroyed to indicate clearly that thread should exit. */ 91 volatile uint32_t u32Magic; 66 uint32_t volatile u32Magic; 67 /** Flag indicating the timer is suspended. */ 68 bool volatile fSuspended; 69 /** Flag indicating that the timer has been destroyed. */ 70 bool volatile fDestroyed; 92 71 /** User argument. */ 93 72 void *pvUser; … … 96 75 /** The current tick. */ 97 76 uint64_t iTick; 98 /** The interval. */ 99 unsigned uMilliesInterval; 100 #ifdef USE_WINMM 101 /** Win32 timer id. */ 102 UINT TimerId; 103 #else 77 /** The timer interval. 0 if one-shot. */ 78 uint64_t u64NanoInterval; 79 /** The first shot interval. 0 if ASAP. */ 80 uint64_t volatile u64NanoFirst; 104 81 /** Time handle. */ 105 82 HANDLE hTimer; 106 # ifdef USE_APC107 /** Handle to wait on. */108 HANDLE hevWait;109 # endif110 83 /** USE_CATCH_UP: ns time of the next tick. 111 84 * !USE_CATCH_UP: -uMilliesInterval * 10000 */ … … 113 86 /** The thread handle of the timer thread. */ 114 87 RTTHREAD Thread; 88 /** Event semaphore on which the thread is blocked. */ 89 RTSEMEVENT Event; 115 90 /** The error/status of the timer. 116 91 * Initially -1, set to 0 when the timer have been successfully started, and 117 92 * to errno on failure in starting the timer. */ 118 93 volatile int iError; 119 #endif120 94 } RTTIMER; 121 95 122 96 123 124 #ifdef USE_WINMM125 /**126 * Win32 callback wrapper.127 */128 static void CALLBACK rttimerCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)129 {130 PRTTIMER pTimer = (PRTTIMER)(void *)dwUser;131 Assert(pTimer->TimerId == uTimerID);132 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick);133 NOREF(uMsg); NOREF(dw1); NOREF(dw2); NOREF(uTimerID);134 }135 #else /* !USE_WINMM */136 137 #ifdef USE_APC138 /**139 * Async callback.140 *141 * @param lpArgToCompletionRoutine Pointer to our timer structure.142 */143 VOID CALLBACK rttimerAPCProc(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)144 {145 PRTTIMER pTimer = (PRTTIMER)lpArgToCompletionRoutine;146 147 /*148 * Check if we're begin destroyed.149 */150 if (pTimer->u32Magic != RTTIMER_MAGIC)151 return;152 153 /*154 * Callback the handler.155 */156 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick);157 158 /*159 * Rearm the timer handler.160 */161 #ifdef USE_CATCH_UP162 pTimer->llNext.QuadPart += (int64_t)pTimer->uMilliesInterval * 10000;163 LARGE_INTEGER ll;164 ll.QuadPart = RTTimeNanoTS() - pTimer->llNext.QuadPart;165 if (ll.QuadPart < -500000)166 ll.QuadPart = ll.QuadPart / 100;167 else168 ll.QuadPart = -500000 / 100; /* need to catch up, do a minimum wait of 0.5ms. */169 #else170 LARGE_INTEGER ll = pTimer->llNext;171 #endif172 BOOL frc = SetWaitableTimer(pTimer->hTimer, &ll, 0, rttimerAPCProc, pTimer, FALSE);173 AssertMsg(frc || pTimer->u32Magic != RTTIMER_MAGIC, ("last error %d\n", GetLastError()));174 }175 #endif /* USE_APC */176 97 177 98 /** 178 99 * Timer thread. 179 100 */ 180 static DECLCALLBACK(int) rttimerCallback(RTTHREAD Thread, void *pvArg)101 static DECLCALLBACK(int) rttimerCallback(RTTHREAD hThreadSelf, void *pvArg) 181 102 { 182 103 PRTTIMER pTimer = (PRTTIMER)(void *)pvArg; … … 186 107 * Bounce our priority up quite a bit. 187 108 */ 188 if ( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) 189 /*&& !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)*/) 109 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) 190 110 { 191 111 int rc = GetLastError(); 192 112 AssertMsgFailed(("Failed to set priority class lasterror %d.\n", rc)); 193 113 pTimer->iError = RTErrConvertFromWin32(rc); 114 RTThreadUserSignal(hThreadSelf); 194 115 return rc; 195 116 } 196 117 197 118 /* 198 * Start the waitable timer. 199 */ 200 201 #ifdef USE_CATCH_UP 202 const int64_t NSInterval = (int64_t)pTimer->uMilliesInterval * 1000000; 203 pTimer->llNext.QuadPart = RTTimeNanoTS() + NSInterval; 204 #else 205 pTimer->llNext.QuadPart = -(int64_t)pTimer->uMilliesInterval * 10000; 206 #endif 207 LARGE_INTEGER ll; 208 ll.QuadPart = -(int64_t)pTimer->uMilliesInterval * 10000; 209 #ifdef USE_APC 210 if (!SetWaitableTimer(pTimer->hTimer, &ll, 0, rttimerAPCProc, pTimer, FALSE)) 211 #else 212 if (!SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE)) 213 #endif 214 { 215 int rc = GetLastError(); 216 AssertMsgFailed(("Failed to set timer, lasterr %d.\n", rc)); 217 pTimer->iError = RTErrConvertFromWin32(rc); 218 RTThreadUserSignal(Thread); 219 return rc; 220 } 221 222 /* 223 * Wait for the semaphore to be posted. 224 */ 225 RTThreadUserSignal(Thread); 226 for (;pTimer->u32Magic == RTTIMER_MAGIC;) 227 { 228 #ifdef USE_APC 229 int rc = WaitForSingleObjectEx(pTimer->hevWait, INFINITE, TRUE); 230 if (rc != WAIT_OBJECT_0 && rc != WAIT_IO_COMPLETION) 231 #else 232 int rc = WaitForSingleObjectEx(pTimer->hTimer, INFINITE, FALSE); 233 if (pTimer->u32Magic != RTTIMER_MAGIC) 234 break; 235 if (rc == WAIT_OBJECT_0) 236 { 237 /* 238 * Callback the handler. 239 */ 240 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick); 241 242 /* 243 * Rearm the timer handler. 244 */ 245 # ifdef USE_CATCH_UP 246 pTimer->llNext.QuadPart += NSInterval; 247 ll.QuadPart = RTTimeNanoTS() - pTimer->llNext.QuadPart; 248 if (ll.QuadPart < -500000) 249 ll.QuadPart = ll.QuadPart / 100; 119 * The work loop. 120 */ 121 RTThreadUserSignal(hThreadSelf); 122 123 while ( !pTimer->fDestroyed 124 && pTimer->u32Magic == RTTIMER_MAGIC) 125 { 126 /* 127 * Wait for a start or destroy event. 128 */ 129 if (pTimer->fSuspended) 130 { 131 int rc = RTSemEventWait(pTimer->Event, RT_INDEFINITE_WAIT); 132 if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED) 133 { 134 AssertRC(rc); 135 if (pTimer->fDestroyed) 136 continue; 137 RTThreadSleep(1000); /* Don't cause trouble! */ 138 } 139 if ( pTimer->fSuspended 140 || pTimer->fDestroyed) 141 continue; 142 } 143 144 /* 145 * Start the waitable timer. 146 */ 147 pTimer->llNext.QuadPart = -(int64_t)pTimer->u64NanoInterval / 100; 148 LARGE_INTEGER ll; 149 if (pTimer->u64NanoFirst) 150 { 151 GetSystemTimeAsFileTime((LPFILETIME)&ll); 152 ll.QuadPart += pTimer->u64NanoFirst / 100; 153 pTimer->u64NanoFirst = 0; 154 } 155 else 156 ll.QuadPart = -(int64_t)pTimer->u64NanoInterval / 100; 157 if (!SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE)) 158 { 159 ASMAtomicXchgBool(&pTimer->fSuspended, true); 160 int rc = GetLastError(); 161 AssertMsgFailed(("Failed to set timer, lasterr %d.\n", rc)); 162 pTimer->iError = RTErrConvertFromWin32(rc); 163 RTThreadUserSignal(hThreadSelf); 164 continue; /* back to suspended mode. */ 165 } 166 pTimer->iError = 0; 167 RTThreadUserSignal(hThreadSelf); 168 169 /* 170 * Timer Service Loop. 171 */ 172 do 173 { 174 int rc = WaitForSingleObjectEx(pTimer->hTimer, INFINITE, FALSE); 175 if (pTimer->u32Magic != RTTIMER_MAGIC) 176 break; 177 if (rc == WAIT_OBJECT_0) 178 { 179 /* 180 * Callback the handler. 181 */ 182 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick); 183 184 /* 185 * Rearm the timer handler. 186 */ 187 ll = pTimer->llNext; 188 BOOL fRc = SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE); 189 AssertMsg(fRc || pTimer->u32Magic != RTTIMER_MAGIC, ("last error %d\n", GetLastError())); NOREF(fRc); 190 } 250 191 else 251 ll.QuadPart = -500000 / 100; /* need to catch up, do a minimum wait of 0.5ms. */ 252 # else 253 ll = pTimer->llNext; 254 # endif 255 BOOL fRc = SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE); 256 AssertMsg(fRc || pTimer->u32Magic != RTTIMER_MAGIC, ("last error %d\n", GetLastError())); NOREF(fRc); 257 } 258 else 259 #endif 260 { 261 /* 262 * We failed during wait, so just signal the destructor and exit. 263 */ 264 int rc2 = GetLastError(); 265 RTThreadUserSignal(Thread); 266 AssertMsgFailed(("Wait on hTimer failed, rc=%d lasterr=%d\n", rc, rc2)); NOREF(rc2); 267 return -1; 192 { 193 /* 194 * We failed during wait, so just signal the destructor and exit. 195 */ 196 int rc2 = GetLastError(); 197 RTThreadUserSignal(hThreadSelf); 198 AssertMsgFailed(("Wait on hTimer failed, rc=%d lasterr=%d\n", rc, rc2)); NOREF(rc2); 199 return -1; 200 } 201 } while (RT_LIKELY( !pTimer->fSuspended 202 && !pTimer->fDestroyed 203 && pTimer->u32Magic == RTTIMER_MAGIC)); 204 205 /* 206 * Disable the timer. 207 */ 208 int rc = CancelWaitableTimer (pTimer->hTimer); 209 AssertMsg(rc, ("CancelWaitableTimer lasterr=%d\n", GetLastError())); 210 211 /* 212 * ACK any pending suspend request. 213 */ 214 if (!pTimer->fDestroyed) 215 { 216 pTimer->iError = 0; 217 RTThreadUserSignal(hThreadSelf); 268 218 } 269 219 } … … 272 222 * Exit. 273 223 */ 274 RTThreadUserSignal(Thread); 275 return 0; 276 } 277 #endif /* !USE_WINMM */ 278 279 280 RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser) 281 { 282 #ifndef USE_WINMM 224 pTimer->iError = 0; 225 RTThreadUserSignal(hThreadSelf); 226 return VINF_SUCCESS; 227 } 228 229 230 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) 231 { 232 /* 233 * We don't support the fancy MP features. 234 */ 235 if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) 236 return VERR_NOT_SUPPORTED; 237 283 238 /* 284 239 * On windows we'll have to set the timer resolution before … … 288 243 ULONG ulMin = UINT32_MAX; 289 244 ULONG ulCur = UINT32_MAX; 245 ULONG ulReq = (ULONG)(u64NanoInterval / 100); 290 246 NtQueryTimerResolution(&ulMax, &ulMin, &ulCur); 291 247 Log(("NtQueryTimerResolution -> ulMax=%lu00ns ulMin=%lu00ns ulCur=%lu00ns\n", ulMax, ulMin, ulCur)); 292 if (ulCur > ulMin && ulCur > 10000 /* = 1ms */) 293 { 294 if (NtSetTimerResolution(10000, TRUE, &ulCur) >= 0) 248 if (ulCur > ulMin && ulCur > ulReq) 249 { 250 ulReq = RT_MIN(ulMin, ulReq); 251 if (NtSetTimerResolution(ulReq, TRUE, &ulCur) >= 0) 252 Log(("Changed timer resolution to %lu*100ns.\n", ulReq)); 253 else if (NtSetTimerResolution(10000, TRUE, &ulCur) >= 0) 295 254 Log(("Changed timer resolution to 1ms.\n")); 296 255 else if (NtSetTimerResolution(20000, TRUE, &ulCur) >= 0) … … 306 265 } 307 266 } 308 #endif /* !USE_WINN */309 267 310 268 /* … … 315 273 if (pTimer) 316 274 { 317 pTimer->u32Magic = RTTIMER_MAGIC; 318 pTimer->pvUser = pvUser; 319 pTimer->pfnTimer = pfnTimer; 320 pTimer->iTick = 0; 321 pTimer->uMilliesInterval = uMilliesInterval; 322 #ifdef USE_WINMM 323 /* sync kill doesn't work. */ 324 pTimer->TimerId = timeSetEvent(uMilliesInterval, 0, rttimerCallback, (DWORD_PTR)pTimer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); 325 if (pTimer->TimerId) 326 { 327 ULONG ulMax = UINT32_MAX; 328 ULONG ulMin = UINT32_MAX; 329 ULONG ulCur = UINT32_MAX; 330 NtQueryTimerResolution(&ulMax, &ulMin, &ulCur); 331 Log(("NtQueryTimerResolution -> ulMax=%lu00ns ulMin=%lu00ns ulCur=%lu00ns\n", ulMax, ulMin, ulCur)); 332 333 *ppTimer = pTimer; 334 return VINF_SUCCESS; 335 } 336 rc = VERR_INVALID_PARAMETER; 337 338 #else /* !USE_WINMM */ 339 340 /* 341 * Create Win32 event semaphore. 342 */ 343 pTimer->iError = 0; 344 pTimer->hTimer = CreateWaitableTimer(NULL, TRUE, NULL); 345 if (pTimer->hTimer) 346 { 347 #ifdef USE_APC 275 pTimer->u32Magic = RTTIMER_MAGIC; 276 pTimer->fSuspended = true; 277 pTimer->fDestroyed = false; 278 pTimer->Thread = NIL_RTTHREAD; 279 pTimer->pfnTimer = pfnTimer; 280 pTimer->pvUser = pvUser; 281 pTimer->u64NanoInterval = u64NanoInterval; 282 283 rc = RTSemEventCreate(&pTimer->Event); 284 AssertRC(rc); 285 if (RT_SUCCESS(rc)) 286 { 348 287 /* 349 * Create wait semaphore.288 * Create Win32 event semaphore. 350 289 */ 351 pTimer-> hevWait = CreateEvent(NULL, FALSE, FALSE, NULL);352 if (pTimer->hevWait)353 #endif 290 pTimer->iError = 0; 291 pTimer->hTimer = CreateWaitableTimer(NULL, TRUE, NULL); 292 if (pTimer->hTimer) 354 293 { 355 294 /* … … 373 312 } 374 313 } 375 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 376 RTThreadWait(pTimer->Thread, 250, NULL); 314 315 /* bail out */ 316 ASMAtomicXchgBool(&pTimer->fDestroyed, true); 317 ASMAtomicXchgU32(&pTimer->u32Magic, ~RTTIMER_MAGIC); 318 RTThreadWait(pTimer->Thread, 45*1000, NULL); 377 319 CancelWaitableTimer(pTimer->hTimer); 378 320 } 379 #ifdef USE_APC 380 CloseHandle(pTimer->hevWait); 381 #endif 321 CloseHandle(pTimer->hTimer); 382 322 } 383 CloseHandle(pTimer->hTimer); 384 } 385 #endif /* !USE_WINMM */ 386 387 AssertMsgFailed(("Failed to create timer uMilliesInterval=%d. rc=%d\n", uMilliesInterval, rc)); 323 RTSemEventDestroy(pTimer->Event); 324 pTimer->Event = NIL_RTSEMEVENT; 325 } 326 388 327 RTMemFree(pTimer); 389 328 } … … 400 339 return VINF_SUCCESS; 401 340 402 /* 403 * Validate handle first. 404 */ 405 int rc; 406 if ( VALID_PTR(pTimer) 407 && pTimer->u32Magic == RTTIMER_MAGIC) 408 { 409 #ifdef USE_WINMM 410 /* 411 * Kill the timer and exit. 412 */ 413 rc = timeKillEvent(pTimer->TimerId); 414 AssertMsg(rc == TIMERR_NOERROR, ("timeKillEvent -> %d\n", rc)); 415 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 416 RTThreadSleep(1); 417 418 #else /* !USE_WINMM */ 419 420 /* 421 * Signal that we want the thread to exit. 422 */ 423 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 424 #ifdef USE_APC 425 SetEvent(pTimer->hevWait); 426 CloseHandle(pTimer->hevWait); 427 rc = CancelWaitableTimer(pTimer->hTimer); 428 AssertMsg(rc, ("CancelWaitableTimer lasterr=%d\n", GetLastError())); 429 #else 341 int rc = VINF_SUCCESS; 342 AssertPtrReturn(pTimer, VERR_INVALID_HANDLE); 343 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 344 AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR); 345 346 /* 347 * Signal that we want the thread to exit. 348 */ 349 ASMAtomicWriteBool(&pTimer->fDestroyed, true); 350 ASMAtomicWriteU32(&pTimer->u32Magic, ~RTTIMER_MAGIC); 351 352 /* 353 * Suspend the timer if it's running. 354 */ 355 if (!pTimer->fSuspended) 356 { 430 357 LARGE_INTEGER ll = {0}; 431 358 ll.LowPart = 100; 432 359 rc = SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE); 433 360 AssertMsg(rc, ("CancelWaitableTimer lasterr=%d\n", GetLastError())); 434 #endif 435 436 /*437 * Wait for the thread to exit.438 * And if it don't wanna exit, we'll get kill it. 439 */440 rc = RTThreadWait(pTimer->Thread, 1000, NULL);441 if (RT_FAILURE(rc))442 TerminateThread((HANDLE)RTThreadGetNative(pTimer->Thread), UINT32_MAX);443 444 /*445 * Free resource.446 */ 447 rc = CloseHandle(pTimer->hTimer);448 AssertMsg(rc, ("CloseHandle lasterr=%d\n", GetLastError()));449 450 #endif /* !USE_WINMM */ 451 RTMemFree(pTimer);452 return rc; 453 }454 455 rc = VERR_INVALID_HANDLE; 456 AssertMsgFailed(("Failed to destroy timer %p. rc=%d\n", pTimer, rc));361 } 362 363 rc = RTSemEventSignal(pTimer->Event); 364 AssertRC(rc); 365 366 /* 367 * Wait for the thread to exit. 368 * And if it don't wanna exit, we'll get kill it. 369 */ 370 rc = RTThreadWait(pTimer->Thread, 30 * 1000, NULL); 371 if (RT_FAILURE(rc)) 372 TerminateThread((HANDLE)RTThreadGetNative(pTimer->Thread), UINT32_MAX); 373 374 /* 375 * Free resource. 376 */ 377 rc = CloseHandle(pTimer->hTimer); 378 AssertMsg(rc, ("CloseHandle lasterr=%d\n", GetLastError())); 379 380 RTSemEventDestroy(pTimer->Event); 381 pTimer->Event = NIL_RTSEMEVENT; 382 383 RTMemFree(pTimer); 457 384 return rc; 458 385 } 459 386 387 388 RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First) 389 { 390 /* 391 * Validate input. 392 */ 393 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 394 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 395 AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR); 396 397 RTThreadUserReset(pTimer->Thread); 398 399 /* 400 * Already running? 401 */ 402 if (!ASMAtomicXchgBool(&pTimer->fSuspended, false)) 403 return VERR_TIMER_ACTIVE; 404 LogFlow(("RTTimerStart: pTimer=%p u64First=%llu u64NanoInterval=%llu\n", pTimer, u64First, pTimer->u64NanoInterval)); 405 406 /* 407 * Tell the thread to start servicing the timer. 408 * Wait for it to ACK the request to avoid reset races. 409 */ 410 ASMAtomicUoWriteU64(&pTimer->u64NanoFirst, u64First); 411 ASMAtomicUoWriteU64(&pTimer->iTick, 0); 412 int rc = RTSemEventSignal(pTimer->Event); 413 if (RT_SUCCESS(rc)) 414 { 415 rc = RTThreadUserWait(pTimer->Thread, 45*1000); 416 AssertRC(rc); 417 RTThreadUserReset(pTimer->Thread); 418 } 419 else 420 AssertRC(rc); 421 422 if (RT_FAILURE(rc)) 423 ASMAtomicXchgBool(&pTimer->fSuspended, true); 424 return rc; 425 } 426 427 428 RTDECL(int) RTTimerStop(PRTTIMER pTimer) 429 { 430 /* 431 * Validate input. 432 */ 433 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 434 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 435 436 RTThreadUserReset(pTimer->Thread); 437 438 /* 439 * Already running? 440 */ 441 if (ASMAtomicXchgBool(&pTimer->fSuspended, true)) 442 return VERR_TIMER_SUSPENDED; 443 LogFlow(("RTTimerStop: pTimer=%p\n", pTimer)); 444 445 /* 446 * Tell the thread to stop servicing the timer. 447 */ 448 int rc = VINF_SUCCESS; 449 if (RTThreadSelf() != pTimer->Thread) 450 { 451 LARGE_INTEGER ll = {0}; 452 ll.LowPart = 100; 453 rc = SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE); 454 AssertMsg(rc, ("SetWaitableTimer lasterr=%d\n", GetLastError())); 455 rc = RTThreadUserWait(pTimer->Thread, 45*1000); 456 AssertRC(rc); 457 RTThreadUserReset(pTimer->Thread); 458 } 459 460 return rc; 461 } 462 463 464 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 465 { 466 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 467 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 468 NOREF(u64NanoInterval); 469 return VERR_NOT_SUPPORTED; 470 } -
trunk/src/VBox/Runtime/testcase/tstTimer.cpp
r82968 r89762 57 57 gcTicks++; 58 58 59 if (iTick != gcTicks) 60 RTPrintf("tstTimer: FAILURE - iTick=%llu expected %u\n", iTick, gcTicks); 61 59 62 const uint64_t u64Now = RTTimeNanoTS(); 60 63 if (gu64Prev) … … 162 165 gu64Prev = 0; 163 166 RT_ZERO(cFrequency); 164 #ifdef RT_OS_WINDOWS165 if (aTests[i].uMicroInterval < 1000)166 continue;167 rc = RTTimerCreate(&pTimer, aTests[i].uMicroInterval / 1000, TimerCallback, NULL);168 #else169 167 rc = RTTimerCreateEx(&pTimer, aTests[i].uMicroInterval * (uint64_t)1000, 0, TimerCallback, NULL); 170 #endif171 168 if (RT_FAILURE(rc)) 172 169 { … … 180 177 */ 181 178 uTSBegin = RTTimeNanoTS(); 182 #ifndef RT_OS_WINDOWS183 179 rc = RTTimerStart(pTimer, 0); 184 180 if (RT_FAILURE(rc)) … … 187 183 cErrors++; 188 184 } 189 #endif190 185 191 186 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * 1000000)
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器