From d151776e59f2730927b25412ab3e324be74f6323 Mon Sep 17 00:00:00 2001 From: Juan Manuel Cruz Date: Wed, 2 Mar 2016 17:31:26 -0600 Subject: [PATCH] debug: thread monitor allow to access more thread information The thread monitor allows to iterate over the thread context structures for each existing thread (fiber/task) in the system. Thread context structures do not expose thread entry information directly. Although all the information can be scavenged from memory stacks. Besides, accessing the information depends on the stack implementation for each architecture. By extending the tcs we allow a direct access to the thread entry point and its parameters, only when thread monitor is enabled. It also allows a task to access its kernel task structure through the first parameter of the thread. This allows a debugger application to access the information directly from the thread context structures list. Change-Id: I0a435942b80eddffdf405016ac4056eb7aa1239c Signed-off-by: Juan Manuel Cruz --- arch/arc/core/thread.c | 7 +++++++ arch/arc/include/nano_private.h | 11 +++++++++++ arch/arm/core/thread.c | 8 ++++++++ arch/arm/include/nano_private.h | 11 +++++++++++ arch/x86/core/i386_sysV_abi/thread.c | 8 ++++++++ arch/x86/include/nano_private.h | 10 ++++++++++ kernel/microkernel/k_task.c | 9 ++++++++- 7 files changed, 63 insertions(+), 1 deletion(-) diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 56cf3e0f996..809a6499d7b 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -143,6 +143,13 @@ void _new_thread(char *pStackMem, unsigned stackSize, _thread_entry_t pEntry, tcs->custom_data = NULL; #endif +#ifdef CONFIG_THREAD_MONITOR + /* + * In debug mode tcs->entry give direct access to the thread entry + * and the corresponding parameters. + */ + tcs->entry = (struct __thread_entry *)(pInitCtx); +#endif /* * intlock_key is constructed based on ARCv2 ISA Programmer's * Reference Manual CLRI instruction description: diff --git a/arch/arc/include/nano_private.h b/arch/arc/include/nano_private.h index f63786cd72b..110388c9dee 100644 --- a/arch/arc/include/nano_private.h +++ b/arch/arc/include/nano_private.h @@ -48,6 +48,16 @@ extern "C" { #endif #ifndef _ASMLANGUAGE + +#ifdef CONFIG_THREAD_MONITOR +struct __thread_entry { + _thread_entry_t pEntry; + void *parameter1; + void *parameter2; + void *parameter3; +}; +#endif /*CONFIG_THREAD_MONITOR*/ + struct coop { /* * Saved on the stack as part of handling a regular IRQ or by the kernel @@ -175,6 +185,7 @@ struct tcs { struct coop coopReg; struct preempt preempReg; #ifdef CONFIG_THREAD_MONITOR + struct __thread_entry *entry; /* thread entry and parameters description */ struct tcs *next_thread; /* next item in list of ALL fiber+tasks */ #endif #ifdef CONFIG_NANO_TIMEOUTS diff --git a/arch/arm/core/thread.c b/arch/arm/core/thread.c index ef3ad3c53ad..d0290e0cc41 100644 --- a/arch/arm/core/thread.c +++ b/arch/arm/core/thread.c @@ -135,6 +135,14 @@ void _new_thread(char *pStackMem, unsigned stackSize, _thread_entry_t pEntry, tcs->custom_data = NULL; #endif +#ifdef CONFIG_THREAD_MONITOR + /* + * In debug mode tcs->entry give direct access to the thread entry + * and the corresponding parameters. + */ + tcs->entry = (struct __thread_entry *)(pInitCtx); +#endif + tcs->preempReg.psp = (uint32_t)pInitCtx; tcs->basepri = 0; diff --git a/arch/arm/include/nano_private.h b/arch/arm/include/nano_private.h index fb08540b78c..a2559bfd09e 100644 --- a/arch/arm/include/nano_private.h +++ b/arch/arm/include/nano_private.h @@ -45,6 +45,16 @@ extern "C" { #endif #ifndef _ASMLANGUAGE + +#ifdef CONFIG_THREAD_MONITOR +struct __thread_entry { + _thread_entry_t pEntry; + void *parameter1; + void *parameter2; + void *parameter3; +}; +#endif /*CONFIG_THREAD_MONITOR*/ + struct coop { /* * Unused for Cortex-M, which automatically saves the neccesary @@ -120,6 +130,7 @@ struct tcs { struct coop coopReg; struct preempt preempReg; #if defined(CONFIG_THREAD_MONITOR) + struct __thread_entry *entry; /* thread entry and parameters description */ struct tcs *next_thread; /* next item in list of ALL fiber+tasks */ #endif #ifdef CONFIG_NANO_TIMEOUTS diff --git a/arch/x86/core/i386_sysV_abi/thread.c b/arch/x86/core/i386_sysV_abi/thread.c index 5337fb93e54..f389d73d68b 100644 --- a/arch/x86/core/i386_sysV_abi/thread.c +++ b/arch/x86/core/i386_sysV_abi/thread.c @@ -103,6 +103,14 @@ static void _new_thread_internal(char *pStackMem, unsigned stackSize, pInitialCtx = (unsigned long *)STACK_ROUND_DOWN(pStackMem + stackSize); +#ifdef CONFIG_THREAD_MONITOR + /* + * In debug mode tcs->entry give direct access to the thread entry + * and the corresponding parameters. + */ + tcs->entry = (struct __thread_entry *)(pInitialCtx - + sizeof(struct __thread_entry)); +#endif /* * We subtract 11 here to account for the thread entry routine * parameters diff --git a/arch/x86/include/nano_private.h b/arch/x86/include/nano_private.h index 6a725dce1bb..42771bb4773 100644 --- a/arch/x86/include/nano_private.h +++ b/arch/x86/include/nano_private.h @@ -409,6 +409,15 @@ extern "C" { #endif +#ifdef CONFIG_THREAD_MONITOR +struct __thread_entry { + _thread_entry_t pEntry; + void *parameter1; + void *parameter2; + void *parameter3; +}; +#endif /*CONFIG_THREAD_MONITOR*/ + /* * The following structure defines the set of 'non-volatile' integer registers. * These registers must be preserved by a called C function. These are the @@ -639,6 +648,7 @@ struct tcs { tPreempReg preempReg; /* volatile integer register storage */ #if defined(CONFIG_THREAD_MONITOR) + struct __thread_entry *entry; /* thread entry and parameters description */ struct tcs *next_thread; /* next item in list of ALL fiber+tasks */ #endif #ifdef CONFIG_GDB_INFO diff --git a/kernel/microkernel/k_task.c b/kernel/microkernel/k_task.c index 30046a8741e..ca1aeb458d5 100644 --- a/kernel/microkernel/k_task.c +++ b/kernel/microkernel/k_task.c @@ -181,6 +181,7 @@ void _k_state_bit_set(struct k_task *task_ptr, uint32_t bits) static void start_task(struct k_task *X, void (*func)(void)) { unsigned int task_options; + void *parameter1; /* Note: the field X->worksize now represents the task size in bytes */ @@ -196,10 +197,16 @@ static void start_task(struct k_task *X, void (*func)(void)) * the thread is a task, rather than a fiber. */ +#ifdef CONFIG_THREAD_MONITOR + parameter1 = (void *)X; +#else + parameter1 = (void *)0; +#endif + _new_thread((char *)X->workspace, /* pStackMem */ X->worksize, /* stackSize */ (_thread_entry_t)func, /* pEntry */ - (void *)0, /* parameter1 */ + parameter1, /* parameter1 */ (void *)0, /* parameter2 */ (void *)0, /* parameter3 */ -1, /* priority */