mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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
98 lines
2.3 KiB
C
98 lines
2.3 KiB
C
/* 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);
|
|
}
|