aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_counter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r--kernel/perf_counter.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index d07b45278b4f..4471e7e2c109 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1663,10 +1663,20 @@ struct perf_output_handle {
1663 unsigned int offset; 1663 unsigned int offset;
1664 unsigned int head; 1664 unsigned int head;
1665 int wakeup; 1665 int wakeup;
1666 int nmi;
1666}; 1667};
1667 1668
1669static inline void __perf_output_wakeup(struct perf_output_handle *handle)
1670{
1671 if (handle->nmi)
1672 perf_pending_queue(handle->counter);
1673 else
1674 perf_counter_wakeup(handle->counter);
1675}
1676
1668static int perf_output_begin(struct perf_output_handle *handle, 1677static int perf_output_begin(struct perf_output_handle *handle,
1669 struct perf_counter *counter, unsigned int size) 1678 struct perf_counter *counter, unsigned int size,
1679 int nmi)
1670{ 1680{
1671 struct perf_mmap_data *data; 1681 struct perf_mmap_data *data;
1672 unsigned int offset, head; 1682 unsigned int offset, head;
@@ -1676,15 +1686,17 @@ static int perf_output_begin(struct perf_output_handle *handle,
1676 if (!data) 1686 if (!data)
1677 goto out; 1687 goto out;
1678 1688
1689 handle->counter = counter;
1690 handle->nmi = nmi;
1691
1679 if (!data->nr_pages) 1692 if (!data->nr_pages)
1680 goto out; 1693 goto fail;
1681 1694
1682 do { 1695 do {
1683 offset = head = atomic_read(&data->head); 1696 offset = head = atomic_read(&data->head);
1684 head += size; 1697 head += size;
1685 } while (atomic_cmpxchg(&data->head, offset, head) != offset); 1698 } while (atomic_cmpxchg(&data->head, offset, head) != offset);
1686 1699
1687 handle->counter = counter;
1688 handle->data = data; 1700 handle->data = data;
1689 handle->offset = offset; 1701 handle->offset = offset;
1690 handle->head = head; 1702 handle->head = head;
@@ -1692,6 +1704,8 @@ static int perf_output_begin(struct perf_output_handle *handle,
1692 1704
1693 return 0; 1705 return 0;
1694 1706
1707fail:
1708 __perf_output_wakeup(handle);
1695out: 1709out:
1696 rcu_read_unlock(); 1710 rcu_read_unlock();
1697 1711
@@ -1733,14 +1747,10 @@ static void perf_output_copy(struct perf_output_handle *handle,
1733#define perf_output_put(handle, x) \ 1747#define perf_output_put(handle, x) \
1734 perf_output_copy((handle), &(x), sizeof(x)) 1748 perf_output_copy((handle), &(x), sizeof(x))
1735 1749
1736static void perf_output_end(struct perf_output_handle *handle, int nmi) 1750static void perf_output_end(struct perf_output_handle *handle)
1737{ 1751{
1738 if (handle->wakeup) { 1752 if (handle->wakeup)
1739 if (nmi) 1753 __perf_output_wakeup(handle);
1740 perf_pending_queue(handle->counter);
1741 else
1742 perf_counter_wakeup(handle->counter);
1743 }
1744 rcu_read_unlock(); 1754 rcu_read_unlock();
1745} 1755}
1746 1756
@@ -1750,12 +1760,12 @@ static int perf_output_write(struct perf_counter *counter, int nmi,
1750 struct perf_output_handle handle; 1760 struct perf_output_handle handle;
1751 int ret; 1761 int ret;
1752 1762
1753 ret = perf_output_begin(&handle, counter, size); 1763 ret = perf_output_begin(&handle, counter, size, nmi);
1754 if (ret) 1764 if (ret)
1755 goto out; 1765 goto out;
1756 1766
1757 perf_output_copy(&handle, buf, size); 1767 perf_output_copy(&handle, buf, size);
1758 perf_output_end(&handle, nmi); 1768 perf_output_end(&handle);
1759 1769
1760out: 1770out:
1761 return ret; 1771 return ret;
@@ -1804,7 +1814,7 @@ static void perf_output_group(struct perf_counter *counter, int nmi)
1804 1814
1805 size = sizeof(header) + counter->nr_siblings * sizeof(entry); 1815 size = sizeof(header) + counter->nr_siblings * sizeof(entry);
1806 1816
1807 ret = perf_output_begin(&handle, counter, size); 1817 ret = perf_output_begin(&handle, counter, size, nmi);
1808 if (ret) 1818 if (ret)
1809 return; 1819 return;
1810 1820
@@ -1824,7 +1834,7 @@ static void perf_output_group(struct perf_counter *counter, int nmi)
1824 perf_output_put(&handle, entry); 1834 perf_output_put(&handle, entry);
1825 } 1835 }
1826 1836
1827 perf_output_end(&handle, nmi); 1837 perf_output_end(&handle);
1828} 1838}
1829 1839
1830void perf_counter_output(struct perf_counter *counter, 1840void perf_counter_output(struct perf_counter *counter,
@@ -1869,7 +1879,7 @@ static void perf_counter_mmap_output(struct perf_counter *counter,
1869{ 1879{
1870 struct perf_output_handle handle; 1880 struct perf_output_handle handle;
1871 int size = mmap_event->event.header.size; 1881 int size = mmap_event->event.header.size;
1872 int ret = perf_output_begin(&handle, counter, size); 1882 int ret = perf_output_begin(&handle, counter, size, 0);
1873 1883
1874 if (ret) 1884 if (ret)
1875 return; 1885 return;
@@ -1877,7 +1887,7 @@ static void perf_counter_mmap_output(struct perf_counter *counter,
1877 perf_output_put(&handle, mmap_event->event); 1887 perf_output_put(&handle, mmap_event->event);
1878 perf_output_copy(&handle, mmap_event->file_name, 1888 perf_output_copy(&handle, mmap_event->file_name,
1879 mmap_event->file_size); 1889 mmap_event->file_size);
1880 perf_output_end(&handle, 0); 1890 perf_output_end(&handle);
1881} 1891}
1882 1892
1883static int perf_counter_mmap_match(struct perf_counter *counter, 1893static int perf_counter_mmap_match(struct perf_counter *counter,