Changeset 10920 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jul 28, 2008 6:44:26 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp
r10854 r10920 37 37 #endif /* !RT_OS_SOLARIS */ 38 38 39 #define LOG_GROUP RTLOGGROUP_TIMER 39 40 40 41 /******************************************************************************* … … 65 66 #endif 66 67 68 #ifdef IPRT_WITH_POSIX_TIMERS 69 #define RT_TIMER_SIGNAL SIGALRM 70 71 /** 72 * Global counter of RTTimer instances. The signal thread is 73 * started when it changes from 0 to 1. The signal thread 74 * terminates when it becomes 0 again. 75 */ 76 uint32_t g_cTimerInstances; 77 /** The signal handling thread. */ 78 RTTHREAD g_Thread; 79 /** 80 * Event semaphore on which the calling thread is blocked until 81 * the signal thread has been initialized. 82 */ 83 RTSEMEVENT g_Event; 84 85 #endif /* IPRT_WITH_POSIX_TIMERS */ 67 86 68 87 /******************************************************************************* … … 93 112 /** Event semaphore on which the thread is blocked. */ 94 113 RTSEMEVENT Event; 95 #endif 114 #endif /* !IPRT_WITH_POSIX_TIMERS */ 96 115 /** User argument. */ 97 116 void *pvUser; … … 111 130 * to errno on failure in starting the timer. */ 112 131 int volatile iError; 113 #else /* !IPRT_WITH_POSIX_TIMERS */132 #else /* IPRT_WITH_POSIX_TIMERS */ 114 133 timer_t timer; 115 #endif /* !IPRT_WITH_POSIX_TIMERS */134 #endif /* IPRT_WITH_POSIX_TIMERS */ 116 135 117 136 } RTTIMER; 118 119 #ifndef IPRT_WITH_POSIX_TIMERS120 137 121 138 /** … … 135 152 static DECLCALLBACK(int) rttimerThread(RTTHREAD Thread, void *pvArg) 136 153 { 154 #ifndef IPRT_WITH_POSIX_TIMERS 137 155 PRTTIMER pTimer = (PRTTIMER)(void *)pvArg; 138 156 RTTIMER Timer = *pTimer; 139 157 Assert(pTimer->u32Magic == RTTIMER_MAGIC); 158 #endif /* !IPRT_WITH_POSIX_TIMERS */ 140 159 141 160 /* … … 170 189 if (sigprocmask(SIG_SETMASK, &SigSet, NULL)) 171 190 { 191 #ifndef IPRT_WITH_POSIX_TIMERS 172 192 int rc = pTimer->iError = RTErrConvertFromErrno(errno); 193 #else /* IPRT_WITH_POSIX_TIMERS */ 194 int rc = RTErrConvertFromErrno(errno); 195 #endif /* IPRT_WITH_POSIX_TIMERS */ 173 196 AssertMsgFailed(("sigprocmask -> errno=%d\n", errno)); 174 197 return rc; … … 179 202 */ 180 203 RTThreadUserSignal(Thread); 204 205 #ifndef IPRT_WITH_POSIX_TIMERS 181 206 while ( !pTimer->fDestroyed 182 207 && pTimer->u32Magic == RTTIMER_MAGIC) … … 305 330 return VINF_SUCCESS; 306 331 } 307 #else /* !IPRT_WITH_POSIX_TIMERS */ 308 void rttimerCallback(union sigval SigVal) 332 #else /* IPRT_WITH_POSIX_TIMERS */ 333 sigemptyset(&SigSet); 334 sigaddset(&SigSet, RT_TIMER_SIGNAL); 335 while (g_cTimerInstances) 336 { 337 siginfo_t SigInfo = {0}; 338 if (RT_LIKELY(sigwaitinfo(&SigSet, &SigInfo) >= 0)) 339 { 340 LogFlow(("rttimerThread: signo=%d pTimer=%p\n", SigInfo.si_signo, SigInfo._sifields._timer.si_sigval.sival_ptr)); 341 if (RT_LIKELY(SigInfo.si_signo == RT_TIMER_SIGNAL)) 342 { 343 PRTTIMER pTimer = (PRTTIMER)SigInfo._sifields._timer.si_sigval.sival_ptr; 344 if (RT_UNLIKELY( pTimer == NULL 345 || pTimer->fSuspended 346 || pTimer->fDestroyed 347 || pTimer->u32Magic != RTTIMER_MAGIC)) 348 continue; 349 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick); 350 /* auto suspend one-shot timers. */ 351 if (RT_UNLIKELY(!pTimer->u64NanoInterval)) 352 { 353 ASMAtomicXchgU8(&pTimer->fSuspended, true); /* @todo Can't we do a simple assigment here? */ 354 //break; 355 } 356 } 357 } 358 } 359 360 return VINF_SUCCESS; 361 } 362 363 /** 364 * Create the SIGALRM handling thread and wait for it to get 365 * ready. 366 */ 367 static int rttimerCreateSignalThread() 309 368 { 310 PRTTIMER pTimer = (PRTTIMER)SigVal.sival_ptr; 311 /* Is the timer being destoyed/suspended at this very moment? */ 312 if (RT_LIKELY(pTimer->u32Magic == RTTIMER_MAGIC 313 && !pTimer->fSuspended 314 && !pTimer->fDestroyed)) 315 { 316 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick); 317 } 369 int rc = RTThreadCreate(&g_Thread, rttimerThread, NULL, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer"); 370 AssertRC(rc); 371 if (RT_SUCCESS(rc)) 372 { 373 /* Let's wait for the thread to get ready to handle signals. */ 374 rc = RTThreadUserWait(g_Thread, 5000); /* @todo 5 sec is enough? or is it too much? */ 375 } 376 LogFlow(("rttimerCreateSignalThread: rc=%Vrc\n", rc)); 377 378 return rc; 379 318 380 } 319 #endif /* !IPRT_WITH_POSIX_TIMERS */381 #endif /* IPRT_WITH_POSIX_TIMERS */ 320 382 321 383 … … 328 390 return VERR_NOT_SUPPORTED; 329 391 330 #ifndef IPRT_WITH_POSIX_TIMERS /** @todo the signal blocking applies to the new code too, see comment in the struct. */392 #ifndef IPRT_WITH_POSIX_TIMERS 331 393 /* 332 394 * Check if timer is busy. … … 345 407 return VERR_TIMER_BUSY; 346 408 } 409 #endif /* !IPRT_WITH_POSIX_TIMERS */ 347 410 348 411 /* … … 354 417 sigprocmask(SIG_BLOCK, &SigSet, NULL); 355 418 419 #ifndef IPRT_WITH_POSIX_TIMERS 356 420 /** @todo Move this RTC hack else where... */ 357 421 static bool fDoneRTC; … … 452 516 else 453 517 rc = VERR_NO_MEMORY; 454 #else /* !IPRT_WITH_POSIX_TIMERS */518 #else /* IPRT_WITH_POSIX_TIMERS */ 455 519 /* 456 520 * Create a new timer. 457 521 */ 458 int rc; 522 LogFlow(("RTTimerCreateEx: u64NanoInterval=%llu fFlags=%lu\n", u64NanoInterval, fFlags)); 523 524 int rc = VINF_SUCCESS; 459 525 PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer)); 460 526 if (pTimer) … … 471 537 pTimer->iTick = 0; 472 538 473 /* Ask to call rttimerCallback in a separate thread context upon timer expiration. */ 474 memset(&evt, 0, sizeof(evt)); 475 evt.sigev_notify = SIGEV_THREAD; 476 evt.sigev_value.sival_ptr = pTimer; 477 evt.sigev_notify_function = rttimerCallback; 478 479 rc = RTErrConvertFromErrno(timer_create(CLOCK_REALTIME, &evt, &pTimer->timer)); 539 /* Create the signal handling thread if it is the first instance. */ 540 if (ASMAtomicIncU32(&g_cTimerInstances) == 1) 541 rc = rttimerCreateSignalThread(); 542 480 543 if (RT_SUCCESS(rc)) 481 544 { 482 *ppTimer = pTimer; 483 return VINF_SUCCESS; 484 } 545 /* Ask to deliver RT_TIMER_SIGNAL upon timer expiration. */ 546 evt.sigev_notify = SIGEV_SIGNAL; 547 evt.sigev_signo = RT_TIMER_SIGNAL; 548 evt.sigev_value.sival_ptr = pTimer; /* sigev_value gets copied to siginfo. */ 549 550 rc = RTErrConvertFromErrno(timer_create(CLOCK_REALTIME, &evt, &pTimer->timer)); 551 LogFlow(("RTTimerCreateEx: rc=%Vrc pTimer=%p\n", rc, pTimer)); 552 if (RT_SUCCESS(rc)) 553 { 554 *ppTimer = pTimer; 555 return VINF_SUCCESS; 556 } 557 } 558 /** 559 * Roll back the timer instance counter. This will cause 560 * termination of the signal handling thread if it is the only 561 * timer. 562 */ 563 ASMAtomicDecU32(&g_cTimerInstances); 485 564 RTMemFree(pTimer); 486 565 } … … 488 567 rc = VERR_NO_MEMORY; 489 568 490 #endif /* !IPRT_WITH_POSIX_TIMERS */569 #endif /* IPRT_WITH_POSIX_TIMERS */ 491 570 return rc; 492 571 } … … 527 606 RTSemEventDestroy(pTimer->Event); 528 607 pTimer->Event = NIL_RTSEMEVENT; 529 #else /* !IPRT_WITH_POSIX_TIMERS */608 #else /* IPRT_WITH_POSIX_TIMERS */ 530 609 if (ASMAtomicXchgU8(&pTimer->fDestroyed, true)) 531 610 { … … 534 613 } 535 614 rc = RTErrConvertFromErrno(timer_delete(pTimer->timer)); 536 #endif /* !IPRT_WITH_POSIX_TIMERS */ 615 /** 616 * Decrement the timer instance counter. This will cause 617 * termination of the signal handling thread if it is the last 618 * remaining timer. 619 */ 620 if (ASMAtomicDecU32(&g_cTimerInstances) == 0) 621 { 622 /* Wake up the timer thread so it can exit. */ 623 kill(getpid(), RT_TIMER_SIGNAL); 624 } 625 #endif /* IPRT_WITH_POSIX_TIMERS */ 537 626 if (RT_SUCCESS(rc)) 538 627 RTMemFree(pTimer); … … 575 664 if (RT_FAILURE(rc)) 576 665 ASMAtomicXchgU8(&pTimer->fSuspended, false); 577 #else /* !IPRT_WITH_POSIX_TIMERS */ 666 #else /* IPRT_WITH_POSIX_TIMERS */ 667 LogFlow(("RTTimerStart: pTimer=%p u64First=%llu u64NanoInterval=%llu\n", pTimer, u64First, pTimer->u64NanoInterval)); 668 578 669 struct itimerspec ts; 579 670 … … 582 673 583 674 ts.it_value.tv_sec = u64First / 1000000000; /* nanosec => sec */ 584 ts.it_value.tv_nsec = u64First ? u64First % 1000000000 : 1 ; /* 0 means disable, replace it with 1. */675 ts.it_value.tv_nsec = u64First ? u64First % 1000000000 : 10; /* 0 means disable, replace it with 10. */ 585 676 ts.it_interval.tv_sec = pTimer->u64NanoInterval / 1000000000; 586 677 ts.it_interval.tv_nsec = pTimer->u64NanoInterval % 1000000000; 587 678 int rc = RTErrConvertFromErrno(timer_settime(pTimer->timer, 0, &ts, NULL)); 588 #endif /* !IPRT_WITH_POSIX_TIMERS */679 #endif /* IPRT_WITH_POSIX_TIMERS */ 589 680 590 681 return rc; … … 622 713 RTThreadUserReset(pTimer->Thread); 623 714 } 624 #else /* !IPRT_WITH_POSIX_TIMERS */ 715 #else /* IPRT_WITH_POSIX_TIMERS */ 716 LogFlow(("RTTimerStop: pTimer=%p\n", pTimer)); 717 625 718 struct itimerspec ts; 626 719 … … 631 724 ts.it_value.tv_nsec = 0; 632 725 int rc = RTErrConvertFromErrno(timer_settime(pTimer->timer, 0, &ts, NULL)); 633 #endif /* !IPRT_WITH_POSIX_TIMERS */726 #endif /* IPRT_WITH_POSIX_TIMERS */ 634 727 635 728 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.