Changeset 1807 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Mar 29, 2007 5:24:21 PM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 19989
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile
r1781 r1807 263 263 generic/RTFileMove-generic.cpp \ 264 264 generic/RTLogWriteDebugger-generic.cpp \ 265 generic/RTTimerCreate-generic.cpp \ 265 266 r3/posix/RTTimeNow-posix.cpp \ 266 267 r3/posix/alloc-posix.cpp \ … … 295 296 generic/RTFileMove-generic.cpp \ 296 297 generic/RTLogWriteDebugger-generic.cpp \ 298 generic/RTTimerCreate-generic.cpp \ 297 299 os2/RTErrConvertFromOS2.cpp \ 298 300 r3/os2/sems-os2.cpp \ … … 314 316 generic/sched-generic.cpp \ 315 317 r3/os2/time-os2.cpp \ 316 r3/posix/timer-posix.cpp \318 generic/timer-generic.cpp \ 317 319 r3/posix/RTTimeNow-posix.cpp \ 318 320 generic/utf16locale-generic.cpp \ … … 355 357 generic/RTFileMove-generic.cpp \ 356 358 generic/RTLogWriteDebugger-generic.cpp \ 359 generic/RTTimerCreate-generic.cpp \ 357 360 generic/pathhost-generic.cpp \ 358 361 generic/sched-generic.cpp \ -
trunk/src/VBox/Runtime/generic/timer-generic.cpp
r1781 r1807 33 33 #include <iprt/time.h> 34 34 #include <iprt/log.h> 35 #include "internal/magics.h" 35 36 36 37 … … 71 72 uint64_t volatile iTick; 72 73 } RTTIMER; 73 /** Magic number for timer handles. (Jared Mason Diamond) */74 #define RTTIMER_MAGIC 0x1937091075 74 76 75 -
trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp
r1470 r1807 33 33 #include <iprt/string.h> 34 34 #include <iprt/err.h> 35 #include "internal/magics.h" 35 36 36 37 #include <unistd.h> … … 59 60 * This is RTTIMER_MAGIC, but changes to something else before the timer 60 61 * is destroyed to indicate clearly that thread should exit. */ 61 volatile uint32_t u32Magic; 62 /** Win32 timer id. */ 62 uint32_t volatile u32Magic; 63 /** Flag indicating the the timer is suspended. */ 64 uint8_t volatile fSuspended; 65 /** Flag indicating that the timer has been destroyed. */ 66 uint8_t volatile fDestroyed; 67 /** The timer thread. */ 63 68 RTTHREAD Thread; 69 /** Event semaphore on which the thread is blocked. */ 70 RTSEMEVENT Event; 64 71 /** User argument. */ 65 72 void *pvUser; 66 73 /** Callback. */ 67 74 PFNRTTIMER pfnTimer; 68 /** The timeout values for the timer. */ 69 struct itimerval TimerVal; 75 /** The timer interval. 0 if one-shot. */ 76 uint64_t u64NanoInterval; 77 /** The first shot interval. 0 if ASAP. */ 78 uint64_t volatile u64NanoFirst; 70 79 /** The error/status of the timer. 71 80 * Initially -1, set to 0 when the timer have been successfully started, and 72 81 * to errno on failure in starting the timer. */ 73 volatile intiError;82 int volatile iError; 74 83 75 84 } RTTIMER; 76 /** Timer handle magic. */77 #define RTTIMER_MAGIC 0x4242424278 85 79 86 … … 114 121 115 122 /* 116 * Mask most signals except those which might be used during 117 * termination is by a pthread implementation. 123 * Mask most signals except those which might be used by the pthread implementation (linux). 118 124 */ 119 125 sigset_t SigSet; … … 136 142 137 143 /* 138 * Start the timer. 139 * 140 * For some SunOS (/SysV?) threading compatibility Linux will only 141 * deliver the SIGALRM to the thread calling setitimer(). Therefore 142 * we have to call it here. 143 * 144 * It turns out this might not always be the case, see SIGALRM killing 145 * processes on RH 2.4.21. 146 */ 147 if (setitimer(ITIMER_REAL, &pTimer->TimerVal, NULL)) 148 { 149 pTimer->iError = RTErrConvertFromErrno(errno); 144 * The work loop. 145 */ 146 RTThreadUserSignal(Thread); 147 while ( !pTimer->fDestroyed 148 && pTimer->u32Magic == RTTIMER_MAGIC) 149 { 150 /* 151 * Wait for a start or destroy event. 152 */ 153 if (pTimer->fSuspended) 154 { 155 int rc = RTSemEventWait(pTimer->Event, RT_INDEFINITE_WAIT); 156 if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED) 157 { 158 AssertRC(rc); 159 RTThreadSleep(1000); /* Don't cause trouble! */ 160 } 161 if ( pTimer->fSuspended 162 || pTimer->fDestroyed) 163 continue; 164 } 165 166 /* 167 * Start the timer. 168 * 169 * For some SunOS (/SysV?) threading compatibility Linux will only 170 * deliver the SIGALRM to the thread calling setitimer(). Therefore 171 * we have to call it here. 172 * 173 * It turns out this might not always be the case, see SIGALRM killing 174 * processes on RH 2.4.21. 175 */ 176 struct itimerval TimerVal; 177 if (pTimer->u64NanoFirst) 178 { 179 uint64_t u64 = RT_MAX(1000, pTimer->u64NanoFirst); 180 TimerVal.it_value.tv_sec = u64 / 1000000000; 181 TimerVal.it_value.tv_usec = (u64 % 1000000000) / 1000; 182 } 183 else 184 { 185 TimerVal.it_value.tv_sec = 0; 186 TimerVal.it_value.tv_usec = 10; 187 } 188 if (pTimer->u64NanoInterval) 189 { 190 uint64_t u64 = RT_MAX(1000, pTimer->u64NanoInterval); 191 TimerVal.it_interval.tv_sec = u64 / 1000000000; 192 TimerVal.it_interval.tv_usec = (u64 % 1000000000) / 1000; 193 } 194 else 195 { 196 TimerVal.it_interval.tv_sec = 0; 197 TimerVal.it_interval.tv_usec = 0; 198 } 199 200 if (setitimer(ITIMER_REAL, &TimerVal, NULL)) 201 { 202 ASMAtomicXchgU8(&pTimer->fSuspended, true); 203 pTimer->iError = RTErrConvertFromErrno(errno); 204 RTThreadUserSignal(Thread); 205 continue; /* back to suspended mode. */ 206 } 207 pTimer->iError = 0; 150 208 RTThreadUserSignal(Thread); 151 return errno; 152 } 153 154 /* 155 * Signal wait loop-forever. 156 */ 157 sigemptyset(&SigSet); 158 sigaddset(&SigSet, SIGALRM); 209 210 /* 211 * Timer Service Loop. 212 */ 213 sigemptyset(&SigSet); 214 sigaddset(&SigSet, SIGALRM); 215 do 216 { 217 siginfo_t SigInfo = {0}; 218 #ifdef __DARWIN__ 219 if (RT_LIKELY(sigwait(&SigSet, &SigInfo.si_signo) >= 0)) 220 { 221 #else 222 if (RT_LIKELY(sigwaitinfo(&SigSet, &SigInfo) >= 0)) 223 { 224 if (RT_LIKELY(SigInfo.si_signo == SIGALRM)) 225 #endif 226 { 227 if (RT_UNLIKELY( pTimer->fSuspended 228 || pTimer->fDestroyed 229 || pTimer->u32Magic != RTTIMER_MAGIC)) 230 break; 231 232 pTimer->pfnTimer(pTimer, pTimer->pvUser); 233 234 /* auto suspend one-shot timers. */ 235 if (RT_UNLIKELY(!pTimer->u64NanoInterval)) 236 { 237 ASMAtomicXchgU8(&pTimer->fSuspended, true); 238 break; 239 } 240 } 241 } 242 else if (errno != EINTR) 243 AssertMsgFailed(("sigwaitinfo -> errno=%d\n", errno)); 244 } while (RT_LIKELY( !pTimer->fSuspended 245 && !pTimer->fDestroyed 246 && pTimer->u32Magic == RTTIMER_MAGIC)); 247 248 /* 249 * Disable the timer. 250 */ 251 struct itimerval TimerVal2 = {{0,0}, {0,0}}; 252 if (setitimer(ITIMER_REAL, &TimerVal2, NULL)) 253 AssertMsgFailed(("setitimer(ITIMER_REAL,&{0}, NULL) failed, errno=%d\n", errno)); 254 255 /* 256 * ACK any pending suspend request. 257 */ 258 if (!pTimer->fDestroyed) 259 { 260 pTimer->iError = 0; 261 RTThreadUserSignal(Thread); 262 } 263 } 264 265 /* 266 * Exit. 267 */ 268 pTimer->iError = 0; 159 269 RTThreadUserSignal(Thread); 160 while (pTimer->u32Magic == RTTIMER_MAGIC) 161 { 162 siginfo_t SigInfo = {0}; 163 #ifdef __DARWIN__ 164 if (sigwait(&SigSet, &SigInfo.si_signo) >= 0) 165 { 166 #else 167 if (sigwaitinfo(&SigSet, &SigInfo) >= 0) 168 { 169 if ( SigInfo.si_signo == SIGALRM 170 && pTimer->u32Magic == RTTIMER_MAGIC) 171 #endif 172 pTimer->pfnTimer(pTimer, pTimer->pvUser); 173 } 174 else if (errno != EINTR) 175 AssertMsgFailed(("sigwaitinfo -> errno=%d\n", errno)); 176 } 177 178 /* 179 * Disable the timer. 180 */ 181 struct itimerval TimerVal = {{0,0}, {0,0}}; 182 if (setitimer(ITIMER_REAL, &TimerVal, NULL)) 183 AssertMsgFailed(("setitimer(ITIMER_REAL,&{0}, NULL) failed, errno=%d\n", errno)); 184 185 /* 186 * Exit. 187 */ 188 RTThreadUserSignal(Thread); 270 189 271 return VINF_SUCCESS; 190 272 } 191 273 192 274 193 /** 194 * Create a recurring timer. 195 * 196 * @returns iprt status code. 197 * @param ppTimer Where to store the timer handle. 198 * @param uMilliesInterval Milliseconds between the timer ticks. 199 * This is rounded up to the system granularity. 200 * @param pfnCallback Callback function which shall be scheduled for execution 201 * on every timer tick. 202 * @param pvUser User argument for the callback. 203 */ 204 RTR3DECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser) 275 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser) 205 276 { 206 277 /* … … 224 295 * Block SIGALRM from calling thread. 225 296 */ 226 #if defined(__FREEBSD__) /* sighold is missing and I don't wish to break anything atm. */227 297 sigset_t SigSet; 228 298 sigemptyset(&SigSet); 229 299 sigaddset(&SigSet, SIGALRM); 230 300 sigprocmask(SIG_BLOCK, &SigSet, NULL); 231 #else 232 sighold(SIGALRM); 233 #endif 301 302 /** @todo Move this RTC hack else where... */ 234 303 static bool fDoneRTC; 235 304 if (!fDoneRTC) … … 273 342 274 343 /* 275 * Create new timer.344 * Create a new timer. 276 345 */ 277 346 int rc; … … 280 349 { 281 350 pTimer->u32Magic = RTTIMER_MAGIC; 351 pTimer->fSuspended = true; 352 pTimer->fDestroyed = false; 353 pTimer->Thread = NIL_RTTHREAD; 354 pTimer->Event = NIL_RTSEMEVENT; 355 pTimer->pfnTimer = pfnTimer; 356 pTimer->pvUser = pvUser; 357 pTimer->u64NanoInterval = u64NanoInterval; 282 358 pTimer->iError = 0; 283 pTimer->pvUser = pvUser; 284 pTimer->pfnTimer = pfnTimer; 285 pTimer->TimerVal.it_interval.tv_sec = uMilliesInterval / 1000; 286 pTimer->TimerVal.it_interval.tv_usec = (uMilliesInterval % 1000) * 1000; 287 pTimer->TimerVal.it_value = pTimer->TimerVal.it_interval; 288 rc = RTThreadCreate(&pTimer->Thread, rttimerThread, pTimer, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer"); 359 rc = RTSemEventCreate(&pTimer->Event); 360 AssertRC(rc); 289 361 if (RT_SUCCESS(rc)) 290 362 { 291 /* 292 * Wait for the timer to successfully create the timer 293 */ 294 /** @todo something is may cause this to take very long. We're waiting 30 seconds now and hope that'll workaround it... */ 295 rc = RTThreadUserWait(pTimer->Thread, 30*1000); 363 rc = RTThreadCreate(&pTimer->Thread, rttimerThread, pTimer, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer"); 364 AssertRC(rc); 296 365 if (RT_SUCCESS(rc)) 297 366 { 298 rc = pTimer->iError; 367 /* 368 * Wait for the timer thread to initialize it self. 369 * This might take a little while... 370 */ 371 rc = RTThreadUserWait(pTimer->Thread, 45*1000); 372 AssertRC(rc); 299 373 if (RT_SUCCESS(rc)) 300 374 { 301 RTThreadYield(); /* Horrible hack to make tstTimer work. Something is really fucked related to scheduling here! (2.6.12) */ 302 *ppTimer = pTimer; 303 return VINF_SUCCESS; 375 rc = RTThreadUserReset(pTimer->Thread); AssertRC(rc); 376 rc = pTimer->iError; 377 AssertRC(rc); 378 if (RT_SUCCESS(rc)) 379 { 380 RTThreadYield(); /* <-- Horrible hack to make tstTimer work. (linux 2.6.12) */ 381 *ppTimer = pTimer; 382 return VINF_SUCCESS; 383 } 304 384 } 385 386 /* bail out */ 387 ASMAtomicXchgU8(&pTimer->fDestroyed, true); 388 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 389 RTThreadWait(pTimer->Thread, 45*1000, NULL); 305 390 } 306 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 307 } 308 309 AssertMsgFailed(("Failed to create timer uMilliesInterval=%d. rc=%Vrc\n", uMilliesInterval, rc)); 391 RTSemEventDestroy(pTimer->Event); 392 pTimer->Event = NIL_RTSEMEVENT; 393 } 310 394 RTMemFree(pTimer); 311 395 } … … 316 400 317 401 318 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)319 {320 /// @todo implement321 return VERR_NOT_IMPLEMENTED;322 }323 324 325 /**326 * Stops and destroys a running timer.327 *328 * @returns iprt status code.329 * @param pTimer Timer to stop and destroy.330 */331 402 RTR3DECL(int) RTTimerDestroy(PRTTIMER pTimer) 332 403 { 333 404 LogFlow(("RTTimerDestroy: pTimer=%p\n", pTimer)); 334 405 406 /* 407 * Validate input. 408 */ 335 409 /* NULL is ok. */ 336 410 if (!pTimer) 337 411 return VINF_SUCCESS; 338 339 /*340 * Validate input.341 */342 412 int rc = VINF_SUCCESS; 343 if (VALID_PTR(pTimer)) 344 { 345 /* 346 * Modify the magic and kick it. 347 */ 348 if (ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1) == RTTIMER_MAGIC) 349 { 413 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 414 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 415 AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR); 416 417 /* 418 * Tell the thread to terminate and wait for it do complete. 419 */ 420 ASMAtomicXchgU8(&pTimer->fDestroyed, true); 421 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 422 rc = RTSemEventSignal(pTimer->Event); 423 AssertRC(rc); 424 if (!pTimer->fSuspended) 425 { 350 426 #ifndef __OS2__ 351 pthread_kill((pthread_t)RTThreadGetNative(pTimer->Thread), SIGALRM); 352 #endif 353 354 /* 355 * Wait for the thread to exit. 356 */ 357 rc = RTThreadWait(pTimer->Thread, 30 * 1000, NULL); 358 if ( RT_SUCCESS(rc) 359 || rc == VERR_INVALID_HANDLE /* we don't keep handles around, you gotta wait before it really exits! */) 360 { 361 RTMemFree(pTimer); 362 return VINF_SUCCESS; 363 } 364 AssertMsgFailed(("Failed to destroy timer %p. rc=%Vrc\n", pTimer, rc)); 365 } 366 else 367 { 368 AssertMsgFailed(("Timer %p is already being destroyed!\n", pTimer)); 369 rc = VERR_INVALID_MAGIC; 370 } 371 } 372 else 373 { 374 AssertMsgFailed(("Bad pTimer pointer %p!\n", pTimer)); 375 rc = VERR_INVALID_HANDLE; 376 } 427 pthread_kill((pthread_t)RTThreadGetNative(pTimer->Thread), SIGALRM); 428 #endif 429 } 430 rc = RTThreadWait(pTimer->Thread, 30 * 1000, NULL); 431 AssertRC(rc); 432 433 RTSemEventDestroy(pTimer->Event); 434 pTimer->Event = NIL_RTSEMEVENT; 435 if (RT_SUCCESS(rc)) 436 RTMemFree(pTimer); 377 437 return rc; 378 438 } … … 381 441 RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First) 382 442 { 383 /// @todo implement 384 return VERR_NOT_IMPLEMENTED; 443 /* 444 * Validate input. 445 */ 446 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 447 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 448 AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR); 449 450 /* 451 * Already running? 452 */ 453 if (!pTimer->fSuspended) 454 return VERR_TIMER_ACTIVE; 455 456 /* 457 * Tell the thread to start servicing the timer. 458 */ 459 RTThreadUserReset(pTimer->Thread); 460 ASMAtomicXchgU64(&pTimer->u64NanoFirst, u64First); 461 ASMAtomicXchgU8(&pTimer->fSuspended, false); 462 int rc = RTSemEventSignal(pTimer->Event); 463 if (RT_SUCCESS(rc)) 464 { 465 rc = RTThreadUserWait(pTimer->Thread, 45*1000); 466 AssertRC(rc); 467 RTThreadUserReset(pTimer->Thread); 468 } 469 else 470 AssertRC(rc); 471 if (RT_FAILURE(rc)) 472 ASMAtomicXchgU8(&pTimer->fSuspended, false); 473 474 return rc; 385 475 } 386 476 … … 388 478 RTDECL(int) RTTimerStop(PRTTIMER pTimer) 389 479 { 390 /// @todo implement 391 return VERR_NOT_IMPLEMENTED; 480 /* 481 * Validate input. 482 */ 483 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 484 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 485 486 /* 487 * Already running? 488 */ 489 if (pTimer->fSuspended) 490 return VERR_TIMER_SUSPENDED; 491 492 /* 493 * Tell the thread to stop servicing the timer. 494 */ 495 RTThreadUserReset(pTimer->Thread); 496 ASMAtomicXchgU8(&pTimer->fSuspended, true); 497 if (RTThreadSelf() != pTimer->Timer) 498 { 499 #ifndef __OS2__ 500 pthread_kill((pthread_t)RTThreadGetNative(pTimer->Thread), SIGALRM); 501 #endif 502 int rc = RTThreadUserWait(pTimer->Thread, 45*1000); 503 AssertRC(rc); 504 RTThreadUserReset(pTimer->Thread); 505 } 506 507 return rc; 392 508 } 509 -
trunk/src/VBox/Runtime/r3/win32/timer-win32.cpp
r197 r1807 64 64 #include <iprt/semaphore.h> 65 65 #include <iprt/err.h> 66 67 #include <errno.h> 66 #include "internal/magics.h" 68 67 69 68 __BEGIN_DECLS … … 113 112 #endif 114 113 } RTTIMER; 115 116 /** Timer handle magic. */117 #define RTTIMER_MAGIC 0x42424242118 119 114 120 115
Note:
See TracChangeset
for help on using the changeset viewer.