Add atomic_t underrun to struct cpu_trace.
Increment it only when trace_freerunning is set and an older trace
entry is overwritten.
Modify copy_trace() to reorder entries, if underrun != 0.
Signed-off-by: Karsten Wiese <[email protected]>
--- rt6-kw/kernel/latency_trace-tk2.1.c 2006-12-06 14:43:52.000000000 +0100
+++ rt6-kw/kernel/latency_trace.c 2006-12-06 14:58:44.000000000 +0100
@@ -228,6 +228,7 @@ struct cpu_trace {
cycle_t preempt_timestamp;
unsigned long critical_start, critical_end;
unsigned long critical_sequence;
+ atomic_t underrun;
atomic_t overrun;
int early_warning;
int latency_type;
@@ -606,16 +607,21 @@ again:
idx_next = idx + 1;
timestamp = now();
- if (unlikely((trace_freerunning || print_functions) &&
- (idx_next >= MAX_TRACE)))
+ if (unlikely((trace_freerunning || print_functions || atomic_read(&tr->underrun)) &&
+ (idx_next >= MAX_TRACE) && !atomic_read(&tr->overrun))) {
+ atomic_inc(&tr->underrun);
idx_next = 0;
+ }
if (unlikely(idx >= MAX_TRACE)) {
atomic_inc(&tr->overrun);
goto out;
}
#ifdef __HAVE_ARCH_CMPXCHG
- if (unlikely(cmpxchg(&tr->trace_idx, idx, idx_next) != idx))
+ if (unlikely(cmpxchg(&tr->trace_idx, idx, idx_next) != idx)) {
+ if (idx_next == 0)
+ atomic_dec(&tr->underrun);
goto again;
+ }
#else
# ifdef CONFIG_SMP
# error CMPXCHG missing
@@ -626,6 +632,9 @@ again:
tr->trace_idx = idx_next;
# endif
#endif
+ if (unlikely(idx_next != 0 && atomic_read(&tr->underrun)))
+ atomic_inc(&tr->underrun);
+
pc = preempt_count();
if (unlikely(!tr->trace))
@@ -938,13 +947,12 @@ char *pid_to_cmdline(unsigned long pid)
return cmdline;
}
-static void copy_trace(struct cpu_trace *save, struct cpu_trace *tr)
+static void copy_trace(struct cpu_trace *save, struct cpu_trace *tr, int reorder)
{
if (!save->trace || !tr->trace)
return;
/* free-running needs reordering */
- /* FIXME: what if we just switched back from freerunning mode? */
- if (trace_freerunning) {
+ if (reorder && atomic_read(&tr->underrun)) {
int i, idx, idx0 = tr->trace_idx;
for (i = 0; i < MAX_TRACE; i++) {
@@ -959,6 +967,7 @@ static void copy_trace(struct cpu_trace
min(save->trace_idx, MAX_TRACE) *
sizeof(struct trace_entry));
}
+ save->underrun = tr->underrun;
save->overrun = tr->overrun;
}
@@ -1010,7 +1019,7 @@ static void update_out_trace(void)
cycle_t stamp, first_stamp, last_stamp;
struct block_idx bidx = { { 0, }, };
struct cpu_trace *tmp_max, *tmp_out;
- int cpu, sum, entries, overrun_sum;
+ int cpu, sum, entries, underrun_sum, overrun_sum;
/*
* For out_tr we only have the first array's trace entries
@@ -1023,7 +1032,7 @@ static void update_out_trace(void)
* Easier to copy this way. Note: the trace buffer is private
* to the output buffer, so preserve it:
*/
- copy_trace(tmp_out, tmp_max);
+ copy_trace(tmp_out, tmp_max, 0);
tmp = tmp_out->trace;
*tmp_out = *tmp_max;
tmp_out->trace = tmp;
@@ -1134,12 +1143,15 @@ static void update_out_trace(void)
}
sum = 0;
+ underrun_sum = 0;
overrun_sum = 0;
for_each_online_cpu(cpu) {
sum += max_tr.traces[cpu].trace_idx;
+ underrun_sum += atomic_read(&max_tr.traces[cpu].underrun);
overrun_sum += atomic_read(&max_tr.traces[cpu].overrun);
}
tmp_out->trace_idx = sum;
+ atomic_set(&tmp_out->underrun, underrun_sum);
atomic_set(&tmp_out->overrun, overrun_sum);
}
@@ -1186,7 +1198,7 @@ static void * notrace l_start(struct seq
seq_puts(m, "--------------------------------------------------------------------\n");
seq_printf(m, " latency: %lu us, #%lu/%lu, CPU#%d | (M:%s VP:%d, KP:%d, SP:%d HP:%d",
cycles_to_usecs(tr->saved_latency),
- entries, entries + atomic_read(&tr->overrun),
+ entries, entries + atomic_read(&tr->underrun) + atomic_read(&tr->overrun),
out_tr.cpu,
#if defined(CONFIG_PREEMPT_NONE)
"server",
@@ -1629,11 +1641,11 @@ static void update_max_tr(struct cpu_tra
if (all_cpus) {
for_each_online_cpu(cpu) {
- copy_trace(max_tr.traces + cpu, cpu_traces + cpu);
+ copy_trace(max_tr.traces + cpu, cpu_traces + cpu, 1);
atomic_dec(&cpu_traces[cpu].disabled);
}
} else
- copy_trace(save, tr);
+ copy_trace(save, tr, 1);
}
#else /* !EVENT_TRACE */
@@ -1830,6 +1842,7 @@ __start_critical_timing(unsigned long ei
tr->critical_sequence = max_sequence;
tr->preempt_timestamp = get_monotonic_cycles();
tr->critical_start = eip;
+ atomic_set(&tr->underrun, 0);
atomic_set(&tr->overrun, 0);
reset_trace_idx(cpu, tr);
tr->latency_type = latency_type;
@@ -2208,6 +2221,7 @@ void __trace_start_sched_wakeup(struct t
tr->preempt_timestamp = get_monotonic_cycles();
tr->latency_type = WAKEUP_LATENCY;
tr->critical_start = CALLER_ADDR0;
+ atomic_set(&tr->underrun, 0);
atomic_set(&tr->overrun, 0);
_trace_cmdline(raw_smp_processor_id(), tr);
atomic_dec(&tr->disabled);
@@ -2318,6 +2332,7 @@ long user_trace_start(void)
tr->critical_sequence = max_sequence;
tr->preempt_timestamp = get_monotonic_cycles();
tr->critical_start = CALLER_ADDR0;
+ atomic_set(&tr->underrun, 0);
atomic_set(&tr->overrun, 0);
_trace_cmdline(cpu, tr);
mcount();
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]