Skip to content

Commit 2c529ce

Browse files
rakonsnashif
authored andcommitted
kernel: thread: k_thread_foreach_unlocked: Implement
Implement thread foreach processing with limited locking to allow threads processing that may take more time but allows missing some threads processing when the thread list is modified. Signed-off-by: Radoslaw Koppel <radoslaw.koppel@nordicsemi.no>
1 parent 5b1a524 commit 2c529ce

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

include/kernel.h

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -644,15 +644,45 @@ typedef void (*k_thread_user_cb_t)(const struct k_thread *thread,
644644
* @param user_data Pointer to user data.
645645
*
646646
* @note CONFIG_THREAD_MONITOR must be set for this function
647-
* to be effective. Also this API uses irq_lock to protect the
648-
* _kernel.threads list which means creation of new threads and
649-
* terminations of existing threads are blocked until this
650-
* API returns.
647+
* to be effective.
648+
* @note This API uses @ref k_spin_lock to protect the _kernel.threads
649+
* list which means creation of new threads and terminations of existing
650+
* threads are blocked until this API returns.
651651
*
652652
* @return N/A
653653
*/
654654
extern void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data);
655655

656+
/**
657+
* @brief Iterate over all the threads in the system without locking.
658+
*
659+
* This routine works exactly the same like @ref k_thread_foreach
660+
* but unlocks interrupts when user_cb is executed.
661+
*
662+
* @param user_cb Pointer to the user callback function.
663+
* @param user_data Pointer to user data.
664+
*
665+
* @note CONFIG_THREAD_MONITOR must be set for this function
666+
* to be effective.
667+
* @note This API uses @ref k_spin_lock only when accessing the _kernel.threads
668+
* queue elements. It unlocks it during user callback function processing.
669+
* If a new task is created when this @c foreach function is in progress,
670+
* the added new task would not be included in the enumeration.
671+
* If a task is aborted during this enumeration, there would be a race here
672+
* and there is a possibility that this aborted task would be included in the
673+
* enumeration.
674+
* @note If the task is aborted and the memory occupied by its @c k_thread
675+
* structure is reused when this @c k_thread_foreach_unlocked is in progress
676+
* it might even lead to the system behave unstable.
677+
* This function may never return, as it would follow some @c next task
678+
* pointers treating given pointer as a pointer to the k_thread structure
679+
* while it is something different right now.
680+
* Do not reuse the memory that was occupied by k_thread structure of aborted
681+
* task if it was aborted after this function was called in any context.
682+
*/
683+
extern void k_thread_foreach_unlocked(
684+
k_thread_user_cb_t user_cb, void *user_data);
685+
656686
/** @} */
657687

658688
/**

kernel/thread.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ void k_thread_foreach(k_thread_user_cb_t user_cb, void *user_data)
5555
#endif
5656
}
5757

58+
void k_thread_foreach_unlocked(k_thread_user_cb_t user_cb, void *user_data)
59+
{
60+
#if defined(CONFIG_THREAD_MONITOR)
61+
struct k_thread *thread;
62+
k_spinlock_key_t key;
63+
64+
__ASSERT(user_cb != NULL, "user_cb can not be NULL");
65+
66+
key = k_spin_lock(&lock);
67+
for (thread = _kernel.threads; thread; thread = thread->next_thread) {
68+
k_spin_unlock(&lock, key);
69+
user_cb(thread, user_data);
70+
key = k_spin_lock(&lock);
71+
}
72+
k_spin_unlock(&lock, key);
73+
#endif
74+
}
75+
5876
bool k_is_in_isr(void)
5977
{
6078
return arch_is_in_isr();

0 commit comments

Comments
 (0)