aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2017-03-10 09:46:05 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2017-05-26 17:12:27 -0400
commitcbe61859a233702ed8e6723b3b133d1f2ae1ae2c (patch)
treee5c20aa3f19feeb5b899bfb3302b5956d86fe526
parent4673107e2ff7c218ecac2de9eedeb61153940bbe (diff)
IRQ tracing: clarify use of per-core counters
Make it a bit more obvious what these counters are used for and how. Question for future work: can we return to using only a single per-core counter?
-rw-r--r--litmus/trace.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/litmus/trace.c b/litmus/trace.c
index 937b1c4d0975..7d698aac257d 100644
--- a/litmus/trace.c
+++ b/litmus/trace.c
@@ -16,8 +16,8 @@ static struct ftdev msg_overhead_dev;
16#define cpu_trace_ts_buf(cpu) cpu_overhead_dev.minor[(cpu)].buf 16#define cpu_trace_ts_buf(cpu) cpu_overhead_dev.minor[(cpu)].buf
17#define msg_trace_ts_buf(cpu) msg_overhead_dev.minor[(cpu)].buf 17#define msg_trace_ts_buf(cpu) msg_overhead_dev.minor[(cpu)].buf
18 18
19DEFINE_PER_CPU(atomic_t, irq_fired_count;) 19DEFINE_PER_CPU(unsigned int, local_irq_count;)
20DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, cpu_irq_fired_count); 20DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, msg_irq_count);
21 21
22static DEFINE_PER_CPU(unsigned int, cpu_ts_seq_no); 22static DEFINE_PER_CPU(unsigned int, cpu_ts_seq_no);
23static DEFINE_PER_CPU(atomic_t, msg_ts_seq_no); 23static DEFINE_PER_CPU(atomic_t, msg_ts_seq_no);
@@ -27,42 +27,28 @@ static int64_t cycle_offset[NR_CPUS][NR_CPUS];
27void ft_irq_fired(void) 27void ft_irq_fired(void)
28{ 28{
29 /* Only called with preemptions disabled. */ 29 /* Only called with preemptions disabled. */
30 atomic_inc(this_cpu_ptr(&irq_fired_count)); 30 /* local counter => not atomic, trace points disable interrupts */
31 atomic_inc(this_cpu_ptr(&cpu_irq_fired_count)); 31 this_cpu_inc(local_irq_count);
32 /* counter for messages => read remotely */
33 atomic_inc(this_cpu_ptr(&msg_irq_count));
32 34
33 if (has_control_page(current)) 35 if (has_control_page(current))
34 get_control_page(current)->irq_count++; 36 get_control_page(current)->irq_count++;
35} 37}
36 38
37static inline void clear_irq_fired(void) 39static inline unsigned int snapshot_local_irqs(void)
38{ 40{
39 atomic_set(raw_cpu_ptr(&irq_fired_count), 0); 41 return this_cpu_xchg(local_irq_count, 0);
40} 42}
41 43
42static inline unsigned int get_and_clear_irq_fired(void) 44static inline unsigned int snapshot_msg_irq_for(int cpu)
43{ 45{
44 /* This is potentially not atomic since we might migrate if 46 return atomic_xchg(&per_cpu(msg_irq_count, cpu), 0);
45 * preemptions are not disabled. As a tradeoff between
46 * accuracy and tracing overheads, this seems acceptable.
47 * If it proves to be a problem, then one could add a callback
48 * from the migration code to invalidate irq_fired_count.
49 */
50 return atomic_xchg(raw_cpu_ptr(&irq_fired_count), 0);
51}
52
53static inline unsigned int get_and_clear_irq_fired_for_cpu(int cpu)
54{
55 return atomic_xchg(&per_cpu(irq_fired_count, cpu), 0);
56}
57
58static inline void cpu_clear_irq_fired(void)
59{
60 atomic_set(raw_cpu_ptr(&cpu_irq_fired_count), 0);
61} 47}
62 48
63static inline unsigned int cpu_get_and_clear_irq_fired(void) 49static inline unsigned int snapshot_msg_irq_locally(void)
64{ 50{
65 return atomic_xchg(raw_cpu_ptr(&cpu_irq_fired_count), 0); 51 return atomic_xchg(raw_cpu_ptr(&msg_irq_count), 0);
66} 52}
67 53
68static inline void save_irq_flags(struct timestamp *ts, unsigned int irq_count) 54static inline void save_irq_flags(struct timestamp *ts, unsigned int irq_count)
@@ -141,11 +127,21 @@ static inline void __write_record(
141 127
142 ts->cpu = cpu; 128 ts->cpu = cpu;
143 129
144 if (record_irq) { 130 switch (record_irq) {
145 if (local_cpu) 131 case LOCAL_IRQ_COUNT:
146 irq_count = cpu_get_and_clear_irq_fired(); 132 if (is_cpu_timestamp)
147 else 133 irq_count = snapshot_local_irqs();
148 irq_count = get_and_clear_irq_fired_for_cpu(cpu); 134 else
135 irq_count = snapshot_msg_irq_locally();
136 break;
137 case REMOTE_IRQ_COUNT:
138 irq_count = snapshot_msg_irq_for(other_cpu);
139 break;
140 case NO_IRQ_COUNT:
141 /* fall through */
142 default:
143 /* do nothing */
144 break;
149 } 145 }
150 146
151 save_irq_flags(ts, irq_count - hide_irq); 147 save_irq_flags(ts, irq_count - hide_irq);
@@ -301,7 +297,7 @@ static void __add_timestamp_user(struct timestamp *pre_recorded)
301 *ts = *pre_recorded; 297 *ts = *pre_recorded;
302 ts->seq_no = seq_no; 298 ts->seq_no = seq_no;
303 ts->cpu = raw_smp_processor_id(); 299 ts->cpu = raw_smp_processor_id();
304 save_irq_flags(ts, get_and_clear_irq_fired()); 300 save_irq_flags(ts, snapshot_local_irqs());
305 ft_buffer_finish_write(buf, ts); 301 ft_buffer_finish_write(buf, ts);
306 } 302 }
307 303