        -:    0:Source:../../../os/rt/include/chvt.h
        -:    0:Programs:17
        -:    1:/*
        -:    2:    ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio.
        -:    3:
        -:    4:    This file is part of ChibiOS.
        -:    5:
        -:    6:    ChibiOS is free software; you can redistribute it and/or modify
        -:    7:    it under the terms of the GNU General Public License as published by
        -:    8:    the Free Software Foundation; either version 3 of the License, or
        -:    9:    (at your option) any later version.
        -:   10:
        -:   11:    ChibiOS is distributed in the hope that it will be useful,
        -:   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
        -:   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        -:   14:    GNU General Public License for more details.
        -:   15:
        -:   16:    You should have received a copy of the GNU General Public License
        -:   17:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
        -:   18:*/
        -:   19:
        -:   20:/**
        -:   21: * @file    chvt.h
        -:   22: * @brief   Time and Virtual Timers module macros and structures.
        -:   23: *
        -:   24: * @addtogroup time
        -:   25: * @{
        -:   26: */
        -:   27:
        -:   28:#ifndef _CHVT_H_
        -:   29:#define _CHVT_H_
        -:   30:
        -:   31:/*===========================================================================*/
        -:   32:/* Module constants.                                                         */
        -:   33:/*===========================================================================*/
        -:   34:
        -:   35:/**
        -:   36: * @name    Special time constants
        -:   37: * @{
        -:   38: */
        -:   39:/**
        -:   40: * @brief   Zero time specification for some functions with a timeout
        -:   41: *          specification.
        -:   42: * @note    Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
        -:   43: *          see the specific function documentation.
        -:   44: */
        -:   45:#define TIME_IMMEDIATE  ((systime_t)0)
        -:   46:
        -:   47:/**
        -:   48: * @brief   Infinite time specification for all functions with a timeout
        -:   49: *          specification.
        -:   50: * @note    Not all functions accept @p TIME_INFINITE as timeout parameter,
        -:   51: *          see the specific function documentation.
        -:   52: */
        -:   53:#define TIME_INFINITE   ((systime_t)-1)
        -:   54:/** @} */
        -:   55:
        -:   56:/*===========================================================================*/
        -:   57:/* Module pre-compile time settings.                                         */
        -:   58:/*===========================================================================*/
        -:   59:
        -:   60:/*===========================================================================*/
        -:   61:/* Derived constants and error checks.                                       */
        -:   62:/*===========================================================================*/
        -:   63:
        -:   64:#if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32)
        -:   65:#error "invalid CH_CFG_ST_RESOLUTION specified, must be 16 or 32"
        -:   66:#endif
        -:   67:
        -:   68:#if CH_CFG_ST_FREQUENCY <= 0
        -:   69:#error "invalid CH_CFG_ST_FREQUENCY specified, must be greater than zero"
        -:   70:#endif
        -:   71:
        -:   72:#if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
        -:   73:#error "invalid CH_CFG_ST_TIMEDELTA specified, must "                       \
        -:   74:       "be zero or greater than one"
        -:   75:#endif
        -:   76:
        -:   77:#if (CH_CFG_ST_TIMEDELTA > 0) && (CH_CFG_TIME_QUANTUM > 0)
        -:   78:#error "CH_CFG_TIME_QUANTUM not supported in tickless mode"
        -:   79:#endif
        -:   80:
        -:   81:#if (CH_CFG_ST_TIMEDELTA > 0) && (CH_DBG_THREADS_PROFILING == TRUE)
        -:   82:#error "CH_DBG_THREADS_PROFILING not supported in tickless mode"
        -:   83:#endif
        -:   84:
        -:   85:/*===========================================================================*/
        -:   86:/* Module data structures and types.                                         */
        -:   87:/*===========================================================================*/
        -:   88:
        -:   89:/*===========================================================================*/
        -:   90:/* Module macros.                                                            */
        -:   91:/*===========================================================================*/
        -:   92:
        -:   93:/**
        -:   94: * @name    Time conversion utilities
        -:   95: * @{
        -:   96: */
        -:   97:/**
        -:   98: * @brief   Seconds to system ticks.
        -:   99: * @details Converts from seconds to system ticks number.
        -:  100: * @note    The result is rounded upward to the next tick boundary.
        -:  101: *
        -:  102: * @param[in] sec       number of seconds
        -:  103: * @return              The number of ticks.
        -:  104: *
        -:  105: * @api
        -:  106: */
        -:  107:#define S2ST(sec)                                                           \
        -:  108:  ((systime_t)((uint32_t)(sec) * (uint32_t)CH_CFG_ST_FREQUENCY))
        -:  109:
        -:  110:/**
        -:  111: * @brief   Milliseconds to system ticks.
        -:  112: * @details Converts from milliseconds to system ticks number.
        -:  113: * @note    The result is rounded upward to the next tick boundary.
        -:  114: *
        -:  115: * @param[in] msec      number of milliseconds
        -:  116: * @return              The number of ticks.
        -:  117: *
        -:  118: * @api
        -:  119: */
        -:  120:#define MS2ST(msec)                                                         \
        -:  121:  ((systime_t)(((((uint32_t)(msec)) *                                       \
        -:  122:                 ((uint32_t)CH_CFG_ST_FREQUENCY)) + 999UL) / 1000UL))
        -:  123:
        -:  124:/**
        -:  125: * @brief   Microseconds to system ticks.
        -:  126: * @details Converts from microseconds to system ticks number.
        -:  127: * @note    The result is rounded upward to the next tick boundary.
        -:  128: *
        -:  129: * @param[in] usec      number of microseconds
        -:  130: * @return              The number of ticks.
        -:  131: *
        -:  132: * @api
        -:  133: */
        -:  134:#define US2ST(usec)                                                         \
        -:  135:  ((systime_t)(((((uint32_t)(usec)) *                                       \
        -:  136:                 ((uint32_t)CH_CFG_ST_FREQUENCY)) + 999999UL) / 1000000UL))
        -:  137:
        -:  138:/**
        -:  139: * @brief   System ticks to seconds.
        -:  140: * @details Converts from system ticks number to seconds.
        -:  141: * @note    The result is rounded up to the next second boundary.
        -:  142: *
        -:  143: * @param[in] n         number of system ticks
        -:  144: * @return              The number of seconds.
        -:  145: *
        -:  146: * @api
        -:  147: */
        -:  148:#define ST2S(n) (((n) + CH_CFG_ST_FREQUENCY - 1UL) / CH_CFG_ST_FREQUENCY)
        -:  149:
        -:  150:/**
        -:  151: * @brief   System ticks to milliseconds.
        -:  152: * @details Converts from system ticks number to milliseconds.
        -:  153: * @note    The result is rounded up to the next millisecond boundary.
        -:  154: *
        -:  155: * @param[in] n         number of system ticks
        -:  156: * @return              The number of milliseconds.
        -:  157: *
        -:  158: * @api
        -:  159: */
        -:  160:#define ST2MS(n) (((n) * 1000UL + CH_CFG_ST_FREQUENCY - 1UL) /              \
        -:  161:                  CH_CFG_ST_FREQUENCY)
        -:  162:
        -:  163:/**
        -:  164: * @brief   System ticks to microseconds.
        -:  165: * @details Converts from system ticks number to microseconds.
        -:  166: * @note    The result is rounded up to the next microsecond boundary.
        -:  167: *
        -:  168: * @param[in] n         number of system ticks
        -:  169: * @return              The number of microseconds.
        -:  170: *
        -:  171: * @api
        -:  172: */
        -:  173:#define ST2US(n) (((n) * 1000000UL + CH_CFG_ST_FREQUENCY - 1UL) /           \
        -:  174:                  CH_CFG_ST_FREQUENCY)
        -:  175:/** @} */
        -:  176:
        -:  177:/*===========================================================================*/
        -:  178:/* External declarations.                                                    */
        -:  179:/*===========================================================================*/
        -:  180:
        -:  181:/*
        -:  182: * Virtual Timers APIs.
        -:  183: */
        -:  184:#ifdef __cplusplus
        -:  185:extern "C" {
        -:  186:#endif
        -:  187:  void _vt_init(void);
        -:  188:  void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
        -:  189:                  vtfunc_t vtfunc, void *par);
        -:  190:  void chVTDoResetI(virtual_timer_t *vtp);
        -:  191:#ifdef __cplusplus
        -:  192:}
        -:  193:#endif
        -:  194:
        -:  195:/*===========================================================================*/
        -:  196:/* Module inline functions.                                                  */
        -:  197:/*===========================================================================*/
        -:  198:
        -:  199:/**
        -:  200: * @brief   Initializes a @p virtual_timer_t object.
        -:  201: * @note    Initializing a timer object is not strictly required because
        -:  202: *          the function @p chVTSetI() initializes the object too. This
        -:  203: *          function is only useful if you need to perform a @p chVTIsArmed()
        -:  204: *          check before calling @p chVTSetI().
        -:  205: *
        -:  206: * @param[out] vtp      the @p virtual_timer_t structure pointer
        -:  207: *
        -:  208: * @init
        -:  209: */
        -:  210:static inline void chVTObjectInit(virtual_timer_t *vtp) {
        -:  211:
        -:  212:  vtp->vt_func = NULL;
        -:  213:}
        -:  214:
        -:  215:/**
        -:  216: * @brief   Current system time.
        -:  217: * @details Returns the number of system ticks since the @p chSysInit()
        -:  218: *          invocation.
        -:  219: * @note    The counter can reach its maximum and then restart from zero.
        -:  220: * @note    This function can be called from any context but its atomicity
        -:  221: *          is not guaranteed on architectures whose word size is less than
        -:  222: *          @p systime_t size.
        -:  223: *
        -:  224: * @return              The system time in ticks.
        -:  225: *
        -:  226: * @xclass
        -:  227: */
function chVTGetSystemTimeX called 1 returned 100% blocks executed 100%
        1:  228:static inline systime_t chVTGetSystemTimeX(void) {
        -:  229:
        -:  230:#if CH_CFG_ST_TIMEDELTA == 0
        1:  231:  return ch.vtlist.vt_systime;
unconditional  0 taken 100%
        -:  232:#else /* CH_CFG_ST_TIMEDELTA > 0 */
        -:  233:  return port_timer_get_time();
        -:  234:#endif /* CH_CFG_ST_TIMEDELTA > 0 */
        -:  235:}
        -:  236:
        -:  237:/**
        -:  238: * @brief   Current system time.
        -:  239: * @details Returns the number of system ticks since the @p chSysInit()
        -:  240: *          invocation.
        -:  241: * @note    The counter can reach its maximum and then restart from zero.
        -:  242: *
        -:  243: * @return              The system time in ticks.
        -:  244: *
        -:  245: * @api
        -:  246: */
        -:  247:static inline systime_t chVTGetSystemTime(void) {
        -:  248:  systime_t systime;
        -:  249:
        -:  250:  chSysLock();
        -:  251:  systime = chVTGetSystemTimeX();
        -:  252:  chSysUnlock();
        -:  253:
        -:  254:  return systime;
        -:  255:}
        -:  256:
        -:  257:/**
        -:  258: * @brief   Returns the elapsed time since the specified start time.
        -:  259: *
        -:  260: * @param[in] start     start time
        -:  261: * @return              The elapsed time.
        -:  262: *
        -:  263: * @xclass
        -:  264: */
        -:  265:static inline systime_t chVTTimeElapsedSinceX(systime_t start) {
        -:  266:
        -:  267:  return chVTGetSystemTimeX() - start;
        -:  268:}
        -:  269:
        -:  270:/**
        -:  271: * @brief   Checks if the specified time is within the specified time window.
        -:  272: * @note    When start==end then the function returns always true because the
        -:  273: *          whole time range is specified.
        -:  274: * @note    This function can be called from any context.
        -:  275: *
        -:  276: * @param[in] time      the time to be verified
        -:  277: * @param[in] start     the start of the time window (inclusive)
        -:  278: * @param[in] end       the end of the time window (non inclusive)
        -:  279: * @retval true         current time within the specified time window.
        -:  280: * @retval false        current time not within the specified time window.
        -:  281: *
        -:  282: * @xclass
        -:  283: */
function chVTIsTimeWithinX called 0 returned 0% blocks executed 0%
    #####:  284:static inline bool chVTIsTimeWithinX(systime_t time,
        -:  285:                                     systime_t start,
        -:  286:                                     systime_t end) {
        -:  287:
    #####:  288:  return (bool)((systime_t)(time - start) < (systime_t)(end - start));
unconditional  0 never executed
        -:  289:}
        -:  290:
        -:  291:/**
        -:  292: * @brief   Checks if the current system time is within the specified time
        -:  293: *          window.
        -:  294: * @note    When start==end then the function returns always true because the
        -:  295: *          whole time range is specified.
        -:  296: *
        -:  297: * @param[in] start     the start of the time window (inclusive)
        -:  298: * @param[in] end       the end of the time window (non inclusive)
        -:  299: * @retval true         current time within the specified time window.
        -:  300: * @retval false        current time not within the specified time window.
        -:  301: *
        -:  302: * @xclass
        -:  303: */
        -:  304:static inline bool chVTIsSystemTimeWithinX(systime_t start, systime_t end) {
        -:  305:
        -:  306:  return chVTIsTimeWithinX(chVTGetSystemTimeX(), start, end);
        -:  307:}
        -:  308:
        -:  309:/**
        -:  310: * @brief   Checks if the current system time is within the specified time
        -:  311: *          window.
        -:  312: * @note    When start==end then the function returns always true because the
        -:  313: *          whole time range is specified.
        -:  314: *
        -:  315: * @param[in] start     the start of the time window (inclusive)
        -:  316: * @param[in] end       the end of the time window (non inclusive)
        -:  317: * @retval true         current time within the specified time window.
        -:  318: * @retval false        current time not within the specified time window.
        -:  319: *
        -:  320: * @api
        -:  321: */
        -:  322:static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) {
        -:  323:
        -:  324:  return chVTIsTimeWithinX(chVTGetSystemTime(), start, end);
        -:  325:}
        -:  326:
        -:  327:/**
        -:  328: * @brief   Returns the time interval until the next timer event.
        -:  329: * @note    The return value is not perfectly accurate and can report values
        -:  330: *          in excess of @p CH_CFG_ST_TIMEDELTA ticks.
        -:  331: * @note    The interval returned by this function is only meaningful if
        -:  332: *          more timers are not added to the list until the returned time.
        -:  333: *
        -:  334: * @param[out] timep    pointer to a variable that will contain the time
        -:  335: *                      interval until the next timer elapses. This pointer
        -:  336: *                      can be @p NULL if the information is not required.
        -:  337: * @return              The time, in ticks, until next time event.
        -:  338: * @retval false        if the timers list is empty.
        -:  339: * @retval true         if the timers list contains at least one timer.
        -:  340: *
        -:  341: * @iclass
        -:  342: */
        -:  343:static inline bool chVTGetTimersStateI(systime_t *timep) {
        -:  344:
        -:  345:  chDbgCheckClassI();
        -:  346:
        -:  347:  if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.vt_next) {
        -:  348:    return false;
        -:  349:  }
        -:  350:
        -:  351:  if (timep != NULL) {
        -:  352:#if CH_CFG_ST_TIMEDELTA == 0
        -:  353:    *timep = ch.vtlist.vt_next->vt_delta;
        -:  354:#else
        -:  355:    *timep = ch.vtlist.vt_lasttime + ch.vtlist.vt_next->vt_delta +
        -:  356:             CH_CFG_ST_TIMEDELTA - chVTGetSystemTimeX();
        -:  357:#endif
        -:  358:  }
        -:  359:
        -:  360:  return true;
        -:  361:}
        -:  362:
        -:  363:/**
        -:  364: * @brief   Returns @p true if the specified timer is armed.
        -:  365: * @pre     The timer must have been initialized using @p chVTObjectInit()
        -:  366: *          or @p chVTDoSetI().
        -:  367: *
        -:  368: * @param[in] vtp       the @p virtual_timer_t structure pointer
        -:  369: * @return              true if the timer is armed.
        -:  370: *
        -:  371: * @iclass
        -:  372: */
function chVTIsArmedI called 62 returned 100% blocks executed 100%
       62:  373:static inline bool chVTIsArmedI(virtual_timer_t *vtp) {
        -:  374:
        -:  375:  chDbgCheckClassI();
        -:  376:
       62:  377:  return (bool)(vtp->vt_func != NULL);
unconditional  0 taken 100%
        -:  378:}
        -:  379:
        -:  380:/**
        -:  381: * @brief   Returns @p true if the specified timer is armed.
        -:  382: * @pre     The timer must have been initialized using @p chVTObjectInit()
        -:  383: *          or @p chVTDoSetI().
        -:  384: *
        -:  385: * @param[in] vtp       the @p virtual_timer_t structure pointer
        -:  386: * @return              true if the timer is armed.
        -:  387: *
        -:  388: * @api
        -:  389: */
        -:  390:static inline bool chVTIsArmed(virtual_timer_t *vtp) {
        -:  391:  bool b;
        -:  392:
        -:  393:  chSysLock();
        -:  394:  b = chVTIsArmedI(vtp);
        -:  395:  chSysUnlock();
        -:  396:
        -:  397:  return b;
        -:  398:}
        -:  399:
        -:  400:/**
        -:  401: * @brief   Disables a Virtual Timer.
        -:  402: * @note    The timer is first checked and disabled only if armed.
        -:  403: * @pre     The timer must have been initialized using @p chVTObjectInit()
        -:  404: *          or @p chVTDoSetI().
        -:  405: *
        -:  406: * @param[in] vtp       the @p virtual_timer_t structure pointer
        -:  407: *
        -:  408: * @iclass
        -:  409: */
        -:  410:static inline void chVTResetI(virtual_timer_t *vtp) {
        -:  411:
        -:  412:  if (chVTIsArmedI(vtp)) {
        -:  413:    chVTDoResetI(vtp);
        -:  414:  }
        -:  415:}
        -:  416:
        -:  417:/**
        -:  418: * @brief   Disables a Virtual Timer.
        -:  419: * @note    The timer is first checked and disabled only if armed.
        -:  420: * @pre     The timer must have been initialized using @p chVTObjectInit()
        -:  421: *          or @p chVTDoSetI().
        -:  422: *
        -:  423: * @param[in] vtp       the @p virtual_timer_t structure pointer
        -:  424: *
        -:  425: * @api
        -:  426: */
        -:  427:static inline void chVTReset(virtual_timer_t *vtp) {
        -:  428:
        -:  429:  chSysLock();
        -:  430:  chVTResetI(vtp);
        -:  431:  chSysUnlock();
        -:  432:}
        -:  433:
        -:  434:/**
        -:  435: * @brief   Enables a virtual timer.
        -:  436: * @details If the virtual timer was already enabled then it is re-enabled
        -:  437: *          using the new parameters.
        -:  438: * @pre     The timer must have been initialized using @p chVTObjectInit()
        -:  439: *          or @p chVTDoSetI().
        -:  440: *
        -:  441: * @param[in] vtp       the @p virtual_timer_t structure pointer
        -:  442: * @param[in] delay     the number of ticks before the operation timeouts, the
        -:  443: *                      special values are handled as follow:
        -:  444: *                      - @a TIME_INFINITE is allowed but interpreted as a
        -:  445: *                        normal time specification.
        -:  446: *                      - @a TIME_IMMEDIATE this value is not allowed.
        -:  447: *                      .
        -:  448: * @param[in] vtfunc    the timer callback function. After invoking the
        -:  449: *                      callback the timer is disabled and the structure can
        -:  450: *                      be disposed or reused.
        -:  451: * @param[in] par       a parameter that will be passed to the callback
        -:  452: *                      function
        -:  453: *
        -:  454: * @iclass
        -:  455: */
        -:  456:static inline void chVTSetI(virtual_timer_t *vtp, systime_t delay,
        -:  457:                            vtfunc_t vtfunc, void *par) {
        -:  458:
        -:  459:  chVTResetI(vtp);
        -:  460:  chVTDoSetI(vtp, delay, vtfunc, par);
        -:  461:}
        -:  462:
        -:  463:/**
        -:  464: * @brief   Enables a virtual timer.
        -:  465: * @details If the virtual timer was already enabled then it is re-enabled
        -:  466: *          using the new parameters.
        -:  467: * @pre     The timer must have been initialized using @p chVTObjectInit()
        -:  468: *          or @p chVTDoSetI().
        -:  469: *
        -:  470: * @param[in] vtp       the @p virtual_timer_t structure pointer
        -:  471: * @param[in] delay     the number of ticks before the operation timeouts, the
        -:  472: *                      special values are handled as follow:
        -:  473: *                      - @a TIME_INFINITE is allowed but interpreted as a
        -:  474: *                        normal time specification.
        -:  475: *                      - @a TIME_IMMEDIATE this value is not allowed.
        -:  476: *                      .
        -:  477: * @param[in] vtfunc    the timer callback function. After invoking the
        -:  478: *                      callback the timer is disabled and the structure can
        -:  479: *                      be disposed or reused.
        -:  480: * @param[in] par       a parameter that will be passed to the callback
        -:  481: *                      function
        -:  482: *
        -:  483: * @api
        -:  484: */
        -:  485:static inline void chVTSet(virtual_timer_t *vtp, systime_t delay,
        -:  486:                           vtfunc_t vtfunc, void *par) {
        -:  487:
        -:  488:  chSysLock();
        -:  489:  chVTSetI(vtp, delay, vtfunc, par);
        -:  490:  chSysUnlock();
        -:  491:}
        -:  492:
        -:  493:/**
        -:  494: * @brief   Virtual timers ticker.
        -:  495: * @note    The system lock is released before entering the callback and
        -:  496: *          re-acquired immediately after. It is callback's responsibility
        -:  497: *          to acquire the lock if needed. This is done in order to reduce
        -:  498: *          interrupts jitter when many timers are in use.
        -:  499: *
        -:  500: * @iclass
        -:  501: */
function chVTDoTickI called 15092 returned 100% blocks executed 100%
    15092:  502:static inline void chVTDoTickI(void) {
        -:  503:
        -:  504:  chDbgCheckClassI();
        -:  505:
        -:  506:#if CH_CFG_ST_TIMEDELTA == 0
    15092:  507:  ch.vtlist.vt_systime++;
    15092:  508:  if (&ch.vtlist != (virtual_timers_list_t *)ch.vtlist.vt_next) {
branch  0 taken 99% (fallthrough)
branch  1 taken 1%
        -:  509:    /* The list is not empty, processing elements on top.*/
    14972:  510:    --ch.vtlist.vt_next->vt_delta;
    30017:  511:    while (ch.vtlist.vt_next->vt_delta == (systime_t)0) {
unconditional  0 taken 100%
branch  1 taken 1%
branch  2 taken 99% (fallthrough)
        -:  512:      virtual_timer_t *vtp;
        -:  513:      vtfunc_t fn;
        -:  514:
       73:  515:      vtp = ch.vtlist.vt_next;
       73:  516:      fn = vtp->vt_func;
       73:  517:      vtp->vt_func = NULL;
       73:  518:      vtp->vt_next->vt_prev = (virtual_timer_t *)&ch.vtlist;
       73:  519:      ch.vtlist.vt_next = vtp->vt_next;
       73:  520:      chSysUnlockFromISR();
call    0 returned 100%
       73:  521:      fn(vtp->vt_par);
call    0 returned 100%
       73:  522:      chSysLockFromISR();
call    0 returned 100%
unconditional  1 taken 100%
        -:  523:    }
        -:  524:  }
        -:  525:#else /* CH_CFG_ST_TIMEDELTA > 0 */
        -:  526:  virtual_timer_t *vtp;
        -:  527:  systime_t now, delta;
        -:  528:
        -:  529:  /* First timer to be processed.*/
        -:  530:  vtp = ch.vtlist.vt_next;
        -:  531:  now = chVTGetSystemTimeX();
        -:  532:
        -:  533:  /* All timers within the time window are triggered and removed,
        -:  534:     note that the loop is stopped by the timers header having
        -:  535:     "ch.vtlist.vt_delta == (systime_t)-1" which is greater than
        -:  536:     all deltas.*/
        -:  537:  while (vtp->vt_delta <= (systime_t)(now - ch.vtlist.vt_lasttime)) {
        -:  538:    vtfunc_t fn;
        -:  539:
        -:  540:    /* The "last time" becomes this timer's expiration time.*/
        -:  541:    ch.vtlist.vt_lasttime += vtp->vt_delta;
        -:  542:
        -:  543:    vtp->vt_next->vt_prev = (virtual_timer_t *)&ch.vtlist;
        -:  544:    ch.vtlist.vt_next = vtp->vt_next;
        -:  545:    fn = vtp->vt_func;
        -:  546:    vtp->vt_func = NULL;
        -:  547:
        -:  548:    /* if the list becomes empty then the timer is stopped.*/
        -:  549:    if (ch.vtlist.vt_next == (virtual_timer_t *)&ch.vtlist) {
        -:  550:      port_timer_stop_alarm();
        -:  551:    }
        -:  552:
        -:  553:    /* Leaving the system critical zone in order to execute the callback
        -:  554:       and in order to give a preemption chance to higher priority
        -:  555:       interrupts.*/
        -:  556:    chSysUnlockFromISR();
        -:  557:
        -:  558:    /* The callback is invoked outside the kernel critical zone.*/
        -:  559:    fn(vtp->vt_par);
        -:  560:
        -:  561:    /* Re-entering the critical zone in order to continue the exploration
        -:  562:       of the list.*/
        -:  563:    chSysLockFromISR();
        -:  564:
        -:  565:    /* Next element in the list, the current time could have advanced so
        -:  566:       recalculating the time window.*/
        -:  567:    vtp = ch.vtlist.vt_next;
        -:  568:    now = chVTGetSystemTimeX();
        -:  569:  }
        -:  570:
        -:  571:  /* if the list is empty, nothing else to do.*/
        -:  572:  if (ch.vtlist.vt_next == (virtual_timer_t *)&ch.vtlist) {
        -:  573:    return;
        -:  574:  }
        -:  575:
        -:  576:  /* Recalculating the next alarm time.*/
        -:  577:  delta = ch.vtlist.vt_lasttime + vtp->vt_delta - now;
        -:  578:  if (delta < (systime_t)CH_CFG_ST_TIMEDELTA) {
        -:  579:    delta = (systime_t)CH_CFG_ST_TIMEDELTA;
        -:  580:  }
        -:  581:  port_timer_set_alarm(now + delta);
        -:  582:
        -:  583:  chDbgAssert((chVTGetSystemTimeX() - ch.vtlist.vt_lasttime) <=
        -:  584:              (now + delta - ch.vtlist.vt_lasttime),
        -:  585:              "exceeding delta");
        -:  586:#endif /* CH_CFG_ST_TIMEDELTA > 0 */
    15092:  587:}
        -:  588:
        -:  589:#endif /* _CHVT_H_ */
        -:  590:
        -:  591:/** @} */
