From 57554055d21fad54e28f921f59da2e9f7505ec01 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Sat, 3 Mar 2018 02:31:05 -0600 Subject: [PATCH] kernel: add a new API for setting thread names Added k_thread_name_set() and enable thread name setting when declaring static threads. This is enabled only when THREAD_MONITOR is used. System threads get a name by default. Signed-off-by: Anas Nashif --- include/kernel.h | 31 ++++++++++-- kernel/Kconfig | 5 ++ kernel/include/kernel_internal.h | 2 +- kernel/include/kernel_structs.h | 4 ++ kernel/init.c | 7 +-- kernel/thread.c | 81 +++++++++++++++++++++++++------- kernel/work_q.c | 4 ++ subsys/shell/shell.c | 3 +- 8 files changed, 113 insertions(+), 24 deletions(-) diff --git a/include/kernel.h b/include/kernel.h index 67345898ffb..ee6ef049473 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -539,6 +539,11 @@ struct k_thread { struct k_thread *next_thread; #endif +#if defined(CONFIG_THREAD_NAME) + /* Thread name */ + const char *name; +#endif + #ifdef CONFIG_THREAD_CUSTOM_DATA /** crude thread-local storage */ void *custom_data; @@ -914,11 +919,12 @@ struct _static_thread_data { u32_t init_options; s32_t init_delay; void (*init_abort)(void); + const char *init_name; }; #define _THREAD_INITIALIZER(thread, stack, stack_size, \ entry, p1, p2, p3, \ - prio, options, delay, abort) \ + prio, options, delay, abort, tname) \ { \ .init_thread = (thread), \ .init_stack = (stack), \ @@ -931,6 +937,7 @@ struct _static_thread_data { .init_options = (options), \ .init_delay = (delay), \ .init_abort = (abort), \ + .init_name = STRINGIFY(tname), \ } /** @@ -977,7 +984,7 @@ struct _static_thread_data { _THREAD_INITIALIZER(&_k_thread_obj_##name, \ _k_thread_stack_##name, stack_size, \ entry, p1, p2, p3, prio, options, delay, \ - NULL); \ + NULL, name); \ const k_tid_t name = (k_tid_t)&_k_thread_obj_##name /** @@ -1223,10 +1230,28 @@ __syscall void k_thread_custom_data_set(void *value); */ __syscall void *k_thread_custom_data_get(void); +/** + * @brief Set current thread name + * + * Set the name of the thread to be used when THREAD_MONITOR is enabled for + * tracing and debugging. + * + */ +__syscall void k_thread_name_set(k_tid_t thread_id, const char *value); + +/** + * @brief Get thread name + * + * Get the name of a thread + * + * @param thread_id Thread ID + * + */ +__syscall const char *k_thread_name_get(k_tid_t thread_id); + /** * @} */ - #include /** diff --git a/kernel/Kconfig b/kernel/Kconfig index 3f33f981e61..64a890b347b 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -339,6 +339,11 @@ config THREAD_MONITOR This option instructs the kernel to maintain a list of all threads (excluding those that have not yet started or have already terminated). + +config THREAD_NAME + bool "Thread name [EXPERIMENTAL]" + help + This option allows to set a name for a thread. endmenu menu "Work Queue Options" diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index 9b203fc2d66..3e239c41401 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -49,7 +49,7 @@ extern void _setup_new_thread(struct k_thread *new_thread, k_thread_stack_t *stack, size_t stack_size, k_thread_entry_t entry, void *p1, void *p2, void *p3, - int prio, u32_t options); + int prio, u32_t options, const char *name); #ifdef CONFIG_USERSPACE /** diff --git a/kernel/include/kernel_structs.h b/kernel/include/kernel_structs.h index 96b1f5f7659..1bb40ce93b1 100644 --- a/kernel/include/kernel_structs.h +++ b/kernel/include/kernel_structs.h @@ -236,6 +236,10 @@ static ALWAYS_INLINE void _new_thread_init(struct k_thread *thread, thread->custom_data = NULL; #endif +#ifdef CONFIG_THREAD_NAME + thread->name = NULL; +#endif + #if defined(CONFIG_USERSPACE) thread->mem_domain_info.mem_domain = NULL; #endif /* CONFIG_USERSPACE */ diff --git a/kernel/init.c b/kernel/init.c index f1e3d9054fe..2d0d1397a8d 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -34,6 +34,8 @@ #include #include +#define IDLE_THREAD_NAME "idle" + /* boot banner items */ #if defined(CONFIG_BOOT_DELAY) && CONFIG_BOOT_DELAY > 0 #define BOOT_DELAY_BANNER " (delayed boot " \ @@ -251,7 +253,7 @@ static void init_idle_thread(struct k_thread *thr, k_thread_stack_t *stack) _setup_new_thread(thr, stack, IDLE_STACK_SIZE, idle, NULL, NULL, NULL, - K_LOWEST_THREAD_PRIO, K_ESSENTIAL); + K_LOWEST_THREAD_PRIO, K_ESSENTIAL, IDLE_THREAD_NAME); _mark_thread_as_started(thr); } #endif @@ -314,8 +316,7 @@ static void prepare_multithreading(struct k_thread *dummy_thread) _setup_new_thread(_main_thread, _main_stack, MAIN_STACK_SIZE, bg_thread_main, NULL, NULL, NULL, - CONFIG_MAIN_THREAD_PRIORITY, K_ESSENTIAL); - + CONFIG_MAIN_THREAD_PRIORITY, K_ESSENTIAL, "main"); sys_trace_thread_create(_main_thread); _mark_thread_as_started(_main_thread); diff --git a/kernel/thread.c b/kernel/thread.c index bbd2b14e909..0fe86e2f580 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -130,22 +130,11 @@ void _impl_k_thread_custom_data_set(void *value) _current->custom_data = value; } -#ifdef CONFIG_USERSPACE -Z_SYSCALL_HANDLER(k_thread_custom_data_set, data) -{ - _impl_k_thread_custom_data_set((void *)data); - return 0; -} -#endif - void *_impl_k_thread_custom_data_get(void) { return _current->custom_data; } -#ifdef CONFIG_USERSPACE -Z_SYSCALL_HANDLER0_SIMPLE(k_thread_custom_data_get); -#endif /* CONFIG_USERSPACE */ #endif /* CONFIG_THREAD_CUSTOM_DATA */ #if defined(CONFIG_THREAD_MONITOR) @@ -173,7 +162,63 @@ void _thread_monitor_exit(struct k_thread *thread) irq_unlock(key); } -#endif /* CONFIG_THREAD_MONITOR */ +#endif + +#ifdef CONFIG_THREAD_NAME +void _impl_k_thread_name_set(struct k_thread *thread, const char *value) +{ + if (thread == NULL) { + _current->name = value; + } else { + thread->name = value; + } +} + +const char *_impl_k_thread_name_get(struct k_thread *thread) +{ + return (const char *)thread->name; +} + +#else +void _impl_k_thread_name_set(k_tid_t thread_id, const char *value) +{ + ARG_UNUSED(thread_id); + ARG_UNUSED(value); +} + +const char *_impl_k_thread_name_get(k_tid_t thread_id) +{ + ARG_UNUSED(thread_id); + return NULL; +} +#endif /* CONFIG_THREAD_NAME */ + +#ifdef CONFIG_USERSPACE + +#if defined(CONFIG_THREAD_NAME) +Z_SYSCALL_HANDLER(k_thread_name_set, thread, data) +{ + char *name_copy = NULL; + + name_copy = z_user_string_alloc_copy((char *)data, 64); + _impl_k_thread_name_set((struct k_thread *)thread, name_copy); + return 0; +} + +Z_SYSCALL_HANDLER1_SIMPLE(k_thread_name_get, K_OBJ_THREAD, k_tid_t); +#endif + +#ifdef CONFIG_THREAD_CUSTOM_DATA +Z_SYSCALL_HANDLER(k_thread_custom_data_set, data) +{ + _impl_k_thread_custom_data_set((void *)data); + return 0; +} + +Z_SYSCALL_HANDLER0_SIMPLE(k_thread_custom_data_get); +#endif /* CONFIG_THREAD_CUSTOM_DATA */ + +#endif #ifdef CONFIG_STACK_SENTINEL /* Check that the stack sentinel is still present @@ -291,7 +336,7 @@ void _setup_new_thread(struct k_thread *new_thread, k_thread_stack_t *stack, size_t stack_size, k_thread_entry_t entry, void *p1, void *p2, void *p3, - int prio, u32_t options) + int prio, u32_t options, const char *name) { stack_size = adjust_stack_size(stack_size); @@ -329,6 +374,9 @@ void _setup_new_thread(struct k_thread *new_thread, _kernel.threads = new_thread; irq_unlock(key); #endif +#ifdef CONFIG_THREAD_NAME + new_thread->name = name; +#endif #ifdef CONFIG_USERSPACE _k_object_init(new_thread); _k_object_init(stack); @@ -372,7 +420,7 @@ k_tid_t _impl_k_thread_create(struct k_thread *new_thread, __ASSERT(!_is_in_isr(), "Threads may not be created in ISRs"); _setup_new_thread(new_thread, stack, stack_size, entry, p1, p2, p3, - prio, options); + prio, options, NULL); if (delay != K_FOREVER) { schedule_new_thread(new_thread, delay); @@ -455,7 +503,7 @@ Z_SYSCALL_HANDLER(k_thread_create, _setup_new_thread((struct k_thread *)new_thread, stack, stack_size, (k_thread_entry_t)entry, (void *)p1, (void *)margs->arg6, (void *)margs->arg7, prio, - options); + options, NULL); if (delay != K_FOREVER) { schedule_new_thread(new_thread, delay); @@ -607,7 +655,8 @@ void _init_static_threads(void) thread_data->init_p2, thread_data->init_p3, thread_data->init_prio, - thread_data->init_options); + thread_data->init_options, + thread_data->init_name); thread_data->init_thread->init_data = thread_data; } diff --git a/kernel/work_q.c b/kernel/work_q.c index 7061f5e49ef..fb2e891ad3f 100644 --- a/kernel/work_q.c +++ b/kernel/work_q.c @@ -16,6 +16,8 @@ #include #include +#define WORKQUEUE_THREAD_NAME "workqueue" + static void work_q_main(void *work_q_ptr, void *p2, void *p3) { struct k_work_q *work_q = work_q_ptr; @@ -53,6 +55,8 @@ void k_work_q_start(struct k_work_q *work_q, k_thread_stack_t *stack, k_queue_init(&work_q->queue); (void)k_thread_create(&work_q->thread, stack, stack_size, work_q_main, work_q, 0, 0, prio, 0, 0); + + k_thread_name_set(&work_q->thread, WORKQUEUE_THREAD_NAME); _k_object_init(work_q); } diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index b74ca686848..148f2853ca1 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -1256,11 +1256,12 @@ int shell_init(const struct shell *shell, const void *transport_config, } } - (void)k_thread_create(shell->thread, + k_tid_t tid = k_thread_create(shell->thread, shell->stack, CONFIG_SHELL_STACK_SIZE, shell_thread, (void *)shell, NULL, NULL, CONFIG_SHELL_THREAD_PRIO, 0, K_NO_WAIT); + k_thread_name_set(tid, "shell"); return 0; }