From c960ebd52fee06becf1b943a4a4eeae566a35a81 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Sat, 24 Apr 2010 10:49:18 -0400 Subject: [PATCH] Use the SET_OUTPUT ioctl to direct all output to the same buffer This ensures that we don't get events out of order, which will make the profiles look a lot less bogus on multi-core systems. --- collector.c | 82 +++++++++++++++++++++++++++++++++++++--------------------- perf_counter.h | 1 + 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/collector.c b/collector.c index 2bba702..86d96ed 100644 --- a/collector.c +++ b/collector.c @@ -379,9 +379,30 @@ map_buffer (counter_t *counter, GError **err) return address; } +static gboolean +counter_set_output (counter_t *counter, int output) +{ + return ioctl (counter->fd, PERF_COUNTER_IOC_SET_OUTPUT, output) == 0; +} + +static void +counter_enable (counter_t *counter) +{ + ioctl (counter->fd, PERF_COUNTER_IOC_ENABLE); +} + +static void +counter_disable (counter_t *counter) +{ + d_print ("disable\n"); + + ioctl (counter->fd, PERF_COUNTER_IOC_DISABLE); +} + static counter_t * counter_new (Collector *collector, int cpu, + counter_t *output, GError **err) { struct perf_counter_attr attr; @@ -417,41 +438,36 @@ counter_new (Collector *collector, if (fd < 0) return fail (err, "Could not open performance counter"); - + counter->collector = collector; counter->fd = fd; - - counter->mmap_page = map_buffer (counter, err); - - if (!counter->mmap_page || counter->mmap_page == MAP_FAILED) - return NULL; - - counter->data = (uint8_t *)counter->mmap_page + get_page_size (); - counter->tail = 0; counter->cpu = cpu; - - fd_add_watch (fd, counter); - fd_set_read_callback (fd, on_read); + if (output && counter_set_output (counter, output->fd)) + { + counter->mmap_page = NULL; + counter->data = NULL; + counter->tail = 0; + } + else + { + counter->mmap_page = map_buffer (counter, err); + + if (!counter->mmap_page || counter->mmap_page == MAP_FAILED) + return NULL; + + counter->data = (uint8_t *)counter->mmap_page + get_page_size (); + counter->tail = 0; + + fd_add_watch (fd, counter); + + fd_set_read_callback (fd, on_read); + } return counter; } static void -counter_enable (counter_t *counter) -{ - ioctl (counter->fd, PERF_COUNTER_IOC_ENABLE); -} - -static void -counter_disable (counter_t *counter) -{ - d_print ("disable\n"); - - ioctl (counter->fd, PERF_COUNTER_IOC_DISABLE); -} - -static void counter_free (counter_t *counter) { d_print ("munmap\n"); @@ -705,13 +721,15 @@ collector_start (Collector *collector, { int n_cpus = get_n_cpus (); int i; + counter_t *output; if (!collector->tracker) collector->tracker = tracker_new (); - + + output = NULL; for (i = 0; i < n_cpus; ++i) { - counter_t *counter = counter_new (collector, i, err); + counter_t *counter = counter_new (collector, i, output, err); if (!counter) { @@ -724,8 +742,11 @@ collector_start (Collector *collector, return FALSE; } - + collector->counters = g_list_append (collector->counters, counter); + + if (!output) + output = counter; } enable_counters (collector); @@ -746,7 +767,8 @@ collector_stop (Collector *collector) { counter_t *counter = list->data; - on_read (counter); + if (counter->data) + on_read (counter); counter_free (counter); } diff --git a/perf_counter.h b/perf_counter.h index 4d3ad31..a22d2cb 100644 --- a/perf_counter.h +++ b/perf_counter.h @@ -216,6 +216,7 @@ struct perf_counter_attr { #define PERF_COUNTER_IOC_REFRESH _IO ('$', 2) #define PERF_COUNTER_IOC_RESET _IO ('$', 3) #define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64) +#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5) enum perf_counter_ioc_flags { PERF_IOC_FLAG_GROUP = 1U << 0, -- 2.7.4