Changeset 10941 in vbox for trunk/src/VBox/Runtime/r3/posix
- Timestamp:
- Jul 29, 2008 4:53:12 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp
r10920 r10941 34 34 /** Enables the use of POSIX RT timers. */ 35 35 #ifndef RT_OS_SOLARIS /* Solaris 10 doesn't have SIGEV_THREAD */ 36 # define IPRT_WITH_POSIX_TIMERS36 # define IPRT_WITH_POSIX_TIMERS 37 37 #endif /* !RT_OS_SOLARIS */ 38 38 39 #define LOG_GROUP RTLOGGROUP_TIMER 39 /** @def RT_TIMER_SIGNAL 40 * The signal number that the timers use. 41 * We currently use SIGALRM for both setitimer and posix real time timers 42 * out of simplicity, but we might want change this later for the posix ones. */ 43 #ifdef IPRT_WITH_POSIX_TIMERS 44 # define RT_TIMER_SIGNAL SIGALRM 45 #else 46 # define RT_TIMER_SIGNAL SIGALRM 47 #endif 48 40 49 41 50 /******************************************************************************* 42 51 * Header Files * 43 52 *******************************************************************************/ 53 #define LOG_GROUP RTLOGGROUP_TIMER 44 54 #include <iprt/timer.h> 45 55 #include <iprt/alloc.h> … … 50 60 #include <iprt/semaphore.h> 51 61 #include <iprt/string.h> 62 #include <iprt/once.h> 52 63 #include <iprt/err.h> 64 #include <iprt/critsect.h> 53 65 #include "internal/magics.h" 54 66 … … 62 74 #include <signal.h> 63 75 #include <errno.h> 64 #ifndef RT_OS_OS2 65 # include <pthread.h> 66 #endif 67 76 #include <pthread.h> 77 78 79 /******************************************************************************* 80 * Global Variables * 81 *******************************************************************************/ 68 82 #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; 83 /** Init the critsect on first call. */ 84 static RTONCE g_TimerOnce = RTONCE_INITIALIZER; 85 /** Global critsect that serializes timer creation and destruction. 86 * This is lazily created on the first RTTimerCreateEx call and will not be 87 * freed up (I'm afraid). */ 88 static RTCRITSECT g_TimerCritSect; 89 /** 90 * Global counter of RTTimer instances. The signal thread is 91 * started when it changes from 0 to 1. The signal thread 92 * terminates when it becomes 0 again. 93 */ 94 static uint32_t volatile g_cTimerInstances; 77 95 /** 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 96 static RTTHREAD g_TimerThread; 85 97 #endif /* IPRT_WITH_POSIX_TIMERS */ 98 86 99 87 100 /******************************************************************************* … … 131 144 int volatile iError; 132 145 #else /* IPRT_WITH_POSIX_TIMERS */ 133 timer_t timer;146 timer_t NativeTimer; 134 147 #endif /* IPRT_WITH_POSIX_TIMERS */ 135 148 136 149 } RTTIMER; 150 151 152 153 #ifdef IPRT_WITH_POSIX_TIMERS 154 155 /** 156 * RTOnce callback that initalizes the critical section. 157 * 158 * @returns RTCritSectInit return code. 159 * @param pvUser1 NULL, ignopred. 160 * @param pvUser2 NULL, ignopred. 161 * 162 */ 163 static DECLCALLBACK(int) rtTimerOnce(void *pvUser1, void *pvUser2) 164 { 165 NOREF(pvUser1); 166 NOREF(pvUser2); 167 return RTCritSectInit(&g_TimerCritSect); 168 } 169 #endif 170 137 171 138 172 /** … … 148 182 149 183 /** 150 * SIGALRMwait thread.184 * RT_TIMER_SIGNAL wait thread. 151 185 */ 152 186 static DECLCALLBACK(int) rttimerThread(RTTHREAD Thread, void *pvArg) … … 166 200 sigemptyset(&SigAct.sa_mask); 167 201 SigAct.sa_handler = rttimerSignalIgnore; 168 if (sigaction( SIGALRM, &SigAct, NULL))202 if (sigaction(RT_TIMER_SIGNAL, &SigAct, NULL)) 169 203 { 170 204 SigAct.sa_flags &= ~SA_RESTART; 171 if (sigaction( SIGALRM, &SigAct, NULL))205 if (sigaction(RT_TIMER_SIGNAL, &SigAct, NULL)) 172 206 AssertMsgFailed(("sigaction failed, errno=%d\n", errno)); 173 207 } … … 189 223 if (sigprocmask(SIG_SETMASK, &SigSet, NULL)) 190 224 { 191 #ifndef IPRT_WITH_POSIX_TIMERS 225 #ifdef IPRT_WITH_POSIX_TIMERS 226 int rc = RTErrConvertFromErrno(errno); 227 #else 192 228 int rc = pTimer->iError = RTErrConvertFromErrno(errno); 193 #else /* IPRT_WITH_POSIX_TIMERS */ 194 int rc = RTErrConvertFromErrno(errno); 195 #endif /* IPRT_WITH_POSIX_TIMERS */ 229 #endif 196 230 AssertMsgFailed(("sigprocmask -> errno=%d\n", errno)); 197 231 return rc; … … 216 250 { 217 251 AssertRC(rc); 252 if (pTimer->fDestroyed) 253 continue; 218 254 RTThreadSleep(1000); /* Don't cause trouble! */ 219 255 } … … 227 263 * 228 264 * For some SunOS (/SysV?) threading compatibility Linux will only 229 * deliver the SIGALRMto the thread calling setitimer(). Therefore265 * deliver the RT_TIMER_SIGNAL to the thread calling setitimer(). Therefore 230 266 * we have to call it here. 231 267 * 232 * It turns out this might not always be the case, see SIGALRMkilling268 * It turns out this might not always be the case, see RT_TIMER_SIGNAL killing 233 269 * processes on RH 2.4.21. 234 270 */ … … 271 307 */ 272 308 sigemptyset(&SigSet); 273 sigaddset(&SigSet, SIGALRM);309 sigaddset(&SigSet, RT_TIMER_SIGNAL); 274 310 do 275 311 { … … 281 317 if (RT_LIKELY(sigwaitinfo(&SigSet, &SigInfo) >= 0)) 282 318 { 283 if (RT_LIKELY(SigInfo.si_signo == SIGALRM))319 if (RT_LIKELY(SigInfo.si_signo == RT_TIMER_SIGNAL)) 284 320 #endif 285 321 { … … 294 330 if (RT_UNLIKELY(!pTimer->u64NanoInterval)) 295 331 { 296 ASMAtomic XchgU8(&pTimer->fSuspended, true);332 ASMAtomicWriteU8(&pTimer->fSuspended, true); 297 333 break; 298 334 } … … 328 364 RTThreadUserSignal(Thread); 329 365 330 return VINF_SUCCESS;331 }332 366 #else /* IPRT_WITH_POSIX_TIMERS */ 367 333 368 sigemptyset(&SigSet); 334 369 sigaddset(&SigSet, RT_TIMER_SIGNAL); … … 339 374 { 340 375 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)) 376 if (RT_LIKELY( SigInfo.si_signo == RT_TIMER_SIGNAL 377 && SigInfo.si_code == SI_TIMER)) /* The SI_TIMER check is *essential* because of the pthread_kill. */ 342 378 { 343 379 PRTTIMER pTimer = (PRTTIMER)SigInfo._sifields._timer.si_sigval.sival_ptr; 344 if (RT_UNLIKELY( pTimer == NULL 345 || pTimer->fSuspended 346 || pTimer->fDestroyed 380 AssertPtr(pTimer); 381 if (RT_UNLIKELY( !VALID_PTR(pTimer) 382 || ASMAtomicUoReadU8(&pTimer->fSuspended) 383 || ASMAtomicUoReadU8(&pTimer->fDestroyed) 347 384 || pTimer->u32Magic != RTTIMER_MAGIC)) 348 385 continue; 386 349 387 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick); 388 350 389 /* auto suspend one-shot timers. */ 351 390 if (RT_UNLIKELY(!pTimer->u64NanoInterval)) 352 { 353 ASMAtomicXchgU8(&pTimer->fSuspended, true); /* @todo Can't we do a simple assigment here? */ 354 //break; 355 } 391 ASMAtomicWriteU8(&pTimer->fSuspended, true); /** @todo Can't we do a simple assigment here? */ 356 392 } 357 393 } 358 394 } 395 #endif /* IPRT_WITH_POSIX_TIMERS */ 359 396 360 397 return VINF_SUCCESS; 361 398 } 362 399 363 /**364 * Create the SIGALRM handling thread and wait for it to get365 * ready.366 */367 static int rttimerCreateSignalThread()368 {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 380 }381 #endif /* IPRT_WITH_POSIX_TIMERS */382 383 400 384 401 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser) … … 400 417 return VERR_NOT_IMPLEMENTED; 401 418 } 402 if ( TimerVal.it_value.tv_usec || TimerVal.it_value.tv_sec 403 || TimerVal.it_interval.tv_usec || TimerVal.it_interval.tv_sec 404 ) 419 if ( TimerVal.it_value.tv_usec 420 || TimerVal.it_value.tv_sec 421 || TimerVal.it_interval.tv_usec 422 || TimerVal.it_interval.tv_sec) 405 423 { 406 424 AssertMsgFailed(("A timer is running. System limit is one timer per process!\n")); … … 410 428 411 429 /* 412 * Block SIGALRMfrom calling thread.430 * Block RT_TIMER_SIGNAL from calling thread. 413 431 */ 414 432 sigset_t SigSet; 415 433 sigemptyset(&SigSet); 416 sigaddset(&SigSet, SIGALRM);434 sigaddset(&SigSet, RT_TIMER_SIGNAL); 417 435 sigprocmask(SIG_BLOCK, &SigSet, NULL); 418 436 419 #ifndef IPRT_WITH_POSIX_TIMERS 437 #ifndef IPRT_WITH_POSIX_TIMERS /** @todo combine more of the setitimer/timer_create code. setitimer could also use the global thread. */ 420 438 /** @todo Move this RTC hack else where... */ 421 439 static bool fDoneRTC; … … 436 454 */ 437 455 Log(("RTTimerCreate: interval={%ld,%ld} trying to adjust /dev/rtc!\n", TimerVal.it_interval.tv_sec, TimerVal.it_interval.tv_usec)); 438 # ifdef RT_OS_LINUX456 # ifdef RT_OS_LINUX 439 457 int fh = open("/dev/rtc", O_RDONLY); 440 458 if (fh >= 0) … … 450 468 else 451 469 Log(("RTTimerCreate: couldn't configure rtc! open failed with errno=%d\n", errno)); 452 # endif470 # endif 453 471 } 454 472 /* disable it */ … … 506 524 /* bail out */ 507 525 ASMAtomicXchgU8(&pTimer->fDestroyed, true); 508 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1);526 ASMAtomicXchgU32(&pTimer->u32Magic, ~RTTIMER_MAGIC); 509 527 RTThreadWait(pTimer->Thread, 45*1000, NULL); 510 528 } … … 516 534 else 517 535 rc = VERR_NO_MEMORY; 536 518 537 #else /* IPRT_WITH_POSIX_TIMERS */ 519 /* 520 * Create a new timer. 538 539 /* 540 * Do the global init first. 541 */ 542 int rc = RTOnce(&g_TimerOnce, rtTimerOnce, NULL, NULL); 543 if (RT_FAILURE(rc)) 544 return rc; 545 546 /* 547 * Create a new timer structure. 521 548 */ 522 549 LogFlow(("RTTimerCreateEx: u64NanoInterval=%llu fFlags=%lu\n", u64NanoInterval, fFlags)); 523 524 int rc = VINF_SUCCESS;525 550 PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer)); 526 551 if (pTimer) 527 552 { 528 struct sigevent evt;529 530 553 /* Initialize timer structure. */ 531 554 pTimer->u32Magic = RTTIMER_MAGIC; … … 537 560 pTimer->iTick = 0; 538 561 539 /* Create the signal handling thread if it is the first instance. */ 540 if (ASMAtomicIncU32(&g_cTimerInstances) == 1) 541 rc = rttimerCreateSignalThread(); 542 543 if (RT_SUCCESS(rc)) 544 { 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)) 562 /* 563 * Create a timer that deliver RT_TIMER_SIGNAL upon timer expiration. 564 */ 565 struct sigevent SigEvt; 566 SigEvt.sigev_notify = SIGEV_SIGNAL; 567 SigEvt.sigev_signo = RT_TIMER_SIGNAL; 568 SigEvt.sigev_value.sival_ptr = pTimer; /* sigev_value gets copied to siginfo. */ 569 int err = timer_create(CLOCK_REALTIME, &SigEvt, &pTimer->NativeTimer); 570 if (!err) 571 { 572 /* 573 * Increment the timer count, do this behind the critsect to avoid races. 574 */ 575 RTCritSectEnter(&g_TimerCritSect); 576 577 if (ASMAtomicIncU32(&g_cTimerInstances) != 1) 553 578 { 579 Assert(g_cTimerInstances > 1); 580 RTCritSectLeave(&g_TimerCritSect); 581 582 LogFlow(("RTTimerCreateEx: rc=%Rrc pTimer=%p (thread already running)\n", rc, pTimer)); 554 583 *ppTimer = pTimer; 555 584 return VINF_SUCCESS; 556 585 } 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); 586 587 /* 588 * Create the signal handling thread. It will wait for the signal 589 * and execute the timer functions. 590 */ 591 rc = RTThreadCreate(&g_TimerThread, rttimerThread, NULL, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer"); 592 if (RT_SUCCESS(rc)) 593 { 594 rc = RTThreadUserWait(g_TimerThread, 45*1000); /* this better not fail... */ 595 if (RT_SUCCESS(rc)) 596 { 597 RTCritSectLeave(&g_TimerCritSect); 598 599 LogFlow(("RTTimerCreateEx: rc=%Rrc pTimer=%p (thread already running)\n", rc, pTimer)); 600 *ppTimer = pTimer; 601 return VINF_SUCCESS; 602 } 603 /* darn, what do we do here? */ 604 } 605 606 /* bail out */ 607 ASMAtomicDecU32(&g_cTimerInstances); 608 Assert(!g_cTimerInstances); 609 610 RTCritSectLeave(&g_TimerCritSect); 611 612 timer_delete(pTimer->NativeTimer); 613 } 614 else 615 { 616 rc = RTErrConvertFromErrno(err); 617 Log(("RTTimerCreateEx: err=%d (%Rrc)\n", err, rc)); 618 } 619 564 620 RTMemFree(pTimer); 565 621 } … … 572 628 573 629 574 RTR3DECL(int) 630 RTR3DECL(int) RTTimerDestroy(PRTTIMER pTimer) 575 631 { 576 632 LogFlow(("RTTimerDestroy: pTimer=%p\n", pTimer)); … … 585 641 AssertPtrReturn(pTimer, VERR_INVALID_POINTER); 586 642 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 587 #ifndef IPRT_WITH_POSIX_TIMERS 643 #ifdef IPRT_WITH_POSIX_TIMERS 644 AssertReturn(g_TimerThread != RTThreadSelf(), VERR_INTERNAL_ERROR); 645 #else 588 646 AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR); 589 590 /* 591 * Tell the thread to terminate and wait for it do complete. 592 */ 593 ASMAtomicXchgU8(&pTimer->fDestroyed, true); 594 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); 647 #endif 648 649 /* 650 * Mark the semaphore as destroyed. 651 */ 652 ASMAtomicWriteU8(&pTimer->fDestroyed, true); 653 ASMAtomicWriteU32(&pTimer->u32Magic, ~RTTIMER_MAGIC); 654 655 #ifdef IPRT_WITH_POSIX_TIMERS 656 /* 657 * Suspend the timer if it's running. 658 */ 659 if (pTimer->fSuspended) 660 { 661 struct itimerspec TimerSpec; 662 TimerSpec.it_value.tv_sec = 0; 663 TimerSpec.it_value.tv_nsec = 0; 664 int err = timer_settime(pTimer->NativeTimer, 0, &TimerSpec, NULL); 665 AssertMsg(!err, ("%d\n", err)); 666 } 667 #endif 668 669 /* 670 * Poke the thread and wait for it to finish. 671 * This is only done for the last timer when using posix timers. 672 */ 673 #ifdef IPRT_WITH_POSIX_TIMERS 674 RTTHREAD Thread = NIL_RTTHREAD; 675 RTCritSectEnter(&g_TimerCritSect); 676 if (ASMAtomicDecU32(&g_cTimerInstances) == 0) 677 { 678 Thread = g_TimerThread; 679 g_TimerThread = NIL_RTTHREAD; 680 } 681 RTCritSectLeave(&g_TimerCritSect); 682 #else /* IPRT_WITH_POSIX_TIMERS */ 683 RTTHREAD Thread = pTimer->Thread; 595 684 rc = RTSemEventSignal(pTimer->Event); 596 685 AssertRC(rc); 597 if (!pTimer->fSuspended) 598 { 599 #ifndef RT_OS_OS2 600 pthread_kill((pthread_t)RTThreadGetNative(pTimer->Thread), SIGALRM); 601 #endif 602 } 603 rc = RTThreadWait(pTimer->Thread, 30 * 1000, NULL); 604 AssertRC(rc); 605 686 #endif /* IPRT_WITH_POSIX_TIMERS */ 687 if (Thread != NIL_RTTHREAD) 688 { 689 /* Signal it so it gets out of the sigwait if it's stuck there... */ 690 pthread_kill((pthread_t)RTThreadGetNative(Thread), RT_TIMER_SIGNAL); 691 692 /* 693 * Wait for the thread to complete. 694 */ 695 rc = RTThreadWait(Thread, 30 * 1000, NULL); 696 AssertRC(rc); 697 } 698 699 700 /* 701 * Free up the resources associated with the timer. 702 */ 703 #ifdef IPRT_WITH_POSIX_TIMERS 704 timer_delete(pTimer->NativeTimer); 705 #else 606 706 RTSemEventDestroy(pTimer->Event); 607 707 pTimer->Event = NIL_RTSEMEVENT; 608 #else /* IPRT_WITH_POSIX_TIMERS */ 609 if (ASMAtomicXchgU8(&pTimer->fDestroyed, true)) 610 { 611 /* It is already being destroyed by another thread. */ 612 return VINF_SUCCESS; 613 } 614 rc = RTErrConvertFromErrno(timer_delete(pTimer->timer)); 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 */ 708 #endif /* !IPRT_WITH_POSIX_TIMERS */ 626 709 if (RT_SUCCESS(rc)) 627 710 RTMemFree(pTimer); … … 639 722 #ifndef IPRT_WITH_POSIX_TIMERS 640 723 AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR); 724 #endif 641 725 642 726 /* 643 727 * Already running? 644 728 */ 645 if (! pTimer->fSuspended)729 if (!ASMAtomicXchgU8(&pTimer->fSuspended, false)) 646 730 return VERR_TIMER_ACTIVE; 647 731 LogFlow(("RTTimerStart: pTimer=%p u64First=%llu u64NanoInterval=%llu\n", pTimer, u64First, pTimer->u64NanoInterval)); 732 733 #ifndef IPRT_WITH_POSIX_TIMERS 648 734 /* 649 735 * Tell the thread to start servicing the timer. 736 * Wait for it to ACK the request to avoid reset races. 650 737 */ 651 738 RTThreadUserReset(pTimer->Thread); … … 662 749 else 663 750 AssertRC(rc); 751 752 #else /* IPRT_WITH_POSIX_TIMERS */ 753 /* 754 * Start the timer. 755 */ 756 struct itimerspec TimerSpec; 757 TimerSpec.it_value.tv_sec = u64First / 1000000000; /* nanosec => sec */ 758 TimerSpec.it_value.tv_nsec = u64First ? u64First % 1000000000 : 10; /* 0 means disable, replace it with 10. */ 759 TimerSpec.it_interval.tv_sec = pTimer->u64NanoInterval / 1000000000; 760 TimerSpec.it_interval.tv_nsec = pTimer->u64NanoInterval % 1000000000; 761 int err = timer_settime(pTimer->NativeTimer, 0, &TimerSpec, NULL); 762 int rc = RTErrConvertFromErrno(err); 763 #endif /* IPRT_WITH_POSIX_TIMERS */ 764 664 765 if (RT_FAILURE(rc)) 665 766 ASMAtomicXchgU8(&pTimer->fSuspended, false); 666 #else /* IPRT_WITH_POSIX_TIMERS */667 LogFlow(("RTTimerStart: pTimer=%p u64First=%llu u64NanoInterval=%llu\n", pTimer, u64First, pTimer->u64NanoInterval));668 669 struct itimerspec ts;670 671 if (!ASMAtomicXchgU8(&pTimer->fSuspended, false))672 return VERR_TIMER_ACTIVE;673 674 ts.it_value.tv_sec = u64First / 1000000000; /* nanosec => sec */675 ts.it_value.tv_nsec = u64First ? u64First % 1000000000 : 10; /* 0 means disable, replace it with 10. */676 ts.it_interval.tv_sec = pTimer->u64NanoInterval / 1000000000;677 ts.it_interval.tv_nsec = pTimer->u64NanoInterval % 1000000000;678 int rc = RTErrConvertFromErrno(timer_settime(pTimer->timer, 0, &ts, NULL));679 #endif /* IPRT_WITH_POSIX_TIMERS */680 681 767 return rc; 682 768 } … … 691 777 AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC); 692 778 779 /* 780 * Already running? 781 */ 782 if (ASMAtomicXchgU8(&pTimer->fSuspended, true)) 783 return VERR_TIMER_SUSPENDED; 784 LogFlow(("RTTimerStop: pTimer=%p\n", pTimer)); 785 693 786 #ifndef IPRT_WITH_POSIX_TIMERS 694 /*695 * Already running?696 */697 if (pTimer->fSuspended)698 return VERR_TIMER_SUSPENDED;699 700 787 /* 701 788 * Tell the thread to stop servicing the timer. … … 706 793 if (RTThreadSelf() != pTimer->Thread) 707 794 { 708 #ifndef RT_OS_OS2 709 pthread_kill((pthread_t)RTThreadGetNative(pTimer->Thread), SIGALRM); 710 #endif 795 pthread_kill((pthread_t)RTThreadGetNative(pTimer->Thread), RT_TIMER_SIGNAL); 711 796 rc = RTThreadUserWait(pTimer->Thread, 45*1000); 712 797 AssertRC(rc); 713 798 RTThreadUserReset(pTimer->Thread); 714 799 } 800 715 801 #else /* IPRT_WITH_POSIX_TIMERS */ 716 LogFlow(("RTTimerStop: pTimer=%p\n", pTimer)); 717 718 struct itimerspec ts; 719 720 if (ASMAtomicXchgU8(&pTimer->fSuspended, true)) 721 return VERR_TIMER_SUSPENDED; 722 723 ts.it_value.tv_sec = 0; 724 ts.it_value.tv_nsec = 0; 725 int rc = RTErrConvertFromErrno(timer_settime(pTimer->timer, 0, &ts, NULL)); 802 /* 803 * Stop the timer. 804 */ 805 struct itimerspec TimerSpec; 806 TimerSpec.it_value.tv_sec = 0; 807 TimerSpec.it_value.tv_nsec = 0; 808 int err = timer_settime(pTimer->NativeTimer, 0, &TimerSpec, NULL); 809 int rc = RTErrConvertFromErrno(err); 726 810 #endif /* IPRT_WITH_POSIX_TIMERS */ 727 811
Note:
See TracChangeset
for help on using the changeset viewer.