[PATCH -rt 2/3] Make trace_freerunning work; Take 2: Add atomic_t underrun

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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]
  Powered by Linux