/** * @brief Initializes the kernel. * @details Initializes the kernel structures, the current instructions flow * becomes the idle thread upon return. The idle thread must not * invoke any kernel primitive able to change state to not runnable. * * @special */ void nilSysInit(void) { Thread *tp; const ThreadConfig *tcp; /* Port layer initialization.*/ port_init(); /* Iterates through the list of defined threads.*/ for (tp = &nil.threads[0], tcp = nil_thd_configs; #if WHG_MOD tp < nil.idlep; #else /* WHG_MOD */ tp < &nil.threads[NIL_CFG_NUM_THREADS]; #endif /* WHG_MOD */ tp++, tcp++) { /* Port dependent thread initialization.*/ SETUP_CONTEXT(tcp->wap, tcp->size, tcp->funcp, tcp->arg); } /* Runs the highest priority thread, the current one becomes the null thread.*/ nil.currp = nil.nextp = nil.threads; #if WHG_MOD port_switch(nil.threads, nil.idlep); #else /* WHG_MOD */ port_switch(nil.threads, &nil.threads[NIL_CFG_NUM_THREADS]); #endif /* WHG_MOD */ /* Interrupts enabled for the idle thread.*/ nilSysEnable(); }
/** * @brief Initializes the kernel. * @details Initializes the kernel structures, the current instructions flow * becomes the idle thread upon return. The idle thread must not * invoke any kernel primitive able to change state to not runnable. * @note This function assumes that the @p nil global variable has been * zeroed by the runtime environment. If this is not the case then * make sure to clear it before calling this function. * * @special */ void chSysInit(void) { thread_t *tp; const thread_config_t *tcp; #if CH_DBG_SYSTEM_STATE_CHECK == TRUE nil.isr_cnt = (cnt_t)0; nil.lock_cnt = (cnt_t)0; #endif /* System initialization hook.*/ CH_CFG_SYSTEM_INIT_HOOK(); /* Iterates through the list of defined threads.*/ tp = &nil.threads[0]; tcp = nil_thd_configs; while (tp < &nil.threads[CH_CFG_NUM_THREADS]) { #if CH_DBG_ENABLE_STACK_CHECK tp->stklimit = (stkalign_t *)tcp->wbase; #endif /* Port dependent thread initialization.*/ PORT_SETUP_CONTEXT(tp, tcp->wbase, tcp->wend, tcp->funcp, tcp->arg); /* Initialization hook.*/ CH_CFG_THREAD_EXT_INIT_HOOK(tp); tp++; tcp++; } #if CH_DBG_ENABLE_STACK_CHECK /* The idle thread is a special case because its stack is set up by the runtime environment.*/ tp->stklimit = THD_IDLE_BASE; #endif /* Interrupts partially enabled. It is equivalent to entering the kernel critical zone.*/ chSysSuspend(); #if CH_DBG_SYSTEM_STATE_CHECK == TRUE nil.lock_cnt = (cnt_t)1; #endif /* Heap initialization, if enabled.*/ #if CH_CFG_USE_HEAP == TRUE _heap_init(); #endif /* Port layer initialization last because it depend on some of the initializations performed before.*/ port_init(); /* Runs the highest priority thread, the current one becomes the idle thread.*/ nil.current = nil.next = nil.threads; port_switch(nil.current, tp); chSysUnlock(); }
/** * @brief Switches to the first thread on the runnable queue. * @note Not a user function, it is meant to be invoked by the scheduler * itself or from within the port layer. * * @special */ void chSchDoReschedule(void) { thread_t *otp = nil.current; nil.current = nil.next; if (otp == &nil.threads[CH_CFG_NUM_THREADS]) { CH_CFG_IDLE_LEAVE_HOOK(); } port_switch(nil.next, otp); }
/** * @brief Reschedules if needed. * * @sclass */ void chSchRescheduleS(void) { if (chSchIsRescRequiredI()) { thread_t *otp = nil.current; nil.current = nil.next; if (otp == &nil.threads[NIL_CFG_NUM_THREADS]) { NIL_CFG_IDLE_LEAVE_HOOK(); } port_switch(nil.next, otp); } }
/** * @brief Initializes the kernel. * @details Initializes the kernel structures, the current instructions flow * becomes the idle thread upon return. The idle thread must not * invoke any kernel primitive able to change state to not runnable. * * @special */ void nilSysInit(void) { thread_ref_t tr; const thread_config_t *tcp; /* Port layer initialization.*/ port_init(); /* Iterates through the list of defined threads.*/ for (tr = &nil.threads[0], tcp = nil_thd_configs; #if WHG_MOD tr < nil.idlep; #else /* WHG_MOD */ tr < &nil.threads[NIL_CFG_NUM_THREADS]; #endif /* WHG_MOD */ tr++, tcp++) { tr->state = NIL_THD_READY; tr->timeout = 0; /* Port dependent thread initialization.*/ SETUP_CONTEXT(tr, tcp->wap, tcp->size, tcp->funcp, tcp->arg); /* Initialization hook.*/ #if defined(NIL_CFG_THREAD_EXT_INIT_HOOK) NIL_CFG_THREAD_EXT_INIT_HOOK(tr); #endif } /* Runs the highest priority thread, the current one becomes the null thread.*/ nil.current = nil.next = nil.threads; #if WHG_MOD port_switch(nil.threads, nil.idlep); #else /* WHG_MOD */ port_switch(nil.threads, &nil.threads[NIL_CFG_NUM_THREADS]); #endif /* WHG_MOD */ /* Interrupts enabled for the idle thread.*/ nilSysEnable(); }
/** * @brief Initializes the kernel. * @details Initializes the kernel structures, the current instructions flow * becomes the idle thread upon return. The idle thread must not * invoke any kernel primitive able to change state to not runnable. * @note This function assumes that the @p nil global variable has been * zeroed by the runtime environment. If this is not the case then * make sure to clear it before calling this function. * * @special */ void chSysInit(void) { thread_t *tp; const thread_config_t *tcp; /* Port layer initialization.*/ port_init(); /* System initialization hook.*/ NIL_CFG_SYSTEM_INIT_HOOK(); /* Iterates through the list of defined threads.*/ tp = &nil.threads[0]; tcp = nil_thd_configs; while (tp < &nil.threads[NIL_CFG_NUM_THREADS]) { #if NIL_CFG_ENABLE_STACK_CHECK tp->stklim = (stkalign_t *)tcp->wbase; #endif /* Port dependent thread initialization.*/ PORT_SETUP_CONTEXT(tp, tcp->wend, tcp->funcp, tcp->arg); /* Initialization hook.*/ NIL_CFG_THREAD_EXT_INIT_HOOK(tp); tp++; tcp++; } #if NIL_CFG_ENABLE_STACK_CHECK /* The idle thread is a special case because its stack is set up by the runtime environment.*/ tp->stklim = THD_IDLE_BASE; #endif /* Runs the highest priority thread, the current one becomes the null thread.*/ nil.current = nil.next = nil.threads; port_switch(nil.current, tp); /* Interrupts enabled for the idle thread.*/ chSysEnable(); }
/** * @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"); } }