diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2008-11-11 12:47:44 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-11-11 12:47:44 -0500 |
| commit | f83c9d0fe42a7544b4d4ffcebb2e6716fcfd95c0 (patch) | |
| tree | 37532424c8ea5a8dac649cb2baed04223722c09f | |
| parent | f536aafc5a2e6f0c8f1577a155e6f93db5e469f0 (diff) | |
ring-buffer: add reader lock
Impact: serialize reader accesses to individual CPU ring buffers
The code in the ring buffer expects only one reader at a time, but currently
it puts that requirement on the caller. This is not strong enough, and this
patch adds a "reader_lock" that serializes the access to the reader API
of the ring buffer.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | kernel/trace/ring_buffer.c | 109 |
1 files changed, 78 insertions, 31 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index a6b8f9d7ac96..17c2ccebb567 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -154,6 +154,7 @@ static inline int test_time_stamp(u64 delta) | |||
| 154 | struct ring_buffer_per_cpu { | 154 | struct ring_buffer_per_cpu { |
| 155 | int cpu; | 155 | int cpu; |
| 156 | struct ring_buffer *buffer; | 156 | struct ring_buffer *buffer; |
| 157 | spinlock_t reader_lock; /* serialize readers */ | ||
| 157 | raw_spinlock_t lock; | 158 | raw_spinlock_t lock; |
| 158 | struct lock_class_key lock_key; | 159 | struct lock_class_key lock_key; |
| 159 | struct list_head pages; | 160 | struct list_head pages; |
| @@ -321,6 +322,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
| 321 | 322 | ||
| 322 | cpu_buffer->cpu = cpu; | 323 | cpu_buffer->cpu = cpu; |
| 323 | cpu_buffer->buffer = buffer; | 324 | cpu_buffer->buffer = buffer; |
| 325 | spin_lock_init(&cpu_buffer->reader_lock); | ||
| 324 | cpu_buffer->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 326 | cpu_buffer->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
| 325 | INIT_LIST_HEAD(&cpu_buffer->pages); | 327 | INIT_LIST_HEAD(&cpu_buffer->pages); |
| 326 | 328 | ||
| @@ -1476,6 +1478,9 @@ unsigned long ring_buffer_overruns(struct ring_buffer *buffer) | |||
| 1476 | void ring_buffer_iter_reset(struct ring_buffer_iter *iter) | 1478 | void ring_buffer_iter_reset(struct ring_buffer_iter *iter) |
| 1477 | { | 1479 | { |
| 1478 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; | 1480 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; |
| 1481 | unsigned long flags; | ||
| 1482 | |||
| 1483 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | ||
| 1479 | 1484 | ||
| 1480 | /* Iterator usage is expected to have record disabled */ | 1485 | /* Iterator usage is expected to have record disabled */ |
| 1481 | if (list_empty(&cpu_buffer->reader_page->list)) { | 1486 | if (list_empty(&cpu_buffer->reader_page->list)) { |
| @@ -1489,6 +1494,8 @@ void ring_buffer_iter_reset(struct ring_buffer_iter *iter) | |||
| 1489 | iter->read_stamp = cpu_buffer->read_stamp; | 1494 | iter->read_stamp = cpu_buffer->read_stamp; |
| 1490 | else | 1495 | else |
| 1491 | iter->read_stamp = iter->head_page->time_stamp; | 1496 | iter->read_stamp = iter->head_page->time_stamp; |
| 1497 | |||
| 1498 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
| 1492 | } | 1499 | } |
| 1493 | 1500 | ||
| 1494 | /** | 1501 | /** |
| @@ -1707,17 +1714,8 @@ static void rb_advance_iter(struct ring_buffer_iter *iter) | |||
| 1707 | rb_advance_iter(iter); | 1714 | rb_advance_iter(iter); |
| 1708 | } | 1715 | } |
| 1709 | 1716 | ||
| 1710 | /** | 1717 | static struct ring_buffer_event * |
| 1711 | * ring_buffer_peek - peek at the next event to be read | 1718 | rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) |
| 1712 | * @buffer: The ring buffer to read | ||
| 1713 | * @cpu: The cpu to peak at | ||
| 1714 | * @ts: The timestamp counter of this event. | ||
| 1715 | * | ||
| 1716 | * This will return the event that will be read next, but does | ||
| 1717 | * not consume the data. | ||
| 1718 | */ | ||
| 1719 | struct ring_buffer_event * | ||
| 1720 | ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | ||
| 1721 | { | 1719 | { |
| 1722 | struct ring_buffer_per_cpu *cpu_buffer; | 1720 | struct ring_buffer_per_cpu *cpu_buffer; |
| 1723 | struct ring_buffer_event *event; | 1721 | struct ring_buffer_event *event; |
| @@ -1779,16 +1777,8 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 1779 | return NULL; | 1777 | return NULL; |
| 1780 | } | 1778 | } |
| 1781 | 1779 | ||
| 1782 | /** | 1780 | static struct ring_buffer_event * |
| 1783 | * ring_buffer_iter_peek - peek at the next event to be read | 1781 | rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) |
| 1784 | * @iter: The ring buffer iterator | ||
| 1785 | * @ts: The timestamp counter of this event. | ||
| 1786 | * | ||
| 1787 | * This will return the event that will be read next, but does | ||
| 1788 | * not increment the iterator. | ||
| 1789 | */ | ||
| 1790 | struct ring_buffer_event * | ||
| 1791 | ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | ||
| 1792 | { | 1782 | { |
| 1793 | struct ring_buffer *buffer; | 1783 | struct ring_buffer *buffer; |
| 1794 | struct ring_buffer_per_cpu *cpu_buffer; | 1784 | struct ring_buffer_per_cpu *cpu_buffer; |
| @@ -1850,6 +1840,51 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 1850 | } | 1840 | } |
| 1851 | 1841 | ||
| 1852 | /** | 1842 | /** |
| 1843 | * ring_buffer_peek - peek at the next event to be read | ||
| 1844 | * @buffer: The ring buffer to read | ||
| 1845 | * @cpu: The cpu to peak at | ||
| 1846 | * @ts: The timestamp counter of this event. | ||
| 1847 | * | ||
| 1848 | * This will return the event that will be read next, but does | ||
| 1849 | * not consume the data. | ||
| 1850 | */ | ||
| 1851 | struct ring_buffer_event * | ||
| 1852 | ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | ||
| 1853 | { | ||
| 1854 | struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; | ||
| 1855 | struct ring_buffer_event *event; | ||
| 1856 | unsigned long flags; | ||
| 1857 | |||
| 1858 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | ||
| 1859 | event = rb_buffer_peek(buffer, cpu, ts); | ||
| 1860 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
| 1861 | |||
| 1862 | return event; | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | /** | ||
| 1866 | * ring_buffer_iter_peek - peek at the next event to be read | ||
| 1867 | * @iter: The ring buffer iterator | ||
| 1868 | * @ts: The timestamp counter of this event. | ||
| 1869 | * | ||
| 1870 | * This will return the event that will be read next, but does | ||
| 1871 | * not increment the iterator. | ||
| 1872 | */ | ||
| 1873 | struct ring_buffer_event * | ||
| 1874 | ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | ||
| 1875 | { | ||
| 1876 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; | ||
| 1877 | struct ring_buffer_event *event; | ||
| 1878 | unsigned long flags; | ||
| 1879 | |||
| 1880 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | ||
| 1881 | event = rb_iter_peek(iter, ts); | ||
| 1882 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
| 1883 | |||
| 1884 | return event; | ||
| 1885 | } | ||
| 1886 | |||
| 1887 | /** | ||
| 1853 | * ring_buffer_consume - return an event and consume it | 1888 | * ring_buffer_consume - return an event and consume it |
| 1854 | * @buffer: The ring buffer to get the next event from | 1889 | * @buffer: The ring buffer to get the next event from |
| 1855 | * | 1890 | * |
| @@ -1860,19 +1895,24 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 1860 | struct ring_buffer_event * | 1895 | struct ring_buffer_event * |
| 1861 | ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) | 1896 | ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) |
| 1862 | { | 1897 | { |
| 1863 | struct ring_buffer_per_cpu *cpu_buffer; | 1898 | struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; |
| 1864 | struct ring_buffer_event *event; | 1899 | struct ring_buffer_event *event; |
| 1900 | unsigned long flags; | ||
| 1865 | 1901 | ||
| 1866 | if (!cpu_isset(cpu, buffer->cpumask)) | 1902 | if (!cpu_isset(cpu, buffer->cpumask)) |
| 1867 | return NULL; | 1903 | return NULL; |
| 1868 | 1904 | ||
| 1869 | event = ring_buffer_peek(buffer, cpu, ts); | 1905 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 1906 | |||
| 1907 | event = rb_buffer_peek(buffer, cpu, ts); | ||
| 1870 | if (!event) | 1908 | if (!event) |
| 1871 | return NULL; | 1909 | goto out; |
| 1872 | 1910 | ||
| 1873 | cpu_buffer = buffer->buffers[cpu]; | ||
| 1874 | rb_advance_reader(cpu_buffer); | 1911 | rb_advance_reader(cpu_buffer); |
| 1875 | 1912 | ||
| 1913 | out: | ||
| 1914 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
| 1915 | |||
| 1876 | return event; | 1916 | return event; |
| 1877 | } | 1917 | } |
| 1878 | 1918 | ||
| @@ -1909,11 +1949,11 @@ ring_buffer_read_start(struct ring_buffer *buffer, int cpu) | |||
| 1909 | atomic_inc(&cpu_buffer->record_disabled); | 1949 | atomic_inc(&cpu_buffer->record_disabled); |
| 1910 | synchronize_sched(); | 1950 | synchronize_sched(); |
| 1911 | 1951 | ||
| 1912 | local_irq_save(flags); | 1952 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 1913 | __raw_spin_lock(&cpu_buffer->lock); | 1953 | __raw_spin_lock(&cpu_buffer->lock); |
| 1914 | ring_buffer_iter_reset(iter); | 1954 | ring_buffer_iter_reset(iter); |
| 1915 | __raw_spin_unlock(&cpu_buffer->lock); | 1955 | __raw_spin_unlock(&cpu_buffer->lock); |
| 1916 | local_irq_restore(flags); | 1956 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |
| 1917 | 1957 | ||
| 1918 | return iter; | 1958 | return iter; |
| 1919 | } | 1959 | } |
| @@ -1945,12 +1985,17 @@ struct ring_buffer_event * | |||
| 1945 | ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) | 1985 | ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts) |
| 1946 | { | 1986 | { |
| 1947 | struct ring_buffer_event *event; | 1987 | struct ring_buffer_event *event; |
| 1988 | struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; | ||
| 1989 | unsigned long flags; | ||
| 1948 | 1990 | ||
| 1949 | event = ring_buffer_iter_peek(iter, ts); | 1991 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 1992 | event = rb_iter_peek(iter, ts); | ||
| 1950 | if (!event) | 1993 | if (!event) |
| 1951 | return NULL; | 1994 | goto out; |
| 1952 | 1995 | ||
| 1953 | rb_advance_iter(iter); | 1996 | rb_advance_iter(iter); |
| 1997 | out: | ||
| 1998 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
| 1954 | 1999 | ||
| 1955 | return event; | 2000 | return event; |
| 1956 | } | 2001 | } |
| @@ -1999,13 +2044,15 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu) | |||
| 1999 | if (!cpu_isset(cpu, buffer->cpumask)) | 2044 | if (!cpu_isset(cpu, buffer->cpumask)) |
| 2000 | return; | 2045 | return; |
| 2001 | 2046 | ||
| 2002 | local_irq_save(flags); | 2047 | spin_lock_irqsave(&cpu_buffer->reader_lock, flags); |
| 2048 | |||
| 2003 | __raw_spin_lock(&cpu_buffer->lock); | 2049 | __raw_spin_lock(&cpu_buffer->lock); |
| 2004 | 2050 | ||
| 2005 | rb_reset_cpu(cpu_buffer); | 2051 | rb_reset_cpu(cpu_buffer); |
| 2006 | 2052 | ||
| 2007 | __raw_spin_unlock(&cpu_buffer->lock); | 2053 | __raw_spin_unlock(&cpu_buffer->lock); |
| 2008 | local_irq_restore(flags); | 2054 | |
| 2055 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
| 2009 | } | 2056 | } |
| 2010 | 2057 | ||
| 2011 | /** | 2058 | /** |
