diff options
-rw-r--r-- | core/host/build.mk | 2 | ||||
-rw-r--r-- | core/host/host_task.h | 26 | ||||
-rw-r--r-- | core/host/main.c | 1 | ||||
-rw-r--r-- | core/host/panic.c | 1 | ||||
-rw-r--r-- | core/host/stack_trace.c | 97 | ||||
-rw-r--r-- | core/host/task.c | 100 | ||||
-rw-r--r-- | include/stack_trace.h | 25 | ||||
-rw-r--r-- | include/task.h | 5 | ||||
-rw-r--r-- | include/test_util.h | 12 | ||||
-rw-r--r-- | test/interrupt.c | 2 |
10 files changed, 174 insertions, 97 deletions
diff --git a/core/host/build.mk b/core/host/build.mk index 121ef98272..183714f6c4 100644 --- a/core/host/build.mk +++ b/core/host/build.mk @@ -8,4 +8,4 @@ CFLAGS_CPU=-fno-builtin -core-y=main.o task.o timer.o panic.o disabled.o +core-y=main.o task.o timer.o panic.o disabled.o stack_trace.o diff --git a/core/host/host_task.h b/core/host/host_task.h new file mode 100644 index 0000000000..e4e0712ea2 --- /dev/null +++ b/core/host/host_task.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Emulator task scheduling module */ + +#ifndef __CROS_EC_HOST_TASK_H +#define __CROS_EC_HOST_TASK_H + +#include <pthread.h> + +#include "task.h" + +/** + * Returns the thread corresponding to the task. + */ +pthread_t task_get_thread(task_id_t tskid); + +/** + * Returns the ID of the active task, regardless of current thread + * context. + */ +task_id_t task_get_running(void); + +#endif /* __CROS_EC_HOST_TASK_H */ diff --git a/core/host/main.c b/core/host/main.c index 2d3622c269..fa5077b33d 100644 --- a/core/host/main.c +++ b/core/host/main.c @@ -9,6 +9,7 @@ #include "flash.h" #include "hooks.h" #include "keyboard_scan.h" +#include "stack_trace.h" #include "system.h" #include "task.h" #include "test_util.h" diff --git a/core/host/panic.c b/core/host/panic.c index 260329cc39..ee21577aec 100644 --- a/core/host/panic.c +++ b/core/host/panic.c @@ -8,6 +8,7 @@ #include "common.h" #include "panic.h" +#include "stack_trace.h" #include "test_util.h" #include "util.h" diff --git a/core/host/stack_trace.c b/core/host/stack_trace.c new file mode 100644 index 0000000000..67ceac5891 --- /dev/null +++ b/core/host/stack_trace.c @@ -0,0 +1,97 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <execinfo.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> + +#include "host_task.h" +#include "host_test.h" +#include "timer.h" + +#define SIGNAL_TRACE_DUMP SIGTERM +#define MAX_TRACE 30 +/* + * When trace dump is requested from signal handler, skip: + * _task_dump_trace_impl + * _task_dump_trace_dispath + * A function in libc + */ +#define SIGNAL_TRACE_OFFSET 3 +/* + * When trace dump is requested from task_dump_trace(), skip: + * task_dump_trace + * _task_dump_trace_impl + */ +#define DIRECT_TRACE_OFFSET 2 + +static pthread_t main_thread; + +static void __attribute__((noinline)) _task_dump_trace_impl(int offset) +{ + void *trace[MAX_TRACE]; + size_t sz; + char **messages; + char buf[256]; + FILE *file; + int i, nb; + + sz = backtrace(trace, MAX_TRACE); + messages = backtrace_symbols(trace + offset, sz - offset); + + for (i = 0; i < sz - offset; ++i) { + fprintf(stderr, "#%-2d %s\n", i, messages[i]); + sprintf(buf, "addr2line %p -e %s", + trace[i + offset], __get_prog_name()); + file = popen(buf, "r"); + if (file) { + nb = fread(buf, 1, sizeof(buf) - 1, file); + buf[nb] = '\0'; + fprintf(stderr, " %s", buf); + pclose(file); + } + } + fflush(stderr); + free(messages); +} + +void __attribute__((noinline)) task_dump_trace(void) +{ + _task_dump_trace_impl(DIRECT_TRACE_OFFSET); +} + +static void __attribute__((noinline)) _task_dump_trace_dispatch(int sig) +{ + int need_dispatch = 1; + task_id_t running = task_get_running(); + + if (!pthread_equal(pthread_self(), main_thread)) { + need_dispatch = 0; + } else if (!task_start_called()) { + fprintf(stderr, "Stack trace of main thread:\n"); + need_dispatch = 0; + } else if (in_interrupt_context()) { + fprintf(stderr, "Stack trace of ISR:\n"); + } else { + fprintf(stderr, "Stack trace of task %d (%s):\n", + running, task_get_name(running)); + } + + if (need_dispatch) { + pthread_kill(task_get_thread(running), SIGNAL_TRACE_DUMP); + } else { + _task_dump_trace_impl(SIGNAL_TRACE_OFFSET); + udelay(100 * MSEC); /* Leave time for stderr to flush */ + exit(1); + } +} + +void task_register_tracedump(void) +{ + /* Trace dumper MUST be registered from main thread */ + main_thread = pthread_self(); + signal(SIGNAL_TRACE_DUMP, _task_dump_trace_dispatch); +} diff --git a/core/host/task.c b/core/host/task.c index 08c70da66b..5bff856def 100644 --- a/core/host/task.c +++ b/core/host/task.c @@ -5,7 +5,6 @@ /* Task scheduling / events module for Chrome EC operating system */ -#include <execinfo.h> #include <malloc.h> #include <pthread.h> #include <semaphore.h> @@ -18,7 +17,7 @@ #include "atomic.h" #include "common.h" #include "console.h" -#include "host_test.h" +#include "host_task.h" #include "task.h" #include "task_id.h" #include "test_util.h" @@ -26,22 +25,6 @@ #define SIGNAL_INTERRUPT SIGUSR1 -#define SIGNAL_TRACE_DUMP SIGTERM -#define MAX_TRACE 30 -/* - * When trace dump is requested from signal handler, skip: - * _task_dump_trace_impl - * _task_dump_trace_dispath - * A function in libc - */ -#define SIGNAL_TRACE_OFFSET 3 -/* - * When trace dump is requested from task_dump_trace(), skip: - * task_dump_trace - * _task_dump_trace_impl - */ -#define DIRECT_TRACE_OFFSET 2 - struct emu_task_t { pthread_t thread; pthread_cond_t resume; @@ -60,7 +43,6 @@ static pthread_cond_t scheduler_cond; static pthread_mutex_t run_lock; static task_id_t running_task_id; static int task_started; -static pthread_t main_thread; static sem_t interrupt_sem; static pthread_mutex_t interrupt_lock; @@ -141,71 +123,6 @@ static void _task_execute_isr(int sig) in_interrupt = 0; } -static void __attribute__((noinline)) _task_dump_trace_impl(int offset) -{ - void *trace[MAX_TRACE]; - size_t sz; - char **messages; - char buf[256]; - FILE *file; - int i, nb; - - sz = backtrace(trace, MAX_TRACE); - messages = backtrace_symbols(trace + offset, sz - offset); - - for (i = 0; i < sz - offset; ++i) { - fprintf(stderr, "#%-2d %s\n", i, messages[i]); - sprintf(buf, "addr2line %p -e %s", - trace[i + offset], __get_prog_name()); - file = popen(buf, "r"); - if (file) { - nb = fread(buf, 1, sizeof(buf) - 1, file); - buf[nb] = '\0'; - fprintf(stderr, " %s", buf); - pclose(file); - } - } - fflush(stderr); - free(messages); -} - -void __attribute__((noinline)) task_dump_trace(void) -{ - _task_dump_trace_impl(DIRECT_TRACE_OFFSET); -} - -static void __attribute__((noinline)) _task_dump_trace_dispatch(int sig) -{ - int need_dispatch = 1; - - if (!pthread_equal(pthread_self(), main_thread)) { - need_dispatch = 0; - } else if (!task_start_called()) { - fprintf(stderr, "Stack trace of main thread:\n"); - need_dispatch = 0; - } else if (in_interrupt_context()) { - fprintf(stderr, "Stack trace of ISR:\n"); - } else { - fprintf(stderr, "Stack trace of task %d (%s):\n", - running_task_id, task_names[running_task_id]); - } - - if (need_dispatch) { - pthread_kill(tasks[running_task_id].thread, SIGNAL_TRACE_DUMP); - } else { - _task_dump_trace_impl(SIGNAL_TRACE_OFFSET); - udelay(100 * MSEC); /* Leave time for stderr to flush */ - exit(1); - } -} - -void task_register_tracedump(void) -{ - /* Trace dumper MUST be registered from main thread */ - main_thread = pthread_self(); - signal(SIGNAL_TRACE_DUMP, _task_dump_trace_dispatch); -} - static void task_register_interrupt(void) { sem_init(&interrupt_sem, 0, 0); @@ -242,6 +159,16 @@ void interrupt_generator_udelay(unsigned us) generator_sleeping = 0; } +const char *task_get_name(task_id_t tskid) +{ + return task_names[tskid]; +} + +pthread_t task_get_thread(task_id_t tskid) +{ + return tasks[tskid].thread; +} + uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) { tasks[tskid].event = event; @@ -307,6 +234,11 @@ task_id_t task_get_current(void) return my_task_id; } +task_id_t task_get_running(void) +{ + return running_task_id; +} + void wait_for_task_started(void) { int i, ok; diff --git a/include/stack_trace.h b/include/stack_trace.h new file mode 100644 index 0000000000..e8b37d1811 --- /dev/null +++ b/include/stack_trace.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trace dump module */ + +#ifndef __CROS_EC_TRACE_H +#define __CROS_EC_TRACE_H + +#ifdef EMU_BUILD +/* + * Register trace dump handler for emulator. Trace dump is printed to stderr + * when SIGUSR2 is received. + */ +void task_register_tracedump(void); + +/* Dump current stack trace */ +void task_dump_trace(void); +#else +static inline void task_register_tracedump(void) { } +static inline void task_dump_trace(void) { } +#endif + +#endif /* __CROS_EC_TRACE_H */ diff --git a/include/task.h b/include/task.h index 1aeb1206b7..f2df173501 100644 --- a/include/task.h +++ b/include/task.h @@ -105,6 +105,11 @@ uint32_t task_wait_event(int timeout_us); */ void task_print_list(void); +/** + * Returns the name of the task. + */ +const char *task_get_name(task_id_t tskid); + #ifdef CONFIG_TASK_PROFILING /** * Start tracking an interrupt. diff --git a/include/test_util.h b/include/test_util.h index 754230489f..4f76a200c4 100644 --- a/include/test_util.h +++ b/include/test_util.h @@ -10,6 +10,7 @@ #include "common.h" #include "console.h" +#include "stack_trace.h" #define RUN_TEST(n) \ do { \ @@ -130,19 +131,8 @@ void interrupt_generator_udelay(unsigned us); #ifdef EMU_BUILD void wait_for_task_started(void); - -/* - * Register trace dump handler for emulator. Trace dump is printed to stderr - * when SIGUSR2 is received. - */ -void task_register_tracedump(void); - -/* Dump current stack trace */ -void task_dump_trace(void); #else static inline void wait_for_task_started(void) { } -static inline void task_register_tracedump(void) { } -static inline void task_dump_trace(void) { } #endif uint32_t prng(uint32_t seed); diff --git a/test/interrupt.c b/test/interrupt.c index b7a42d1588..ae8ce66b58 100644 --- a/test/interrupt.c +++ b/test/interrupt.c @@ -8,8 +8,8 @@ #include "common.h" #include "console.h" -#include "test_util.h" #include "task.h" +#include "test_util.h" #include "timer.h" #include "util.h" |