diff --git a/include/kernel.h b/include/kernel.h index 315a8891265..c67380ec077 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -533,6 +533,8 @@ enum execution_context_types { * @ingroup kernel_apis * @{ */ +typedef void (*k_thread_user_cb_t)(const struct k_thread *thread, + void *user_data); /** * @brief Analyze the main, idle, interrupt and system workqueue call stacks @@ -552,6 +554,25 @@ enum execution_context_types { */ extern void k_call_stacks_analyze(void); +/** + * @brief Iterate over all the threads in the system. + * + * This routine iterates over all the threads in the system and + * calls the user_cb function for each thread. + * + * @param user_cb Pointer to the user callback function. + * @param user_data Pointer to user data. + * + * @note CONFIG_THREAD_MONITOR must be set for this function + * to be effective. Also this API uses irq_lock to protect the + * _kernel.threads list which means creation of new threads and + * terminations of existing threads are blocked until this + * API returns. + * + * @return N/A + */ +extern void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data); + /** @} */ /** diff --git a/kernel/thread.c b/kernel/thread.c index f6e6d3021b2..c67db7d9bfa 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -36,6 +36,29 @@ extern struct _static_thread_data _static_thread_data_list_end[]; thread_data < _static_thread_data_list_end; \ thread_data++) +#if defined(CONFIG_THREAD_MONITOR) +void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data) +{ + struct k_thread *thread; + unsigned int key; + + __ASSERT(user_cb, "user_cb can not be NULL"); + + /* + * Lock is needed to make sure that the _kernel.threads is not being + * modified by the user_cb either dircetly or indircetly. + * The indircet ways are through calling k_thread_create and + * k_thread_abort from user_cb. + */ + key = irq_lock(); + for (thread = _kernel.threads; thread; thread = thread->next_thread) { + user_cb(thread, user_data); + } + irq_unlock(key); +} +#else +void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data) { } +#endif int k_is_in_isr(void) {