VirtualBox

Changeset 1781 in vbox


Ignore:
Timestamp:
Mar 28, 2007 4:46:12 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
19953
Message:

Split out generic/RTTimerCreate-generic.cpp from generic/timer-generic.cpp.

Location:
trunk/src/VBox/Runtime
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile

    r1632 r1781  
    326326        generic/RTFileMove-generic.cpp \
    327327        generic/RTLogWriteDebugger-generic.cpp \
     328        generic/RTTimerCreate-generic.cpp \
    328329        generic/pathhost-generic.cpp \
    329330        generic/sched-generic.cpp \
     
    708709RuntimeR0Drv_SOURCES.darwin = \
    709710        generic/RTAssertDoBreakpoint-generic.cpp \
     711        generic/RTTimerCreate-generic.cpp \
    710712        RTErrConvertFromErrno.cpp \
    711713        string/memchr.asm \
  • trunk/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp

    r1716 r1781  
    11/** $Id$ */
    22/** @file
    3  * InnoTek Portable Runtime - Timers, Generic.
     3 * InnoTek Portable Runtime - Timers, Generic RTTimerCreate() Implementation.
    44 */
    55
     
    2525*******************************************************************************/
    2626#include <iprt/timer.h>
    27 #include <iprt/thread.h>
    2827#include <iprt/err.h>
    2928#include <iprt/assert.h>
    30 #include <iprt/alloc.h>
    31 #include <iprt/asm.h>
    32 #include <iprt/semaphore.h>
    33 #include <iprt/time.h>
    34 #include <iprt/log.h>
    35 
    36 
    37 
    38 /*******************************************************************************
    39 *   Structures and Typedefs                                                    *
    40 *******************************************************************************/
    41 /**
    42  * The internal representation of a timer handle.
    43  */
    44 typedef struct RTTIMER
    45 {
    46     /** Magic.
    47      * This is RTTIMER_MAGIC, but changes to something else before the timer
    48      * is destroyed to indicate clearly that thread should exit. */
    49     uint32_t volatile       u32Magic;
    50     /** Flag indicating the the timer is suspended. */
    51     uint8_t volatile        fSuspended;
    52     /** Flag indicating that the timer has been destroyed. */
    53     uint8_t volatile        fDestroyed;
    54     /** Callback. */
    55     PFNRTTIMER              pfnTimer;
    56     /** User argument. */
    57     void                   *pvUser;
    58     /** The timer thread. */
    59     RTTHREAD                Thread;
    60     /** Event semaphore on which the thread is blocked. */
    61     RTSEMEVENT              Event;
    62     /** The timer interval. 0 if one-shot. */
    63     uint64_t                u64NanoInterval;
    64     /** The start of the current run.
    65      * This is used to calculate when the timer ought to fire the next time. */
    66     uint64_t volatile       u64StartTS;
    67     /** The start of the current run.
    68      * This is used to calculate when the timer ought to fire the next time. */
    69     uint64_t volatile       u64NextTS;
    70     /** The current tick number (since u64StartTS). */
    71     uint64_t volatile       iTick;
    72 } RTTIMER;
    73 /** Magic number for timer handles. (Jared Mason Diamond) */
    74 #define RTTIMER_MAGIC       0x19370910
    75 
    76 
    77 /*******************************************************************************
    78 *   Internal Functions                                                         *
    79 *******************************************************************************/
    80 static DECLCALLBACK(int) rtTimerThread(RTTHREAD Thread, void *pvUser);
    8129
    8230
     
    9543}
    9644
    97 
    98 RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
    99 {
    100     *ppTimer = NULL;
    101 
    102     /*
    103      * Allocate and initialize the timer handle.
    104      */
    105     PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
    106     if (!pTimer)
    107         return VERR_NO_MEMORY;
    108 
    109     pTimer->u32Magic = RTTIMER_MAGIC;
    110     pTimer->fSuspended = true;
    111     pTimer->fDestroyed = false;
    112     pTimer->pfnTimer = pfnTimer;
    113     pTimer->pvUser = pvUser;
    114     pTimer->Thread = NIL_RTTHREAD;
    115     pTimer->Event = NIL_RTSEMEVENT;
    116     pTimer->u64NanoInterval = u64NanoInterval;
    117     pTimer->u64StartTS = 0;
    118 
    119     int rc = RTSemEventCreate(&pTimer->Event);
    120     if (RT_SUCCESS(rc))
    121     {
    122         rc = RTThreadCreate(&pTimer->Thread, rtTimerThread, pTimer, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "TIMER");
    123         if (RT_SUCCESS(rc))
    124         {
    125             *ppTimer = pTimer;
    126             return VINF_SUCCESS;
    127         }
    128 
    129         pTimer->u32Magic = 0;
    130         RTSemEventDestroy(pTimer->Event);
    131         pTimer->Event = NIL_RTSEMEVENT;
    132     }
    133     RTMemFree(pTimer);
    134 
    135     return rc;
    136 }
    137 
    138 
    139 /**
    140  * Validates the timer handle.
    141  *
    142  * @returns true if valid, false if invalid.
    143  * @param   pTimer  The handle.
    144  */
    145 DECLINLINE(bool) rtTimerIsValid(PRTTIMER pTimer)
    146 {
    147     AssertReturn(VALID_PTR(pTimer), false);
    148     AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, false);
    149     AssertReturn(!pTimer->fDestroyed, false);
    150     return true;
    151 }
    152 
    153 
    154 RTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
    155 {
    156     /* It's ok to pass NULL pointer. */
    157     if (pTimer == /*NIL_RTTIMER*/ NULL)
    158         return VINF_SUCCESS;
    159     if (!rtTimerIsValid(pTimer))
    160         return VERR_INVALID_HANDLE;
    161 
    162     /*
    163      * If the timer is active, we just flag it to self destruct on the next tick.
    164      * If it's suspended we can safely set the destroy flag and signal it.
    165      */
    166     RTTHREAD Thread = pTimer->Thread;
    167     if (!pTimer->fSuspended)
    168     {
    169         ASMAtomicXchgU8(&pTimer->fSuspended, true);
    170         ASMAtomicXchgU8(&pTimer->fDestroyed, true);
    171     }
    172     else
    173     {
    174         ASMAtomicXchgU8(&pTimer->fDestroyed, true);
    175         int rc = RTSemEventSignal(pTimer->Event);
    176         if (rc == VERR_ALREADY_POSTED)
    177             rc = VINF_SUCCESS;
    178         AssertRC(rc);
    179     }
    180 
    181     RTThreadWait(Thread, 250, NULL);
    182     return VINF_SUCCESS;
    183 }
    184 
    185 
    186 RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
    187 {
    188     if (!rtTimerIsValid(pTimer))
    189         return VERR_INVALID_HANDLE;
    190     if (!pTimer->fSuspended)
    191         return VERR_TIMER_ACTIVE;
    192 
    193     /*
    194      * Calc when it should start fireing and give the thread a kick so it get going.
    195      */
    196     u64First += RTTimeNanoTS();
    197     ASMAtomicXchgU64(&pTimer->iTick, 0);
    198     ASMAtomicXchgU64(&pTimer->u64StartTS, u64First);
    199     ASMAtomicXchgU64(&pTimer->u64NextTS, u64First);
    200     ASMAtomicXchgU8(&pTimer->fSuspended, false);
    201     int rc = RTSemEventSignal(pTimer->Event);
    202     if (rc == VERR_ALREADY_POSTED)
    203         rc = VINF_SUCCESS;
    204     AssertRC(rc);
    205     return rc;
    206 }
    207 
    208 
    209 RTDECL(int) RTTimerStop(PRTTIMER pTimer)
    210 {
    211     if (!rtTimerIsValid(pTimer))
    212         return VERR_INVALID_HANDLE;
    213     if (pTimer->fSuspended)
    214         return VERR_TIMER_SUSPENDED;
    215 
    216     /*
    217      * Mark it as suspended and kick the thread.
    218      */
    219     ASMAtomicXchgU8(&pTimer->fSuspended, true);
    220     int rc = RTSemEventSignal(pTimer->Event);
    221     if (rc == VERR_ALREADY_POSTED)
    222         rc = VINF_SUCCESS;
    223     AssertRC(rc);
    224     return rc;
    225 }
    226 
    227 
    228 static DECLCALLBACK(int) rtTimerThread(RTTHREAD Thread, void *pvUser)
    229 {
    230     PRTTIMER pTimer = (PRTTIMER)pvUser;
    231 
    232     /*
    233      * The loop.
    234      */
    235     while (!pTimer->fDestroyed)
    236     {
    237         if (pTimer->fSuspended)
    238         {
    239             int rc = RTSemEventWait(pTimer->Event, RT_INDEFINITE_WAIT);
    240             if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED)
    241             {
    242                 AssertRC(rc);
    243                 RTThreadSleep(1000); /* Don't cause trouble! */
    244             }
    245         }
    246         else
    247         {
    248             const uint64_t u64NanoTS = RTTimeNanoTS();
    249             if (u64NanoTS >= pTimer->u64NextTS)
    250             {
    251                 pTimer->iTick++;
    252                 pTimer->pfnTimer(pTimer, pTimer->pvUser);
    253 
    254                 /* status changed? */
    255                 if (pTimer->fSuspended || pTimer->fDestroyed)
    256                     continue;
    257 
    258                 /* one shot? */
    259                 if (!pTimer->u64NanoInterval)
    260                 {
    261                     ASMAtomicXchgU8(&pTimer->fSuspended, true);
    262                     continue;
    263                 }
    264 
    265                 /* calc the next time we should fire. */
    266                 pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval;
    267                 if (pTimer->u64NextTS < u64NanoTS)
    268 #ifdef IN_RING3 /* In ring-3 we'll catch up lost ticks immediately. */
    269                     pTimer->u64NextTS = u64NanoTS + 1;
    270 #else
    271                     pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2;
    272 #endif
    273             }
    274 
    275             /* block. */
    276             uint64_t cNanoSeconds = pTimer->u64NextTS - u64NanoTS;
    277 #ifdef IN_RING3 /* In ring-3 we'll catch up lost ticks immediately. */
    278             if (cNanoSeconds > 10)
    279 #endif
    280             {
    281                 int rc = RTSemEventWait(pTimer->Event, cNanoSeconds < 1000000 ? 1 : cNanoSeconds / 1000000);
    282                 if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED && rc != VERR_TIMEOUT)
    283                 {
    284                     AssertRC(rc);
    285                     RTThreadSleep(1000); /* Don't cause trouble! */
    286                 }
    287             }
    288         }
    289     }
    290 
    291     /*
    292      * Release the timer resources.
    293      */
    294     ASMAtomicIncU32(&pTimer->u32Magic); /* make the handle invalid. */
    295     int rc = RTSemEventDestroy(pTimer->Event); AssertRC(rc);
    296     pTimer->Event = NIL_RTSEMEVENT;
    297     pTimer->Thread = NIL_RTTHREAD;
    298     RTMemFree(pTimer);
    299 
    300     return VINF_SUCCESS;
    301 }
    302 
    303 
    304 
    305 
    306 RTDECL(uint32_t) RTTimerGetSystemGranularity(void)
    307 {
    308     return 10000000; /* 10ms */
    309 }
    310 
    311 
    312 RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
    313 {
    314     return VERR_NOT_SUPPORTED;
    315 }
    316 
    317 
    318 RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
    319 {
    320     return VERR_NOT_SUPPORTED;
    321 }
    322 
  • trunk/src/VBox/Runtime/generic/timer-generic.cpp

    r1536 r1781  
    8181
    8282
    83 RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser)
    84 {
    85     int rc = RTTimerCreateEx(ppTimer, uMilliesInterval * UINT64_C(1000000), 0, pfnTimer, pvUser);
    86     if (RT_SUCCESS(rc))
    87     {
    88         rc = RTTimerStart(*ppTimer, 0);
    89         if (RT_SUCCESS(rc))
    90             return rc;
    91         int rc2 = RTTimerDestroy(*ppTimer); AssertRC(rc2);
    92         *ppTimer = NULL;
    93     }
    94     return rc;
    95 }
    96 
    97 
    9883RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
    9984{
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