        -:    0:Source:../../../os/rt/src/chthreads.c
        -:    0:Programs:18
        -:    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    chthreads.c
        -:   22: * @brief   Threads code.
        -:   23: *
        -:   24: * @addtogroup threads
        -:   25: * @details Threads related APIs and services.
        -:   26: *          <h2>Operation mode</h2>
        -:   27: *          A thread is an abstraction of an independent instructions flow.
        -:   28: *          In ChibiOS/RT a thread is represented by a "C" function owning
        -:   29: *          a processor context, state informations and a dedicated stack
        -:   30: *          area. In this scenario static variables are shared among all
        -:   31: *          threads while automatic variables are local to the thread.<br>
        -:   32: *          Operations defined for threads:
        -:   33: *          - <b>Create</b>, a thread is started on the specified thread
        -:   34: *            function. This operation is available in multiple variants,
        -:   35: *            both static and dynamic.
        -:   36: *          - <b>Exit</b>, a thread terminates by returning from its top
        -:   37: *            level function or invoking a specific API, the thread can
        -:   38: *            return a value that can be retrieved by other threads.
        -:   39: *          - <b>Wait</b>, a thread waits for the termination of another
        -:   40: *            thread and retrieves its return value.
        -:   41: *          - <b>Resume</b>, a thread created in suspended state is started.
        -:   42: *          - <b>Sleep</b>, the execution of a thread is suspended for the
        -:   43: *            specified amount of time or the specified future absolute time
        -:   44: *            is reached.
        -:   45: *          - <b>SetPriority</b>, a thread changes its own priority level.
        -:   46: *          - <b>Yield</b>, a thread voluntarily renounces to its time slot.
        -:   47: *          .
        -:   48: *          The threads subsystem is implicitly included in kernel however
        -:   49: *          some of its part may be excluded by disabling them in @p chconf.h,
        -:   50: *          see the @p CH_CFG_USE_WAITEXIT and @p CH_CFG_USE_DYNAMIC configuration
        -:   51: *          options.
        -:   52: * @{
        -:   53: */
        -:   54:
        -:   55:#include "ch.h"
        -:   56:
        -:   57:/*===========================================================================*/
        -:   58:/* Module local definitions.                                                 */
        -:   59:/*===========================================================================*/
        -:   60:
        -:   61:/*===========================================================================*/
        -:   62:/* Module exported variables.                                                */
        -:   63:/*===========================================================================*/
        -:   64:
        -:   65:/*===========================================================================*/
        -:   66:/* Module local types.                                                       */
        -:   67:/*===========================================================================*/
        -:   68:
        -:   69:/*===========================================================================*/
        -:   70:/* Module local variables.                                                   */
        -:   71:/*===========================================================================*/
        -:   72:
        -:   73:/*===========================================================================*/
        -:   74:/* Module local functions.                                                   */
        -:   75:/*===========================================================================*/
        -:   76:
        -:   77:/*===========================================================================*/
        -:   78:/* Module exported functions.                                                */
        -:   79:/*===========================================================================*/
        -:   80:
        -:   81:/**
        -:   82: * @brief   Initializes a thread structure.
        -:   83: * @note    This is an internal functions, do not use it in application code.
        -:   84: *
        -:   85: * @param[in] tp        pointer to the thread
        -:   86: * @param[in] prio      the priority level for the new thread
        -:   87: * @return              The same thread pointer passed as parameter.
        -:   88: *
        -:   89: * @notapi
        -:   90: */
function _thread_init called 48053 returned 100% blocks executed 100%
    48053:   91:thread_t *_thread_init(thread_t *tp, tprio_t prio) {
        -:   92:
    48053:   93:  tp->p_prio = prio;
    48053:   94:  tp->p_state = CH_STATE_WTSTART;
    48053:   95:  tp->p_flags = CH_FLAG_MODE_STATIC;
        -:   96:#if CH_CFG_TIME_QUANTUM > 0
    48053:   97:  tp->p_preempt = (tslices_t)CH_CFG_TIME_QUANTUM;
        -:   98:#endif
        -:   99:#if CH_CFG_USE_MUTEXES == TRUE
    48053:  100:  tp->p_realprio = prio;
    48053:  101:  tp->p_mtxlist = NULL;
        -:  102:#endif
        -:  103:#if CH_CFG_USE_EVENTS == TRUE
    48053:  104:  tp->p_epending = (eventmask_t)0;
        -:  105:#endif
        -:  106:#if CH_DBG_THREADS_PROFILING == TRUE
    48053:  107:  tp->p_time = (systime_t)0;
        -:  108:#endif
        -:  109:#if CH_CFG_USE_DYNAMIC == TRUE
    48053:  110:  tp->p_refs = (trefs_t)1;
        -:  111:#endif
        -:  112:#if CH_CFG_USE_REGISTRY == TRUE
    48053:  113:  tp->p_name = NULL;
    48053:  114:  REG_INSERT(tp);
        -:  115:#endif
        -:  116:#if CH_CFG_USE_WAITEXIT == TRUE
    48053:  117:  list_init(&tp->p_waiting);
call    0 returned 100%
        -:  118:#endif
        -:  119:#if CH_CFG_USE_MESSAGES == TRUE
    48053:  120:  queue_init(&tp->p_msgqueue);
call    0 returned 100%
        -:  121:#endif
        -:  122:#if CH_DBG_ENABLE_STACK_CHECK == TRUE
        -:  123:  tp->p_stklimit = (stkalign_t *)(tp + 1);
        -:  124:#endif
        -:  125:#if CH_DBG_STATISTICS == TRUE
        -:  126:  chTMObjectInit(&tp->p_stats);
        -:  127:  chTMStartMeasurementX(&tp->p_stats);
        -:  128:#endif
        -:  129:#if defined(CH_CFG_THREAD_INIT_HOOK)
        -:  130:  CH_CFG_THREAD_INIT_HOOK(tp);
        -:  131:#endif
    48053:  132:  return tp;
unconditional  0 taken 100%
        -:  133:}
        -:  134:
        -:  135:#if (CH_DBG_FILL_THREADS == TRUE) || defined(__DOXYGEN__)
        -:  136:/**
        -:  137: * @brief   Memory fill utility.
        -:  138: *
        -:  139: * @param[in] startp    first address to fill
        -:  140: * @param[in] endp      last address to fill +1
        -:  141: * @param[in] v         filler value
        -:  142: *
        -:  143: * @notapi
        -:  144: */
function _thread_memfill called 96102 returned 100% blocks executed 100%
    96102:  145:void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
        -:  146:
798992156:  147:  while (startp < endp) {
unconditional  0 taken 100%
branch  1 taken 99%
branch  2 taken 1% (fallthrough)
798799952:  148:    *startp++ = v;
unconditional  0 taken 100%
        -:  149:  }
    96102:  150:}
        -:  151:#endif /* CH_DBG_FILL_THREADS */
        -:  152:
        -:  153:/**
        -:  154: * @brief   Creates a new thread into a static memory area.
        -:  155: * @details The new thread is initialized but not inserted in the ready list,
        -:  156: *          the initial state is @p CH_STATE_WTSTART.
        -:  157: * @post    The initialized thread can be subsequently started by invoking
        -:  158: *          @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
        -:  159: *          depending on the execution context.
        -:  160: * @note    A thread can terminate by calling @p chThdExit() or by simply
        -:  161: *          returning from its main function.
        -:  162: * @note    Threads created using this function do not obey to the
        -:  163: *          @p CH_DBG_FILL_THREADS debug option because it would keep
        -:  164: *          the kernel locked for too much time.
        -:  165: *
        -:  166: * @param[out] wsp      pointer to a working area dedicated to the thread stack
        -:  167: * @param[in] size      size of the working area
        -:  168: * @param[in] prio      the priority level for the new thread
        -:  169: * @param[in] pf        the thread function
        -:  170: * @param[in] arg       an argument passed to the thread function. It can be
        -:  171: *                      @p NULL.
        -:  172: * @return              The pointer to the @p thread_t structure allocated for
        -:  173: *                      the thread into the working space area.
        -:  174: *
        -:  175: * @iclass
        -:  176: */
function chThdCreateI called 48052 returned 100% blocks executed 88%
    48052:  177:thread_t *chThdCreateI(void *wsp, size_t size,
        -:  178:                       tprio_t prio, tfunc_t pf, void *arg) {
        -:  179:  /* The thread structure is laid out in the lower part of the thread
        -:  180:     workspace.*/
    48052:  181:  thread_t *tp = wsp;
        -:  182:
    48052:  183:  chDbgCheckClassI();
call    0 returned 100%
    48052:  184:  chDbgCheck((wsp != NULL) && (size >= THD_WORKING_AREA_SIZE(0)) &&
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 100% (fallthrough)
branch  3 taken 0%
branch  4 taken 100% (fallthrough)
branch  5 taken 0%
branch  6 taken 0% (fallthrough)
branch  7 taken 100%
call    8 never executed
unconditional  9 never executed
        -:  185:             (prio <= HIGHPRIO) && (pf != NULL));
        -:  186:
    48052:  187:  PORT_SETUP_CONTEXT(tp, wsp, size, pf, arg);
        -:  188:
    48052:  189:  return _thread_init(tp, prio);
call    0 returned 100%
        -:  190:}
        -:  191:
        -:  192:/**
        -:  193: * @brief   Creates a new thread into a static memory area.
        -:  194: * @note    A thread can terminate by calling @p chThdExit() or by simply
        -:  195: *          returning from its main function.
        -:  196: *
        -:  197: * @param[out] wsp      pointer to a working area dedicated to the thread stack
        -:  198: * @param[in] size      size of the working area
        -:  199: * @param[in] prio      the priority level for the new thread
        -:  200: * @param[in] pf        the thread function
        -:  201: * @param[in] arg       an argument passed to the thread function. It can be
        -:  202: *                      @p NULL.
        -:  203: * @return              The pointer to the @p thread_t structure allocated for
        -:  204: *                      the thread into the working space area.
        -:  205: *
        -:  206: * @api
        -:  207: */
function chThdCreateStatic called 48044 returned 100% blocks executed 100%
    48044:  208:thread_t *chThdCreateStatic(void *wsp, size_t size,
        -:  209:                            tprio_t prio, tfunc_t pf, void *arg) {
        -:  210:  thread_t *tp;
        -:  211:  
        -:  212:#if CH_DBG_FILL_THREADS == TRUE
    48044:  213:  _thread_memfill((uint8_t *)wsp,
call    0 returned 100%
        -:  214:                  (uint8_t *)wsp + sizeof(thread_t),
        -:  215:                  CH_DBG_THREAD_FILL_VALUE);
    48044:  216:  _thread_memfill((uint8_t *)wsp + sizeof(thread_t),
call    0 returned 100%
        -:  217:                  (uint8_t *)wsp + size,
        -:  218:                  CH_DBG_STACK_FILL_VALUE);
        -:  219:#endif
        -:  220:
    48044:  221:  chSysLock();
call    0 returned 100%
    48044:  222:  tp = chThdCreateI(wsp, size, prio, pf, arg);
call    0 returned 100%
    48044:  223:  chSchWakeupS(tp, MSG_OK);
call    0 returned 100%
    48044:  224:  chSysUnlock();
call    0 returned 100%
        -:  225:
    48044:  226:  return tp;
unconditional  0 taken 100%
        -:  227:}
        -:  228:
        -:  229:/**
        -:  230: * @brief   Resumes a thread created with @p chThdCreateI().
        -:  231: *
        -:  232: * @param[in] tp        pointer to the thread
        -:  233: * @return              The pointer to the @p thread_t structure allocated for
        -:  234: *                      the thread into the working space area.
        -:  235: *
        -:  236: * @api
        -:  237: */
function chThdStart called 1 returned 100% blocks executed 100%
        1:  238:thread_t *chThdStart(thread_t *tp) {
        -:  239:
        1:  240:  chSysLock();
call    0 returned 100%
        1:  241:  tp = chThdStartI(tp);
call    0 returned 100%
        1:  242:  chSysUnlock();
call    0 returned 100%
        -:  243:
        1:  244:  return tp;
unconditional  0 taken 100%
        -:  245:}
        -:  246:
        -:  247:/**
        -:  248: * @brief   Changes the running thread priority level then reschedules if
        -:  249: *          necessary.
        -:  250: * @note    The function returns the real thread priority regardless of the
        -:  251: *          current priority that could be higher than the real priority
        -:  252: *          because the priority inheritance mechanism.
        -:  253: *
        -:  254: * @param[in] newprio   the new priority level of the running thread
        -:  255: * @return              The old priority level.
        -:  256: *
        -:  257: * @api
        -:  258: */
function chThdSetPriority called 4 returned 100% blocks executed 91%
        4:  259:tprio_t chThdSetPriority(tprio_t newprio) {
unconditional  0 taken 100%
        -:  260:  tprio_t oldprio;
        -:  261:
        4:  262:  chDbgCheck(newprio <= HIGHPRIO);
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
call    2 never executed
unconditional  3 never executed
        -:  263:
        4:  264:  chSysLock();
call    0 returned 100%
        -:  265:#if CH_CFG_USE_MUTEXES == TRUE
        4:  266:  oldprio = currp->p_realprio;
        4:  267:  if ((currp->p_prio == currp->p_realprio) || (newprio > currp->p_prio)) {
branch  0 taken 50% (fallthrough)
branch  1 taken 50%
branch  2 taken 50% (fallthrough)
branch  3 taken 50%
        3:  268:    currp->p_prio = newprio;
unconditional  0 taken 100%
        -:  269:  }
        4:  270:  currp->p_realprio = newprio;
        -:  271:#else
        -:  272:  oldprio = currp->p_prio;
        -:  273:  currp->p_prio = newprio;
        -:  274:#endif
        4:  275:  chSchRescheduleS();
call    0 returned 100%
        4:  276:  chSysUnlock();
call    0 returned 100%
        -:  277:
        4:  278:  return oldprio;
unconditional  0 taken 100%
        -:  279:}
        -:  280:
        -:  281:/**
        -:  282: * @brief   Requests a thread termination.
        -:  283: * @pre     The target thread must be written to invoke periodically
        -:  284: *          @p chThdShouldTerminate() and terminate cleanly if it returns
        -:  285: *          @p true.
        -:  286: * @post    The specified thread will terminate after detecting the termination
        -:  287: *          condition.
        -:  288: *
        -:  289: * @param[in] tp        pointer to the thread
        -:  290: *
        -:  291: * @api
        -:  292: */
function chThdTerminate called 10 returned 100% blocks executed 100%
       10:  293:void chThdTerminate(thread_t *tp) {
        -:  294:
       10:  295:  chSysLock();
call    0 returned 100%
       10:  296:  tp->p_flags |= CH_FLAG_TERMINATE;
       10:  297:  chSysUnlock();
call    0 returned 100%
       10:  298:}
        -:  299:
        -:  300:/**
        -:  301: * @brief   Suspends the invoking thread for the specified time.
        -:  302: *
        -:  303: * @param[in] time      the delay in system ticks, the special values are
        -:  304: *                      handled as follow:
        -:  305: *                      - @a TIME_INFINITE the thread enters an infinite sleep
        -:  306: *                        state.
        -:  307: *                      - @a TIME_IMMEDIATE this value is not allowed.
        -:  308: *                      .
        -:  309: *
        -:  310: * @api
        -:  311: */
function chThdSleep called 45 returned 100% blocks executed 100%
       45:  312:void chThdSleep(systime_t time) {
        -:  313:
       45:  314:  chSysLock();
call    0 returned 100%
       45:  315:  chThdSleepS(time);
call    0 returned 100%
       45:  316:  chSysUnlock();
call    0 returned 100%
       45:  317:}
        -:  318:
        -:  319:/**
        -:  320: * @brief   Suspends the invoking thread until the system time arrives to the
        -:  321: *          specified value.
        -:  322: * @note    The function has no concept of "past", all specifiable times
        -:  323: *          are in the future, this means that if you call this function
        -:  324: *          exceeding your calculated intervals then the function will
        -:  325: *          return in a far future time, not immediately.
        -:  326: * @see     chThdSleepUntilWindowed()
        -:  327: *
        -:  328: * @param[in] time      absolute system time
        -:  329: *
        -:  330: * @api
        -:  331: */
function chThdSleepUntil called 1 returned 100% blocks executed 100%
        1:  332:void chThdSleepUntil(systime_t time) {
        -:  333:
        1:  334:  chSysLock();
call    0 returned 100%
        1:  335:  time -= chVTGetSystemTimeX();
call    0 returned 100%
        1:  336:  if (time > (systime_t)0) {
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
        1:  337:    chThdSleepS(time);
call    0 returned 100%
unconditional  1 taken 100%
        -:  338:  }
        1:  339:  chSysUnlock();
call    0 returned 100%
        1:  340:}
        -:  341:
        -:  342:/**
        -:  343: * @brief   Suspends the invoking thread until the system time arrives to the
        -:  344: *          specified value.
        -:  345: * @note    The system time is assumed to be between @p prev and @p time
        -:  346: *          else the call is assumed to have been called outside the
        -:  347: *          allowed time interval, in this case no sleep is performed.
        -:  348: * @see     chThdSleepUntil()
        -:  349: *
        -:  350: * @param[in] prev      absolute system time of the previous deadline
        -:  351: * @param[in] next      absolute system time of the next deadline
        -:  352: * @return				the @p next parameter
        -:  353: *
        -:  354: * @api
        -:  355: */
function chThdSleepUntilWindowed called 0 returned 0% blocks executed 0%
    #####:  356:systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next) {
        -:  357:  systime_t time;
        -:  358:
    #####:  359:  chSysLock();
call    0 never executed
    #####:  360:  time = chVTGetSystemTimeX();
call    0 never executed
    #####:  361:  if (chVTIsTimeWithinX(time, prev, next)) {
call    0 never executed
branch  1 never executed
branch  2 never executed
    #####:  362:	chThdSleepS(next - time);
call    0 never executed
unconditional  1 never executed
        -:  363:  }
    #####:  364:  chSysUnlock();
call    0 never executed
        -:  365:
    #####:  366:  return next;
unconditional  0 never executed
        -:  367:}
        -:  368:
        -:  369:/**
        -:  370: * @brief   Yields the time slot.
        -:  371: * @details Yields the CPU control to the next thread in the ready list with
        -:  372: *          equal priority, if any.
        -:  373: *
        -:  374: * @api
        -:  375: */
function chThdYield called 4898900 returned 100% blocks executed 100%
  4898900:  376:void chThdYield(void) {
        -:  377:
  4898900:  378:  chSysLock();
call    0 returned 100%
  4898900:  379:  chSchDoYieldS();
call    0 returned 100%
  4898900:  380:  chSysUnlock();
call    0 returned 100%
  4898900:  381:}
        -:  382:
        -:  383:/**
        -:  384: * @brief   Terminates the current thread.
        -:  385: * @details The thread goes in the @p CH_STATE_FINAL state holding the
        -:  386: *          specified exit status code, other threads can retrieve the
        -:  387: *          exit status code by invoking the function @p chThdWait().
        -:  388: * @post    Eventual code after this function will never be executed,
        -:  389: *          this function never returns. The compiler has no way to
        -:  390: *          know this so do not assume that the compiler would remove
        -:  391: *          the dead code.
        -:  392: *
        -:  393: * @param[in] msg       thread exit code
        -:  394: *
        -:  395: * @api
        -:  396: */
function chThdExit called 48051 returned 0% blocks executed 100%
    48051:  397:void chThdExit(msg_t msg) {
        -:  398:
    48051:  399:  chSysLock();
call    0 returned 100%
    48051:  400:  chThdExitS(msg);
call    0 returned 0%
        -:  401:  /* The thread never returns here.*/
    #####:  402:}
        -:  403:
        -:  404:/**
        -:  405: * @brief   Terminates the current thread.
        -:  406: * @details The thread goes in the @p CH_STATE_FINAL state holding the
        -:  407: *          specified exit status code, other threads can retrieve the
        -:  408: *          exit status code by invoking the function @p chThdWait().
        -:  409: * @post    Eventual code after this function will never be executed,
        -:  410: *          this function never returns. The compiler has no way to
        -:  411: *          know this so do not assume that the compiler would remove
        -:  412: *          the dead code.
        -:  413: *
        -:  414: * @param[in] msg       thread exit code
        -:  415: *
        -:  416: * @sclass
        -:  417: */
function chThdExitS called 48051 returned 0% blocks executed 90%
    48051:  418:void chThdExitS(msg_t msg) {
    48051:  419:  thread_t *tp = currp;
        -:  420:
    48051:  421:  tp->p_u.exitcode = msg;
        -:  422:#if defined(CH_CFG_THREAD_EXIT_HOOK)
        -:  423:  CH_CFG_THREAD_EXIT_HOOK(tp);
        -:  424:#endif
        -:  425:#if CH_CFG_USE_WAITEXIT == TRUE
   120060:  426:  while (list_notempty(&tp->p_waiting)) {
unconditional  0 taken 100%
call    1 returned 100%
branch  2 taken 33%
branch  3 taken 67% (fallthrough)
    23958:  427:    (void) chSchReadyI(list_remove(&tp->p_waiting));
call    0 returned 100%
call    1 returned 100%
unconditional  2 taken 100%
        -:  428:  }
        -:  429:#endif
        -:  430:#if CH_CFG_USE_REGISTRY == TRUE
        -:  431:  /* Static threads are immediately removed from the registry because
        -:  432:     there is no memory to recover.*/
    48051:  433:  if ((tp->p_flags & CH_FLAG_MODE_MASK) == CH_FLAG_MODE_STATIC) {
branch  0 taken 99% (fallthrough)
branch  1 taken 1%
    48044:  434:    REG_REMOVE(tp);
unconditional  0 taken 100%
        -:  435:  }
        -:  436:#endif
    48051:  437:  chSchGoSleepS(CH_STATE_FINAL);
call    0 returned 0%
        -:  438:
        -:  439:  /* The thread never returns here.*/
    #####:  440:  chDbgAssert(false, "zombies apocalypse");
call    0 never executed
    #####:  441:}
        -:  442:
        -:  443:#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
        -:  444:/**
        -:  445: * @brief   Blocks the execution of the invoking thread until the specified
        -:  446: *          thread terminates then the exit code is returned.
        -:  447: * @details This function waits for the specified thread to terminate then
        -:  448: *          decrements its reference counter, if the counter reaches zero then
        -:  449: *          the thread working area is returned to the proper allocator.<br>
        -:  450: *          The memory used by the exited thread is handled in different ways
        -:  451: *          depending on the API that spawned the thread:
        -:  452: *          - If the thread was spawned by @p chThdCreateStatic() or by
        -:  453: *            @p chThdCreateI() then nothing happens and the thread working
        -:  454: *            area is not released or modified in any way. This is the
        -:  455: *            default, totally static, behavior.
        -:  456: *          - If the thread was spawned by @p chThdCreateFromHeap() then
        -:  457: *            the working area is returned to the system heap.
        -:  458: *          - If the thread was spawned by @p chThdCreateFromMemoryPool()
        -:  459: *            then the working area is returned to the owning memory pool.
        -:  460: *          .
        -:  461: * @pre     The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in
        -:  462: *          order to use this function.
        -:  463: * @post    Enabling @p chThdWait() requires 2-4 (depending on the
        -:  464: *          architecture) extra bytes in the @p thread_t structure.
        -:  465: * @post    After invoking @p chThdWait() the thread pointer becomes invalid
        -:  466: *          and must not be used as parameter for further system calls.
        -:  467: * @note    If @p CH_CFG_USE_DYNAMIC is not specified this function just waits for
        -:  468: *          the thread termination, no memory allocators are involved.
        -:  469: *
        -:  470: * @param[in] tp        pointer to the thread
        -:  471: * @return              The exit code from the terminated thread.
        -:  472: *
        -:  473: * @api
        -:  474: */
function chThdWait called 24012 returned 100% blocks executed 81%
    24012:  475:msg_t chThdWait(thread_t *tp) {
unconditional  0 taken 100%
        -:  476:  msg_t msg;
        -:  477:
    24012:  478:  chDbgCheck(tp != NULL);
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
call    2 never executed
unconditional  3 never executed
        -:  479:
    24012:  480:  chSysLock();
call    0 returned 100%
    24012:  481:  chDbgAssert(tp != currp, "waiting self");
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
call    2 never executed
unconditional  3 never executed
unconditional  4 taken 100%
        -:  482:#if CH_CFG_USE_DYNAMIC == TRUE
    24012:  483:  chDbgAssert(tp->p_refs > (trefs_t)0, "not referenced");
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
call    2 never executed
unconditional  3 never executed
        -:  484:#endif
    24012:  485:  if (tp->p_state != CH_STATE_FINAL) {
branch  0 taken 99% (fallthrough)
branch  1 taken 1%
    23958:  486:    list_insert(currp, &tp->p_waiting);
call    0 returned 100%
    23958:  487:    chSchGoSleepS(CH_STATE_WTEXIT);
call    0 returned 100%
unconditional  1 taken 100%
        -:  488:  }
    24012:  489:  msg = tp->p_u.exitcode;
    24012:  490:  chSysUnlock();
call    0 returned 100%
        -:  491:
        -:  492:#if CH_CFG_USE_DYNAMIC == TRUE
        -:  493:  /* Releasing a lock if it is a dynamic thread.*/
    24012:  494:  chThdRelease(tp);
call    0 returned 100%
        -:  495:#endif
        -:  496:
    24012:  497:  return msg;
unconditional  0 taken 100%
        -:  498:}
        -:  499:#endif /* CH_CFG_USE_WAITEXIT */
        -:  500:
        -:  501:/**
        -:  502: * @brief   Sends the current thread sleeping and sets a reference variable.
        -:  503: * @note    This function must reschedule, it can only be called from thread
        -:  504: *          context.
        -:  505: *
        -:  506: * @param[in] trp       a pointer to a thread reference object
        -:  507: * @return              The wake up message.
        -:  508: *
        -:  509: * @sclass
        -:  510: */
function chThdSuspendS called 0 returned 0% blocks executed 0%
    #####:  511:msg_t chThdSuspendS(thread_reference_t *trp) {
    #####:  512:  thread_t *tp = chThdGetSelfX();
call    0 never executed
        -:  513:
    #####:  514:  chDbgAssert(*trp == NULL, "not NULL");
branch  0 never executed
branch  1 never executed
call    2 never executed
unconditional  3 never executed
        -:  515:
    #####:  516:  *trp = tp;
    #####:  517:  tp->p_u.wttrp = trp;
    #####:  518:  chSchGoSleepS(CH_STATE_SUSPENDED);
call    0 never executed
        -:  519:
    #####:  520:  return chThdGetSelfX()->p_u.rdymsg;
call    0 never executed
unconditional  1 never executed
        -:  521:}
        -:  522:
        -:  523:/**
        -:  524: * @brief   Sends the current thread sleeping and sets a reference variable.
        -:  525: * @note    This function must reschedule, it can only be called from thread
        -:  526: *          context.
        -:  527: *
        -:  528: * @param[in] trp       a pointer to a thread reference object
        -:  529: * @param[in] timeout   the timeout in system ticks, the special values are
        -:  530: *                      handled as follow:
        -:  531: *                      - @a TIME_INFINITE the thread enters an infinite sleep
        -:  532: *                        state.
        -:  533: *                      - @a TIME_IMMEDIATE the thread is not enqueued and
        -:  534: *                        the function returns @p MSG_TIMEOUT as if a timeout
        -:  535: *                        occurred.
        -:  536: *                      .
        -:  537: * @return              The wake up message.
        -:  538: * @retval MSG_TIMEOUT  if the operation timed out.
        -:  539: *
        -:  540: * @sclass
        -:  541: */
function chThdSuspendTimeoutS called 0 returned 0% blocks executed 0%
    #####:  542:msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) {
    #####:  543:  thread_t *tp = chThdGetSelfX();
call    0 never executed
        -:  544:
    #####:  545:  chDbgAssert(*trp == NULL, "not NULL");
branch  0 never executed
branch  1 never executed
call    2 never executed
unconditional  3 never executed
        -:  546:
    #####:  547:  if (TIME_IMMEDIATE == timeout) {
branch  0 never executed
branch  1 never executed
    #####:  548:    return MSG_TIMEOUT;
unconditional  0 never executed
        -:  549:  }
        -:  550:
    #####:  551:  *trp = tp;
    #####:  552:  tp->p_u.wttrp = trp;
        -:  553:
    #####:  554:  return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout);
call    0 never executed
unconditional  1 never executed
        -:  555:}
        -:  556:
        -:  557:/**
        -:  558: * @brief   Wakes up a thread waiting on a thread reference object.
        -:  559: * @note    This function must not reschedule because it can be called from
        -:  560: *          ISR context.
        -:  561: *
        -:  562: * @param[in] trp       a pointer to a thread reference object
        -:  563: * @param[in] msg       the message code
        -:  564: *
        -:  565: * @iclass
        -:  566: */
function chThdResumeI called 0 returned 0% blocks executed 0%
    #####:  567:void chThdResumeI(thread_reference_t *trp, msg_t msg) {
        -:  568:
    #####:  569:  if (*trp != NULL) {
branch  0 never executed
branch  1 never executed
    #####:  570:    thread_t *tp = *trp;
unconditional  0 never executed
        -:  571:
    #####:  572:    chDbgAssert(tp->p_state == CH_STATE_SUSPENDED,
branch  0 never executed
branch  1 never executed
call    2 never executed
unconditional  3 never executed
        -:  573:                "not THD_STATE_SUSPENDED");
        -:  574:
    #####:  575:    *trp = NULL;
    #####:  576:    tp->p_u.rdymsg = msg;
    #####:  577:    (void) chSchReadyI(tp);
call    0 never executed
unconditional  1 never executed
        -:  578:  }
    #####:  579:}
        -:  580:
        -:  581:/**
        -:  582: * @brief   Wakes up a thread waiting on a thread reference object.
        -:  583: * @note    This function must reschedule, it can only be called from thread
        -:  584: *          context.
        -:  585: *
        -:  586: * @param[in] trp       a pointer to a thread reference object
        -:  587: * @param[in] msg       the message code
        -:  588: *
        -:  589: * @iclass
        -:  590: */
function chThdResumeS called 0 returned 0% blocks executed 0%
    #####:  591:void chThdResumeS(thread_reference_t *trp, msg_t msg) {
        -:  592:
    #####:  593:  if (*trp != NULL) {
branch  0 never executed
branch  1 never executed
    #####:  594:    thread_t *tp = *trp;
unconditional  0 never executed
        -:  595:
    #####:  596:    chDbgAssert(tp->p_state == CH_STATE_SUSPENDED,
branch  0 never executed
branch  1 never executed
call    2 never executed
unconditional  3 never executed
        -:  597:                "not THD_STATE_SUSPENDED");
        -:  598:
    #####:  599:    *trp = NULL;
    #####:  600:    chSchWakeupS(tp, msg);
call    0 never executed
unconditional  1 never executed
        -:  601:  }
    #####:  602:}
        -:  603:
        -:  604:/**
        -:  605: * @brief   Wakes up a thread waiting on a thread reference object.
        -:  606: * @note    This function must reschedule, it can only be called from thread
        -:  607: *          context.
        -:  608: *
        -:  609: * @param[in] trp       a pointer to a thread reference object
        -:  610: * @param[in] msg       the message code
        -:  611: *
        -:  612: * @api
        -:  613: */
function chThdResume called 0 returned 0% blocks executed 0%
    #####:  614:void chThdResume(thread_reference_t *trp, msg_t msg) {
        -:  615:
    #####:  616:  chSysLock();
call    0 never executed
    #####:  617:  chThdResumeS(trp, msg);
call    0 never executed
    #####:  618:  chSysUnlock();
call    0 never executed
    #####:  619:}
        -:  620:
        -:  621:/**
        -:  622: * @brief   Enqueues the caller thread on a threads queue object.
        -:  623: * @details The caller thread is enqueued and put to sleep until it is
        -:  624: *          dequeued or the specified timeouts expires.
        -:  625: *
        -:  626: * @param[in] tqp       pointer to the threads queue object
        -:  627: * @param[in] timeout   the timeout in system ticks, the special values are
        -:  628: *                      handled as follow:
        -:  629: *                      - @a TIME_INFINITE the thread enters an infinite sleep
        -:  630: *                        state.
        -:  631: *                      - @a TIME_IMMEDIATE the thread is not enqueued and
        -:  632: *                        the function returns @p MSG_TIMEOUT as if a timeout
        -:  633: *                        occurred.
        -:  634: *                      .
        -:  635: * @return              The message from @p osalQueueWakeupOneI() or
        -:  636: *                      @p osalQueueWakeupAllI() functions.
        -:  637: * @retval MSG_TIMEOUT  if the thread has not been dequeued within the
        -:  638: *                      specified timeout or if the function has been
        -:  639: *                      invoked with @p TIME_IMMEDIATE as timeout
        -:  640: *                      specification.
        -:  641: *
        -:  642: * @sclass
        -:  643: */
function chThdEnqueueTimeoutS called 6 returned 100% blocks executed 100%
        6:  644:msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout) {
        -:  645:
        6:  646:  if (TIME_IMMEDIATE == timeout) {
branch  0 taken 33% (fallthrough)
branch  1 taken 67%
        2:  647:    return MSG_TIMEOUT;
unconditional  0 taken 100%
        -:  648:  }
        -:  649:
        4:  650:  queue_insert(currp, tqp);
call    0 returned 100%
        -:  651:
        4:  652:  return chSchGoSleepTimeoutS(CH_STATE_QUEUED, timeout);
call    0 returned 100%
unconditional  1 taken 100%
        -:  653:}
        -:  654:
        -:  655:/**
        -:  656: * @brief   Dequeues and wakes up one thread from the threads queue object,
        -:  657: *          if any.
        -:  658: *
        -:  659: * @param[in] tqp       pointer to the threads queue object
        -:  660: * @param[in] msg       the message code
        -:  661: *
        -:  662: * @iclass
        -:  663: */
function chThdDequeueNextI called 5444669 returned 100% blocks executed 75%
  5444669:  664:void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
        -:  665:
  5444669:  666:  if (queue_notempty(tqp)) {
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  667:    chThdDoDequeueNextI(tqp, msg);
call    0 never executed
unconditional  1 never executed
        -:  668:  }
  5444669:  669:}
        -:  670:
        -:  671:/**
        -:  672: * @brief   Dequeues and wakes up all threads from the threads queue object.
        -:  673: *
        -:  674: * @param[in] tqp       pointer to the threads queue object
        -:  675: * @param[in] msg       the message code
        -:  676: *
        -:  677: * @iclass
        -:  678: */
function chThdDequeueAllI called 2 returned 100% blocks executed 80%
        2:  679:void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) {
        -:  680:
        4:  681:  while (queue_notempty(tqp)) {
unconditional  0 taken 100%
call    1 returned 100%
branch  2 taken 0%
branch  3 taken 100% (fallthrough)
    #####:  682:    chThdDoDequeueNextI(tqp, msg);
call    0 never executed
unconditional  1 never executed
        -:  683:  }
        2:  684:}
        -:  685:
        -:  686:/** @} */
