/** * @brief Suspends the invoking thread until the system time arrives to the * specified value. * @note The system time is assumed to be between @p prev and @p time * else the call is assumed to have been called outside the * allowed time interval, in this case no sleep is performed. * @see chThdSleepUntilWindowed() * * @param[in] prev absolute system time of the previous deadline * @param[in] next absolute system time of the next deadline * @return the @p next parameter * * @api */ systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next) { systime_t time; chSysLock(); time = chVTGetSystemTimeX(); if (chVTIsTimeWithinX(time, prev, next)) chThdSleepS(next - time); chSysUnlock(); return next; }
/** * @brief CPU pulse. * @note The current implementation is not totally reliable. * * @param[in] duration CPU pulse duration in milliseconds */ void test_cpu_pulse(unsigned duration) { systime_t start, end, now; start = chThdGetTicksX(chThdGetSelfX()); end = start + MS2ST(duration); do { now = chThdGetTicksX(chThdGetSelfX()); #if defined(SIMULATOR) _sim_check_for_interrupts(); #endif } while (chVTIsTimeWithinX(now, start, end)); }
/** * @brief Puts the current thread to sleep into the specified state with * timeout specification. * @details The thread goes into a sleeping state, if it is not awakened * explicitly within the specified system time then it is forcibly * awakened with a @p NIL_MSG_TMO low level message. * * @param[in] newstate the new thread state or a semaphore pointer * @param[in] timeout the number of ticks before the operation timeouts. * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * @return The wakeup message. * @retval NIL_MSG_TMO if a timeout occurred. * * @sclass */ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) { thread_t *ntp, *otp = nil.current; chDbgAssert(otp != &nil.threads[NIL_CFG_NUM_THREADS], "idle cannot sleep"); /* Storing the wait object for the current thread.*/ otp->state = newstate; #if NIL_CFG_ST_TIMEDELTA > 0 if (timeout != TIME_INFINITE) { systime_t abstime; /* TIMEDELTA makes sure to have enough time to reprogram the timer before the free-running timer counter reaches the selected timeout.*/ if (timeout < (systime_t)NIL_CFG_ST_TIMEDELTA) { timeout = (systime_t)NIL_CFG_ST_TIMEDELTA; } /* Absolute time of the timeout event.*/ abstime = chVTGetSystemTimeX() + timeout; if (nil.lasttime == nil.nexttime) { /* Special case, first thread asking for a timeout.*/ port_timer_start_alarm(abstime); nil.nexttime = abstime; } else { /* Special case, there are already other threads with a timeout activated, evaluating the order.*/ if (chVTIsTimeWithinX(abstime, nil.lasttime, nil.nexttime)) { port_timer_set_alarm(abstime); nil.nexttime = abstime; } } /* Timeout settings.*/ otp->timeout = abstime - nil.lasttime; } #else /* Timeout settings.*/ otp->timeout = timeout; #endif /* Scanning the whole threads array.*/ ntp = nil.threads; while (true) { /* Is this thread ready to execute?*/ if (NIL_THD_IS_READY(ntp)) { nil.current = nil.next = ntp; if (ntp == &nil.threads[NIL_CFG_NUM_THREADS]) { NIL_CFG_IDLE_ENTER_HOOK(); } port_switch(ntp, otp); return nil.current->u1.msg; } /* Points to the next thread in lowering priority order.*/ ntp++; chDbgAssert(ntp <= &nil.threads[NIL_CFG_NUM_THREADS], "pointer out of range"); } }