From e7d37725db662ded51a3ff20ddb6874b0d054935 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 20 May 2010 16:46:39 +0200 Subject: [PATCH] --- yaml --- r: 199125 b: refs/heads/master c: 5d967a8be636a4f301a8daad642bd1007299d9ec h: refs/heads/master i: 199123: 86d695aa097f4e9f1566a7e9e25df5fee207a2a7 v: v3 --- [refs] | 2 +- trunk/include/linux/perf_event.h | 3 ++ trunk/kernel/perf_event.c | 54 +++++++++++++++----------------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/[refs] b/[refs] index 83b26a6ff22f..72c818420a42 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: adb8e118f288dc4c569ac9a89010b81a4745fbf0 +refs/heads/master: 5d967a8be636a4f301a8daad642bd1007299d9ec diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 7098ebbb3b3a..7bd17f0488f8 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -806,6 +806,9 @@ struct perf_output_handle { unsigned long head; unsigned long offset; unsigned long wakeup; + unsigned long size; + void *addr; + int page; int nmi; int sample; }; diff --git a/trunk/kernel/perf_event.c b/trunk/kernel/perf_event.c index 1531e0b409a5..b67549a08626 100644 --- a/trunk/kernel/perf_event.c +++ b/trunk/kernel/perf_event.c @@ -2961,39 +2961,30 @@ static void perf_output_put_handle(struct perf_output_handle *handle) void perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len) { - unsigned int pages_mask; - unsigned long offset; - unsigned int size; - void **pages; - - offset = handle->offset; - pages_mask = handle->data->nr_pages - 1; - pages = handle->data->data_pages; - - do { - unsigned long page_offset; - unsigned long page_size; - int nr; - - nr = (offset >> PAGE_SHIFT) & pages_mask; - page_size = 1UL << (handle->data->data_order + PAGE_SHIFT); - page_offset = offset & (page_size - 1); - size = min_t(unsigned int, page_size - page_offset, len); - - memcpy(pages[nr] + page_offset, buf, size); - - len -= size; - buf += size; - offset += size; - } while (len); - - handle->offset = offset; + handle->offset += len; /* * Check we didn't copy past our reservation window, taking the * possible unsigned int wrap into account. */ - WARN_ON_ONCE(((long)(handle->head - handle->offset)) < 0); + if (WARN_ON_ONCE(((long)(handle->head - handle->offset)) < 0)) + return; + + do { + unsigned long size = min(handle->size, len); + + memcpy(handle->addr, buf, size); + + len -= size; + handle->addr += size; + handle->size -= size; + if (!handle->size) { + handle->page++; + handle->page &= handle->data->nr_pages - 1; + handle->addr = handle->data->data_pages[handle->page]; + handle->size = PAGE_SIZE << handle->data->data_order; + } + } while (len); } int perf_output_begin(struct perf_output_handle *handle, @@ -3059,6 +3050,13 @@ int perf_output_begin(struct perf_output_handle *handle, if (head - local_read(&data->wakeup) > data->watermark) local_add(data->watermark, &data->wakeup); + handle->page = handle->offset >> (PAGE_SHIFT + data->data_order); + handle->page &= data->nr_pages - 1; + handle->size = handle->offset & ((PAGE_SIZE << data->data_order) - 1); + handle->addr = data->data_pages[handle->page]; + handle->addr += handle->size; + handle->size = (PAGE_SIZE << data->data_order) - handle->size; + if (have_lost) { lost_event.header.type = PERF_RECORD_LOST; lost_event.header.misc = 0;