diff options
author | Vic (Chun-Ju) Yang <victoryang@chromium.org> | 2014-01-21 17:18:33 +0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-01-22 04:52:49 +0000 |
commit | 7c686dd68ba382a01040f5cf23c5e416ee39e65e (patch) | |
tree | efc0e15822d4ba10ff7520e16098b44dc8168c75 /core | |
parent | a02d7fa1480380ef402118395870d742b3910fd9 (diff) | |
download | chrome-ec-7c686dd68ba382a01040f5cf23c5e416ee39e65e.tar.gz |
emulator: Move trace dump to a separate module
The implementation of trace dump has little to do with task scheduling,
so we should move it to a separate module for cleaner code. This
requires exposing some emulator-specific task info, as defined in
host_task.h.
BUG=chrome-os-partner:19235
TEST=Pass all tests
BRANCH=None
Change-Id: Iba9bc0794a4e1dd4ddb92b98345162b398fa6a8d
Signed-off-by: Vic (Chun-Ju) Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/183238
Diffstat (limited to 'core')
-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 |
6 files changed, 142 insertions, 85 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; |