diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2017-03-10 09:46:05 -0500 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2017-05-26 17:12:27 -0400 |
commit | cbe61859a233702ed8e6723b3b133d1f2ae1ae2c (patch) | |
tree | e5c20aa3f19feeb5b899bfb3302b5956d86fe526 | |
parent | 4673107e2ff7c218ecac2de9eedeb61153940bbe (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.c | 60 |
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 | ||
19 | DEFINE_PER_CPU(atomic_t, irq_fired_count;) | 19 | DEFINE_PER_CPU(unsigned int, local_irq_count;) |
20 | DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, cpu_irq_fired_count); | 20 | DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, msg_irq_count); |
21 | 21 | ||
22 | static DEFINE_PER_CPU(unsigned int, cpu_ts_seq_no); | 22 | static DEFINE_PER_CPU(unsigned int, cpu_ts_seq_no); |
23 | static DEFINE_PER_CPU(atomic_t, msg_ts_seq_no); | 23 | static DEFINE_PER_CPU(atomic_t, msg_ts_seq_no); |
@@ -27,42 +27,28 @@ static int64_t cycle_offset[NR_CPUS][NR_CPUS]; | |||
27 | void ft_irq_fired(void) | 27 | void 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 | ||
37 | static inline void clear_irq_fired(void) | 39 | static 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 | ||
42 | static inline unsigned int get_and_clear_irq_fired(void) | 44 | static 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 | |||
53 | static 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 | |||
58 | static inline void cpu_clear_irq_fired(void) | ||
59 | { | ||
60 | atomic_set(raw_cpu_ptr(&cpu_irq_fired_count), 0); | ||
61 | } | 47 | } |
62 | 48 | ||
63 | static inline unsigned int cpu_get_and_clear_irq_fired(void) | 49 | static 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 | ||
68 | static inline void save_irq_flags(struct timestamp *ts, unsigned int irq_count) | 54 | static 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 | ||