From 110b8e42ff5d718d26801d260559456f3d083979 Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Fri, 27 Apr 2018 12:55:43 +0530 Subject: [PATCH] kernel: Add k_thread_foreach API Add k_thread_foreach API to iterate over all the threads in the system. This API can be used for debugging threads in multi threaded environment to dump and analyze various thread parameters like priority, state, stack address etc... Signed-off-by: Ramakrishna Pallala --- include/kernel.h | 21 +++++++++++++++++++++ kernel/thread.c | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+) 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) {