#include <ddb/tr.h>
#if TRACE_BUFFER
#include <string.h>
#include <ddb/db_command.h>
#include <mach_kdb.h>
#include <kern/lock.h>
#include <kern/spl.h>
extern void fc_get(int *);
#define TRACE_MAX (4 * 1024)
#define TRACE_WINDOW 40
typedef struct trace_event {
char *funcname;
char *file;
char *fmt;
#if NCPUS > 1
char cpu_number;
#endif
unsigned int lineno;
unsigned int tag1;
unsigned int tag2;
unsigned int tag3;
unsigned int tag4;
int indent;
int timestamp[2];
} trace_event;
trace_event trace_buffer[TRACE_MAX];
unsigned long trace_index;
#if NCPUS == 1
int tr_indent = 0;
#else
int tr_indent[NCPUS];
int tr_limit = -1;
#endif
decl_simple_lock_data(,trace_lock)
void
tr_init(void)
{
#if NCPUS > 1
int i;
for(i=0;i<NCPUS;i++)
tr_indent[i]=0;
#endif
simple_lock_init(&trace_lock, ETAP_DIPC_TRACE);
}
void
tr(
char *funcname,
char *file,
unsigned int lineno,
char *fmt,
unsigned int tag1,
unsigned int tag2,
unsigned int tag3,
unsigned int tag4)
{
int s;
register unsigned long ti, tn;
#if NCPUS > 1
char cpu;
#endif
#if PARAGON860
do {
ti = trace_index;
tn = ti + 1;
if (tn >= TRACE_MAX - 1)
tn = 0;
} while (cmpsw(ti, tn, &trace_index) == -1);
fc_get(trace_buffer[ti].timestamp);
#else
s = splimp();
simple_lock(&trace_lock);
ti = trace_index++;
if (trace_index >= TRACE_MAX - 1)
trace_index = 0;
simple_unlock(&trace_lock);
splx(s);
fc_get(trace_buffer[ti].timestamp);
#endif
trace_buffer[ti].funcname = funcname;
trace_buffer[ti].file = file;
trace_buffer[ti].lineno = lineno;
trace_buffer[ti].fmt = fmt;
trace_buffer[ti].tag1 = tag1;
trace_buffer[ti].tag2 = tag2;
trace_buffer[ti].tag3 = tag3;
trace_buffer[ti].tag4 = tag4;
#if NCPUS == 1
trace_buffer[ti].indent = tr_indent;
#else
mp_disable_preemption();
cpu = cpu_number();
trace_buffer[ti].indent = tr_indent[cpu];
trace_buffer[ti].cpu_number = cpu;
mp_enable_preemption();
#endif
}
#if MACH_KDB
#include <ddb/db_output.h>
void show_tr(
unsigned long index,
unsigned long range,
unsigned long show_extra);
int matches(
char *pattern,
char *target);
void parse_tr(
unsigned long index,
unsigned long range);
#define MAX_BLANKS 16
char blanks[MAX_BLANKS+4];
void
show_tr(
unsigned long index,
unsigned long range,
unsigned long show_extra)
{
char *filename, *cp;
#if PARAGON860
trace_event *last_trace;
#endif
unsigned int level;
int old_history;
int i;
if (index == -1) {
index = trace_index - (TRACE_WINDOW-4);
range = TRACE_WINDOW;
} else if (index == 0) {
index = trace_index - (TRACE_WINDOW-4);
range = TRACE_WINDOW;
show_extra = 0;
}
if (index + range > TRACE_MAX)
range = TRACE_MAX - index;
#if PARAGON860
last_trace = &trace_buffer[index-1];
#endif
level = trace_buffer[index-1].indent;
memset(blanks, ' ', trace_buffer[index].indent);
blanks[trace_buffer[index].indent] = '\0';
for (i = index; i < index + range; ++i) {
#if NCPUS > 1
if ((tr_limit != -1) &&
(trace_buffer[i].cpu_number != tr_limit))
continue;
#endif
if (trace_buffer[i].file == (char *) 0 ||
trace_buffer[i].funcname == (char *) 0 ||
trace_buffer[i].lineno == 0 ||
trace_buffer[i].fmt == 0) {
db_printf("[%04x%s]\n", i,
i >= trace_index ? "*" : "");
continue;
}
old_history = (i >= trace_index);
if (level != trace_buffer[i].indent) {
level = trace_buffer[i].indent;
if (level >= MAX_BLANKS)
level = MAX_BLANKS;
memset(blanks, ' ', level);
blanks[level] = '\0';
}
for (cp = trace_buffer[i].file; *cp; ++cp)
if (*cp == '/')
filename = cp + 1;
#if NCPUS > 1
db_printf("{%02d}",trace_buffer[i].cpu_number);
#endif
db_printf("[%04x%s] %s%-16s", i, old_history ? "*" : "",
blanks, trace_buffer[i].funcname);
if (show_extra) {
if (show_extra > 0) {
db_printf(" (%x/%8x)",
trace_buffer[i].timestamp[0],
trace_buffer[i].timestamp[1]);
#if PARAGON860
if (old_history &&
((last_trace - trace_buffer)
< trace_index))
db_printf("(N/A)");
else
db_printf("(%d)",
timer_subtime(
trace_buffer[i].timestamp,
last_trace->timestamp));
#endif
db_printf(" ");
}
if (show_extra > 1) {
db_printf("(%s:%05d):\n\t",
filename, trace_buffer[i].lineno);
}
} else
db_printf(": ");
db_printf(trace_buffer[i].fmt, trace_buffer[i].tag1,
trace_buffer[i].tag2, trace_buffer[i].tag3,
trace_buffer[i].tag4);
db_printf("\n");
#if PARAGON860
last_trace = &trace_buffer[i];
#endif
}
}
int
matches(
char *pattern,
char *target)
{
char *cp, *cp1, *cp2;
for (cp = target; *cp; ++cp) {
for (cp2 = pattern, cp1 = cp; *cp2 && *cp1; ++cp2, ++cp1)
if (*cp2 != *cp1)
break;
if (!*cp2)
return 1;
}
return 0;
}
char parse_tr_buffer[100] = "KMSG";
void
parse_tr(
unsigned long index,
unsigned long range)
{
int i;
char *filename, *cp;
char *string = parse_tr_buffer;
if (index == 0) {
index = trace_index - (TRACE_WINDOW-4);
range = TRACE_WINDOW;
}
if (index + range > TRACE_MAX)
range = TRACE_MAX - index;
for (i = index; i < index + range; ++i) {
#if NCPUS > 1
if ((tr_limit != -1) &&
(trace_buffer[i].cpu_number != tr_limit))
continue;
#endif
if (trace_buffer[i].file == (char *) 0 ||
trace_buffer[i].funcname == (char *) 0 ||
trace_buffer[i].lineno == 0 ||
trace_buffer[i].fmt == 0) {
db_printf("[%04x%s]\n", i,
i >= trace_index ? "*" : "");
continue;
}
if (!matches(string, trace_buffer[i].fmt))
continue;
for (cp = trace_buffer[i].file; *cp; ++cp)
if (*cp == '/')
filename = cp + 1;
#if NCPUS > 1
db_printf("{%02d}",trace_buffer[i].cpu_number);
#endif
db_printf("[%04x%s] %s", i, i >= trace_index ? "*" : "",
trace_buffer[i].funcname);
db_printf(": ");
db_printf(trace_buffer[i].fmt, trace_buffer[i].tag1,
trace_buffer[i].tag2, trace_buffer[i].tag3,
trace_buffer[i].tag4);
db_printf("\n");
}
}
void
db_show_tr(
db_expr_t addr,
boolean_t have_addr,
db_expr_t count,
char * modif)
{
int flag, level;
flag = 0, level = 0;
if (db_option(modif, 'l')) {
flag = 1;
level = -1;
}
if (db_option(modif, 'a')) {
flag = 2;
level = -1;
}
TR_SHOW(level, 0, flag);
}
#endif
#endif