summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic (Chun-Ju) Yang <victoryang@chromium.org>2014-01-21 17:18:33 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-01-22 04:52:49 +0000
commit7c686dd68ba382a01040f5cf23c5e416ee39e65e (patch)
treeefc0e15822d4ba10ff7520e16098b44dc8168c75
parenta02d7fa1480380ef402118395870d742b3910fd9 (diff)
downloadchrome-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
-rw-r--r--core/host/build.mk2
-rw-r--r--core/host/host_task.h26
-rw-r--r--core/host/main.c1
-rw-r--r--core/host/panic.c1
-rw-r--r--core/host/stack_trace.c97
-rw-r--r--core/host/task.c100
-rw-r--r--include/stack_trace.h25
-rw-r--r--include/task.h5
-rw-r--r--include/test_util.h12
-rw-r--r--test/interrupt.c2
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"