diff --git a/core/include/sched.h b/core/include/sched.h index d62a555b92..db9fad5463 100644 --- a/core/include/sched.h +++ b/core/include/sched.h @@ -298,6 +298,62 @@ static inline void sched_runq_advance(uint8_t prio) clist_lpoprpush(&sched_runqueues[prio]); } +#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) || defined(DOXYGEN) +/** + * @brief Scheduler runqueue (change) callback + * + * @details Function has to be provided by the user of this API. + * It will be called: + * - when the scheduler is run, + * - when a thread enters the active queue or + * - when the last thread leaves a queue + * + * @warning This API is not intended for out of tree users. + * Breaking API changes will be done without notice and + * without deprecation. Consider yourself warned! + * + * @param prio the priority of the runqueue that changed + * + */ +extern void sched_runq_callback(uint8_t prio); +#endif + +/** + * @brief Tell if the number of threads in a runqueue is 0 + * + * @param[in] prio The priority of the runqueue to get information of + * @return Truth value for that information + * @warning This API is not intended for out of tree users. + */ +static inline int sched_runq_is_empty(uint8_t prio) +{ + return clist_is_empty(&sched_runqueues[prio]); +} + +/** + * @brief Tell if the number of threads in a runqueue is 1 + * + * @param[in] prio The priority of the runqueue to get information of + * @return Truth value for that information + * @warning This API is not intended for out of tree users. + */ +static inline int sched_runq_exactly_one(uint8_t prio) +{ + return clist_exactly_one(&sched_runqueues[prio]); +} + +/** + * @brief Tell if the number of threads in a runqueue greater than 1 + * + * @param[in] prio The priority of the runqueue to get information of + * @return Truth value for that information + * @warning This API is not intended for out of tree users. + */ +static inline int sched_runq_more_than_one(uint8_t prio) +{ + return clist_more_than_one(&sched_runqueues[prio]); +} + #ifdef __cplusplus } #endif diff --git a/core/sched.c b/core/sched.c index 50254a63c2..b6eb15c28f 100644 --- a/core/sched.c +++ b/core/sched.c @@ -75,8 +75,8 @@ clist_node_t sched_runqueues[SCHED_PRIO_LEVELS]; static uint32_t runqueue_bitcache = 0; #ifdef MODULE_SCHED_CB -static void (*sched_cb) (kernel_pid_t active_thread, - kernel_pid_t next_thread) = NULL; +static void (*sched_cb)(kernel_pid_t active_thread, + kernel_pid_t next_thread) = NULL; #endif /* Depending on whether the CLZ instruction is available, the order of the @@ -156,6 +156,10 @@ thread_t *__attribute__((used)) sched_run(void) thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next, thread_t, rq_entry); +#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) + sched_runq_callback(nextrq); +#endif + DEBUG( "sched_run: active thread: %" PRIkernel_pid ", next thread: %" PRIkernel_pid "\n", (kernel_pid_t)((active_thread == NULL) @@ -220,6 +224,16 @@ void sched_set_status(thread_t *process, thread_status_t status) clist_rpush(&sched_runqueues[process->priority], &(process->rq_entry)); _set_runqueue_bit(process); + + /* some thread entered a runqueue + * if it is the active runqueue + * inform the runqueue_change callback */ +#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) + thread_t *active_thread = thread_get_active(); + if (active_thread && active_thread->priority == process->priority) { + sched_runq_callback(process->priority); + } +#endif } } else { @@ -231,6 +245,9 @@ void sched_set_status(thread_t *process, thread_status_t status) if (!sched_runqueues[process->priority].next) { _clear_runqueue_bit(process); +#if (IS_USED(MODULE_SCHED_RUNQ_CALLBACK)) + sched_runq_callback(process->priority); +#endif } } } diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index f684dc6b3b..645d69110a 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -135,6 +135,7 @@ PSEUDOMODULES += saul_nrf_vddh PSEUDOMODULES += saul_pwm PSEUDOMODULES += scanf_float PSEUDOMODULES += sched_cb +PSEUDOMODULES += sched_runq_callback PSEUDOMODULES += semtech_loramac_rx PSEUDOMODULES += shell_hooks PSEUDOMODULES += slipdev_stdio