/** * @brief Time management handler. * @note This handler has to be invoked by a periodic ISR in order to * reschedule the waiting threads. * * @iclass */ void nilSysTimerHandlerI(void) { #if NIL_CFG_TIMEDELTA == 0 thread_ref_t tr = &nil.threads[0]; nil.systime++; do { /* Is the thread in a wait state with timeout?.*/ if (tr->timeout > 0) { nilDbgAssert(!NIL_THD_IS_READY(tr), "nilSysTimerHandlerI(), #1", "is ready"); /* Did the timer reach zero?*/ if (--tr->timeout == 0) { /* Timeout on semaphores requires a special handling because the semaphore counter must be incremented.*/ if (NIL_THD_IS_WTSEM(tr)) tr->u1.semp->cnt++; else if (NIL_THD_IS_SUSP(tr)) tr->u1.trp = NULL; nilSchReadyI(tr, NIL_MSG_TMO); } } /* Lock released in order to give a preemption chance on those architectures supporting IRQ preemption.*/ nilSysUnlockFromISR(); tr++; nilSysLockFromISR(); #if WHG_MOD } while (tr < nil.idlep); #else /* WHG_MOD */ } while (tr < &nil.threads[NIL_CFG_NUM_THREADS]);
/** * @brief Performs a reset operation on the semaphore. * @post After invoking this function all the threads waiting on the * semaphore, if any, are released and the semaphore counter is set * to the specified, non negative, value. * @post This function does not reschedule so a call to a rescheduling * function must be performed before unlocking the kernel. Note that * interrupt handlers always reschedule on exit so an explicit * reschedule must not be performed in ISRs. * * @param[in] sp pointer to a @p semaphore_t structure * @param[in] n the new value of the semaphore counter. The value must * be non-negative. * * @iclass */ void chSemResetI(semaphore_t *sp, cnt_t n) { thread_t *tp; cnt_t cnt; chDbgCheckClassI(); chDbgCheck((sp != NULL) && (n >= (cnt_t)0)); cnt = sp->cnt; sp->cnt = n; tp = nil.threads; while (cnt < (cnt_t)0) { chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], "pointer out of range"); /* Is this thread waiting on this semaphore?*/ if (tp->u1.semp == sp) { chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting"); cnt++; (void) chSchReadyI(tp, MSG_RESET); } tp++; } }
/** * @brief Performs a signal operation on a semaphore. * @post This function does not reschedule so a call to a rescheduling * function must be performed before unlocking the kernel. Note that * interrupt handlers always reschedule on exit so an explicit * reschedule must not be performed in ISRs. * * @param[in] sp pointer to a @p semaphore_t structure * * @iclass */ void chSemSignalI(semaphore_t *sp) { if (++sp->cnt <= (cnt_t)0) { thread_reference_t tr = nil.threads; while (true) { /* Is this thread waiting on this semaphore?*/ if (tr->u1.semp == sp) { chDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); (void) chSchReadyI(tr, MSG_OK); return; } tr++; chDbgAssert(tr < &nil.threads[NIL_CFG_NUM_THREADS], "pointer out of range"); } } }
/** * @brief Dequeues and wakes up one thread from the queue, if any. * * @param[in] tqp pointer to the threads queue object * @param[in] msg the message code * * @iclass */ void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) { semaphore_t *sp = &tqp->sem; if (chSemGetCounterI(&tqp->sem) < (cnt_t)0) { thread_reference_t tr = nil.threads; while (true) { /* Is this thread waiting on this semaphore?*/ if (tr->u1.semp == sp) { sp->cnt++; chDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); (void) chSchReadyI(tr, msg); return; } tr++; chDbgAssert(tr < &nil.threads[NIL_CFG_NUM_THREADS], "pointer out of range"); } } }
/** * @brief Dequeues and wakes up all threads from the queue. * * @param[in] tqp pointer to the threads queue object * @param[in] msg the message code * * @iclass */ void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) { semaphore_t *sp = &tqp->sem; thread_reference_t tr; cnt_t cnt; cnt = sp->cnt; sp->cnt = (cnt_t)0; tr = nil.threads; while (cnt < (cnt_t)0) { /* Is this thread waiting on this semaphore?*/ if (tr->u1.semp == sp) { chDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); cnt++; (void) chSchReadyI(tr, msg); } tr++; chDbgAssert(tr < &nil.threads[NIL_CFG_NUM_THREADS], "pointer out of range"); } }
/** * @brief Time management handler. * @note This handler has to be invoked by a periodic ISR in order to * reschedule the waiting threads. * * @iclass */ void chSysTimerHandlerI(void) { #if NIL_CFG_ST_TIMEDELTA == 0 thread_t *tp = &nil.threads[0]; nil.systime++; do { /* Is the thread in a wait state with timeout?.*/ if (tp->timeout > (systime_t)0) { chDbgAssert(!NIL_THD_IS_READY(tp), "is ready"); /* Did the timer reach zero?*/ if (--tp->timeout == (systime_t)0) { /* Timeout on semaphores requires a special handling because the semaphore counter must be incremented.*/ /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ if (NIL_THD_IS_WTSEM(tp)) { tp->u1.semp->cnt++; } else if (NIL_THD_IS_SUSP(tp)) { *tp->u1.trp = NULL; } /*lint -restore*/ (void) chSchReadyI(tp, MSG_TIMEOUT); } } /* Lock released in order to give a preemption chance on those architectures supporting IRQ preemption.*/ chSysUnlockFromISR(); tp++; chSysLockFromISR(); } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]); #else thread_t *tp = &nil.threads[0]; systime_t next = (systime_t)0; chDbgAssert(nil.nexttime == port_timer_get_alarm(), "time mismatch"); do { /* Is the thread in a wait state with timeout?.*/ if (tp->timeout > (systime_t)0) { chDbgAssert(!NIL_THD_IS_READY(tp), "is ready"); chDbgAssert(tp->timeout >= (nil.nexttime - nil.lasttime), "skipped one"); tp->timeout -= nil.nexttime - nil.lasttime; if (tp->timeout == (systime_t)0) { /* Timeout on semaphores requires a special handling because the semaphore counter must be incremented.*/ /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ if (NIL_THD_IS_WTSEM(tp)) { tp->u1.semp->cnt++; } else if (NIL_THD_IS_SUSP(tp)) { *tp->u1.trp = NULL; } /*lint -restore*/ (void) chSchReadyI(tp, MSG_TIMEOUT); } else { if (tp->timeout <= (systime_t)(next - (systime_t)1)) { next = tp->timeout; } } } /* Lock released in order to give a preemption chance on those architectures supporting IRQ preemption.*/ chSysUnlockFromISR(); tp++; chSysLockFromISR(); } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]); nil.lasttime = nil.nexttime; if (next > (systime_t)0) { nil.nexttime += next; port_timer_set_alarm(nil.nexttime); } else { /* No tick event needed.*/ port_timer_stop_alarm(); } #endif }