mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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
This commit is contained in:
committed by
chrome-internal-fetch
parent
a02d7fa148
commit
7c686dd68b
@@ -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
|
||||
|
||||
26
core/host/host_task.h
Normal file
26
core/host/host_task.h
Normal file
@@ -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 */
|
||||
@@ -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"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "panic.h"
|
||||
#include "stack_trace.h"
|
||||
#include "test_util.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
97
core/host/stack_trace.c
Normal file
97
core/host/stack_trace.c
Normal file
@@ -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);
|
||||
}
|
||||
100
core/host/task.c
100
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;
|
||||
|
||||
25
include/stack_trace.h
Normal file
25
include/stack_trace.h
Normal file
@@ -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 */
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user