diff options
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r-- | kernel/perf_counter.c | 42 |
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 | ||
1669 | static 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 | |||
1668 | static int perf_output_begin(struct perf_output_handle *handle, | 1677 | static 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 | ||
1707 | fail: | ||
1708 | __perf_output_wakeup(handle); | ||
1695 | out: | 1709 | out: |
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 | ||
1736 | static void perf_output_end(struct perf_output_handle *handle, int nmi) | 1750 | static 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 | ||
1760 | out: | 1770 | out: |
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 | ||
1830 | void perf_counter_output(struct perf_counter *counter, | 1840 | void 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 | ||
1883 | static int perf_counter_mmap_match(struct perf_counter *counter, | 1893 | static int perf_counter_mmap_match(struct perf_counter *counter, |