VirtualBox

Changeset 10941 in vbox for trunk/src/VBox/Runtime/r3/posix


Ignore:
Timestamp:
Jul 29, 2008 4:53:12 PM (16 years ago)
Author:
vboxsync
Message:

iprt/posix timers: Cleanup fixing the create/destroy races, a termination crash, and thread handle leak.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp

    r10920 r10941  
    3434/** Enables the use of POSIX RT timers. */
    3535#ifndef RT_OS_SOLARIS /* Solaris 10 doesn't have SIGEV_THREAD */
    36 #define IPRT_WITH_POSIX_TIMERS
     36# define IPRT_WITH_POSIX_TIMERS
    3737#endif /* !RT_OS_SOLARIS */
    3838
    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
    4049
    4150/*******************************************************************************
    4251*   Header Files                                                               *
    4352*******************************************************************************/
     53#define LOG_GROUP   RTLOGGROUP_TIMER
    4454#include <iprt/timer.h>
    4555#include <iprt/alloc.h>
     
    5060#include <iprt/semaphore.h>
    5161#include <iprt/string.h>
     62#include <iprt/once.h>
    5263#include <iprt/err.h>
     64#include <iprt/critsect.h>
    5365#include "internal/magics.h"
    5466
     
    6274#include <signal.h>
    6375#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*******************************************************************************/
    6882#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. */
     84static 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).  */
     88static 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 */
     94static uint32_t volatile g_cTimerInstances;
    7795/** 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 
     96static RTTHREAD g_TimerThread;
    8597#endif /* IPRT_WITH_POSIX_TIMERS */
     98
    8699
    87100/*******************************************************************************
     
    131144    int volatile            iError;
    132145#else /* IPRT_WITH_POSIX_TIMERS */
    133     timer_t                 timer;
     146    timer_t                 NativeTimer;
    134147#endif /* IPRT_WITH_POSIX_TIMERS */
    135148
    136149} 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 */
     163static DECLCALLBACK(int) rtTimerOnce(void *pvUser1, void *pvUser2)
     164{
     165    NOREF(pvUser1);
     166    NOREF(pvUser2);
     167    return RTCritSectInit(&g_TimerCritSect);
     168}
     169#endif
     170
    137171
    138172/**
     
    148182
    149183/**
    150  * SIGALRM wait thread.
     184 * RT_TIMER_SIGNAL wait thread.
    151185 */
    152186static DECLCALLBACK(int) rttimerThread(RTTHREAD Thread, void *pvArg)
     
    166200    sigemptyset(&SigAct.sa_mask);
    167201    SigAct.sa_handler = rttimerSignalIgnore;
    168     if (sigaction(SIGALRM, &SigAct, NULL))
     202    if (sigaction(RT_TIMER_SIGNAL, &SigAct, NULL))
    169203    {
    170204        SigAct.sa_flags &= ~SA_RESTART;
    171         if (sigaction(SIGALRM, &SigAct, NULL))
     205        if (sigaction(RT_TIMER_SIGNAL, &SigAct, NULL))
    172206            AssertMsgFailed(("sigaction failed, errno=%d\n", errno));
    173207    }
     
    189223    if (sigprocmask(SIG_SETMASK, &SigSet, NULL))
    190224    {
    191 #ifndef IPRT_WITH_POSIX_TIMERS
     225#ifdef IPRT_WITH_POSIX_TIMERS
     226        int rc = RTErrConvertFromErrno(errno);
     227#else
    192228        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
    196230        AssertMsgFailed(("sigprocmask -> errno=%d\n", errno));
    197231        return rc;
     
    216250            {
    217251                AssertRC(rc);
     252                if (pTimer->fDestroyed)
     253                    continue;
    218254                RTThreadSleep(1000); /* Don't cause trouble! */
    219255            }
     
    227263         *
    228264         * For some SunOS (/SysV?) threading compatibility Linux will only
    229          * deliver the SIGALRM to the thread calling setitimer(). Therefore
     265         * deliver the RT_TIMER_SIGNAL to the thread calling setitimer(). Therefore
    230266         * we have to call it here.
    231267         *
    232          * It turns out this might not always be the case, see SIGALRM killing
     268         * It turns out this might not always be the case, see RT_TIMER_SIGNAL killing
    233269         * processes on RH 2.4.21.
    234270         */
     
    271307         */
    272308        sigemptyset(&SigSet);
    273         sigaddset(&SigSet, SIGALRM);
     309        sigaddset(&SigSet, RT_TIMER_SIGNAL);
    274310        do
    275311        {
     
    281317            if (RT_LIKELY(sigwaitinfo(&SigSet, &SigInfo) >= 0))
    282318            {
    283                 if (RT_LIKELY(SigInfo.si_signo == SIGALRM))
     319                if (RT_LIKELY(SigInfo.si_signo == RT_TIMER_SIGNAL))
    284320#endif
    285321                {
     
    294330                    if (RT_UNLIKELY(!pTimer->u64NanoInterval))
    295331                    {
    296                         ASMAtomicXchgU8(&pTimer->fSuspended, true);
     332                        ASMAtomicWriteU8(&pTimer->fSuspended, true);
    297333                        break;
    298334                    }
     
    328364    RTThreadUserSignal(Thread);
    329365
    330     return VINF_SUCCESS;
    331 }
    332366#else /* IPRT_WITH_POSIX_TIMERS */
     367
    333368    sigemptyset(&SigSet);
    334369    sigaddset(&SigSet, RT_TIMER_SIGNAL);
     
    339374        {
    340375            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. */
    342378            {
    343379                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)
    347384                                ||  pTimer->u32Magic != RTTIMER_MAGIC))
    348385                    continue;
     386
    349387                pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick);
     388
    350389                /* auto suspend one-shot timers. */
    351390                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? */
    356392            }
    357393        }
    358394    }
     395#endif /* IPRT_WITH_POSIX_TIMERS */
    359396
    360397    return VINF_SUCCESS;
    361398}
    362399
    363 /**
    364  * Create the SIGALRM handling thread and wait for it to get
    365  * 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 
    383400
    384401RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
     
    400417        return VERR_NOT_IMPLEMENTED;
    401418    }
    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)
    405423    {
    406424        AssertMsgFailed(("A timer is running. System limit is one timer per process!\n"));
     
    410428
    411429    /*
    412      * Block SIGALRM from calling thread.
     430     * Block RT_TIMER_SIGNAL from calling thread.
    413431     */
    414432    sigset_t SigSet;
    415433    sigemptyset(&SigSet);
    416     sigaddset(&SigSet, SIGALRM);
     434    sigaddset(&SigSet, RT_TIMER_SIGNAL);
    417435    sigprocmask(SIG_BLOCK, &SigSet, NULL);
    418436
    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. */
    420438    /** @todo Move this RTC hack else where... */
    421439    static bool fDoneRTC;
     
    436454             */
    437455            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_LINUX
     456# ifdef RT_OS_LINUX
    439457            int fh = open("/dev/rtc", O_RDONLY);
    440458            if (fh >= 0)
     
    450468            else
    451469                Log(("RTTimerCreate: couldn't configure rtc! open failed with errno=%d\n", errno));
    452 #endif
     470# endif
    453471        }
    454472        /* disable it */
     
    506524                /* bail out */
    507525                ASMAtomicXchgU8(&pTimer->fDestroyed, true);
    508                 ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1);
     526                ASMAtomicXchgU32(&pTimer->u32Magic, ~RTTIMER_MAGIC);
    509527                RTThreadWait(pTimer->Thread, 45*1000, NULL);
    510528            }
     
    516534    else
    517535        rc = VERR_NO_MEMORY;
     536
    518537#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.
    521548     */
    522549    LogFlow(("RTTimerCreateEx: u64NanoInterval=%llu fFlags=%lu\n", u64NanoInterval, fFlags));
    523 
    524     int rc = VINF_SUCCESS;
    525550    PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
    526551    if (pTimer)
    527552    {
    528         struct sigevent  evt;
    529 
    530553        /* Initialize timer structure. */
    531554        pTimer->u32Magic        = RTTIMER_MAGIC;
     
    537560        pTimer->iTick           = 0;
    538561
    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)
    553578            {
     579                Assert(g_cTimerInstances > 1);
     580                RTCritSectLeave(&g_TimerCritSect);
     581
     582                LogFlow(("RTTimerCreateEx: rc=%Rrc pTimer=%p (thread already running)\n", rc, pTimer));
    554583                *ppTimer = pTimer;
    555584                return VINF_SUCCESS;
    556585            }
    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
    564620        RTMemFree(pTimer);
    565621    }
     
    572628
    573629
    574 RTR3DECL(int)     RTTimerDestroy(PRTTIMER pTimer)
     630RTR3DECL(int) RTTimerDestroy(PRTTIMER pTimer)
    575631{
    576632    LogFlow(("RTTimerDestroy: pTimer=%p\n", pTimer));
     
    585641    AssertPtrReturn(pTimer, VERR_INVALID_POINTER);
    586642    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
    588646    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;
    595684    rc = RTSemEventSignal(pTimer->Event);
    596685    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
    606706    RTSemEventDestroy(pTimer->Event);
    607707    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 */
    626709    if (RT_SUCCESS(rc))
    627710        RTMemFree(pTimer);
     
    639722#ifndef IPRT_WITH_POSIX_TIMERS
    640723    AssertReturn(pTimer->Thread != RTThreadSelf(), VERR_INTERNAL_ERROR);
     724#endif
    641725
    642726    /*
    643727     * Already running?
    644728     */
    645     if (!pTimer->fSuspended)
     729    if (!ASMAtomicXchgU8(&pTimer->fSuspended, false))
    646730        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
    648734    /*
    649735     * Tell the thread to start servicing the timer.
     736     * Wait for it to ACK the request to avoid reset races.
    650737     */
    651738    RTThreadUserReset(pTimer->Thread);
     
    662749    else
    663750        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
    664765    if (RT_FAILURE(rc))
    665766        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 
    681767    return rc;
    682768}
     
    691777    AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, VERR_INVALID_MAGIC);
    692778
     779    /*
     780     * Already running?
     781     */
     782    if (ASMAtomicXchgU8(&pTimer->fSuspended, true))
     783        return VERR_TIMER_SUSPENDED;
     784    LogFlow(("RTTimerStop: pTimer=%p\n", pTimer));
     785
    693786#ifndef IPRT_WITH_POSIX_TIMERS
    694     /*
    695      * Already running?
    696      */
    697     if (pTimer->fSuspended)
    698         return VERR_TIMER_SUSPENDED;
    699 
    700787    /*
    701788     * Tell the thread to stop servicing the timer.
     
    706793    if (RTThreadSelf() != pTimer->Thread)
    707794    {
    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);
    711796        rc = RTThreadUserWait(pTimer->Thread, 45*1000);
    712797        AssertRC(rc);
    713798        RTThreadUserReset(pTimer->Thread);
    714799    }
     800
    715801#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);
    726810#endif /* IPRT_WITH_POSIX_TIMERS */
    727811
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette