Files
OpenCellular/core/host/stack_trace.c
Vic Yang 7bbf6d7bb3 Slow down time when running unit tests
When a timing sensitive test run on a heavily loaded system, sometimes a
task runs for longer than it usually does and causes the test to fail.
All the timing requirements in the unit tests are trying to verify the
various delays in our codebase, and mostly we don't care about the time
taken by active running code (as they are very quick.) To improve the
stability of tests, let's slow down the time. To a test, it's as if the
code runs faster. If a test uses udelay() and exceeds the 10-second time
limit, we can make that single test faster by setting the time scale.

BUG=None
TEST=Repeatedly run 'make runtests'
BRANCH=None

Change-Id: I9bc5c77e0d34d04c8630d495387a751ef29c7bd5
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/220717
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2014-10-04 21:08:38 +00:00

97 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);
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);
}