diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-04-30 20:49:44 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-05-05 14:25:44 -0400 |
commit | e4906eff9e6fbd2d311abcbcc53d5a531773c982 (patch) | |
tree | 05dd56b9336e7059cca3b651d542cc4b8bc2220b /kernel/trace/ring_buffer.c | |
parent | c8d771835e18c938dae8690611d65fe98ad30f58 (diff) |
ring-buffer: convert cpu buffer entries to local_t
The entries counter in cpu buffer is not atomic. It can be updated by
other interrupts or from another CPU (readers).
But making entries into "atomic_t" causes an atomic operation that can
hurt performance. Instead we convert it to a local_t that will increment
a counter with a local CPU atomic operation (if the arch supports it).
Instead of fighting with readers and overwrites that decrement the counter,
I added a "read" counter. Every time a reader reads an entry it is
incremented.
We already have a overrun counter and with that, the entries counter and
the read counter, we can calculate the total number of entries in the
buffer with:
(entries - overrun) - read
As long as the total number of entries in the ring buffer is less than
the word size, this will work. But since the entries counter was previously
a long, this is no different than what we had before.
Thanks to Andrew Morton for pointing out in the first version that
atomic_t does not replace unsigned long. I switched to atomic_long_t
even though it is signed. A negative count is most likely a bug.
[ Impact: keep accurate count of cpu buffer entries ]
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ring_buffer.c')
-rw-r--r-- | kernel/trace/ring_buffer.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 26e1359fe193..c792ea893b01 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -405,7 +405,8 @@ struct ring_buffer_per_cpu { | |||
405 | unsigned long nmi_dropped; | 405 | unsigned long nmi_dropped; |
406 | unsigned long commit_overrun; | 406 | unsigned long commit_overrun; |
407 | unsigned long overrun; | 407 | unsigned long overrun; |
408 | unsigned long entries; | 408 | unsigned long read; |
409 | local_t entries; | ||
409 | u64 write_stamp; | 410 | u64 write_stamp; |
410 | u64 read_stamp; | 411 | u64 read_stamp; |
411 | atomic_t record_disabled; | 412 | atomic_t record_disabled; |
@@ -997,7 +998,6 @@ static void rb_update_overflow(struct ring_buffer_per_cpu *cpu_buffer) | |||
997 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) | 998 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
998 | continue; | 999 | continue; |
999 | cpu_buffer->overrun++; | 1000 | cpu_buffer->overrun++; |
1000 | cpu_buffer->entries--; | ||
1001 | } | 1001 | } |
1002 | } | 1002 | } |
1003 | 1003 | ||
@@ -1588,7 +1588,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_lock_reserve); | |||
1588 | static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer, | 1588 | static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer, |
1589 | struct ring_buffer_event *event) | 1589 | struct ring_buffer_event *event) |
1590 | { | 1590 | { |
1591 | cpu_buffer->entries++; | 1591 | local_inc(&cpu_buffer->entries); |
1592 | 1592 | ||
1593 | /* Only process further if we own the commit */ | 1593 | /* Only process further if we own the commit */ |
1594 | if (!rb_is_commit(cpu_buffer, event)) | 1594 | if (!rb_is_commit(cpu_buffer, event)) |
@@ -1722,7 +1722,7 @@ void ring_buffer_discard_commit(struct ring_buffer *buffer, | |||
1722 | * The commit is still visible by the reader, so we | 1722 | * The commit is still visible by the reader, so we |
1723 | * must increment entries. | 1723 | * must increment entries. |
1724 | */ | 1724 | */ |
1725 | cpu_buffer->entries++; | 1725 | local_inc(&cpu_buffer->entries); |
1726 | out: | 1726 | out: |
1727 | /* | 1727 | /* |
1728 | * If a write came in and pushed the tail page | 1728 | * If a write came in and pushed the tail page |
@@ -1902,7 +1902,8 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu) | |||
1902 | return 0; | 1902 | return 0; |
1903 | 1903 | ||
1904 | cpu_buffer = buffer->buffers[cpu]; | 1904 | cpu_buffer = buffer->buffers[cpu]; |
1905 | ret = cpu_buffer->entries; | 1905 | ret = (local_read(&cpu_buffer->entries) - cpu_buffer->overrun) |
1906 | - cpu_buffer->read; | ||
1906 | 1907 | ||
1907 | return ret; | 1908 | return ret; |
1908 | } | 1909 | } |
@@ -1985,7 +1986,8 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer) | |||
1985 | /* if you care about this being correct, lock the buffer */ | 1986 | /* if you care about this being correct, lock the buffer */ |
1986 | for_each_buffer_cpu(buffer, cpu) { | 1987 | for_each_buffer_cpu(buffer, cpu) { |
1987 | cpu_buffer = buffer->buffers[cpu]; | 1988 | cpu_buffer = buffer->buffers[cpu]; |
1988 | entries += cpu_buffer->entries; | 1989 | entries += (local_read(&cpu_buffer->entries) - |
1990 | cpu_buffer->overrun) - cpu_buffer->read; | ||
1989 | } | 1991 | } |
1990 | 1992 | ||
1991 | return entries; | 1993 | return entries; |
@@ -2225,7 +2227,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) | |||
2225 | 2227 | ||
2226 | if (event->type_len <= RINGBUF_TYPE_DATA_TYPE_LEN_MAX | 2228 | if (event->type_len <= RINGBUF_TYPE_DATA_TYPE_LEN_MAX |
2227 | || rb_discarded_event(event)) | 2229 | || rb_discarded_event(event)) |
2228 | cpu_buffer->entries--; | 2230 | cpu_buffer->read++; |
2229 | 2231 | ||
2230 | rb_update_read_stamp(cpu_buffer, event); | 2232 | rb_update_read_stamp(cpu_buffer, event); |
2231 | 2233 | ||
@@ -2642,7 +2644,8 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) | |||
2642 | cpu_buffer->nmi_dropped = 0; | 2644 | cpu_buffer->nmi_dropped = 0; |
2643 | cpu_buffer->commit_overrun = 0; | 2645 | cpu_buffer->commit_overrun = 0; |
2644 | cpu_buffer->overrun = 0; | 2646 | cpu_buffer->overrun = 0; |
2645 | cpu_buffer->entries = 0; | 2647 | cpu_buffer->read = 0; |
2648 | local_set(&cpu_buffer->entries, 0); | ||
2646 | 2649 | ||
2647 | cpu_buffer->write_stamp = 0; | 2650 | cpu_buffer->write_stamp = 0; |
2648 | cpu_buffer->read_stamp = 0; | 2651 | cpu_buffer->read_stamp = 0; |
@@ -2813,7 +2816,7 @@ static void rb_remove_entries(struct ring_buffer_per_cpu *cpu_buffer, | |||
2813 | /* Only count data entries */ | 2816 | /* Only count data entries */ |
2814 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) | 2817 | if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
2815 | continue; | 2818 | continue; |
2816 | cpu_buffer->entries--; | 2819 | cpu_buffer->read++; |
2817 | } | 2820 | } |
2818 | __raw_spin_unlock(&cpu_buffer->lock); | 2821 | __raw_spin_unlock(&cpu_buffer->lock); |
2819 | } | 2822 | } |