summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <sandmann@daimi.au.dk>2010-04-24 10:49:18 -0400
committerSøren Sandmann Pedersen <sandmann@daimi.au.dk>2010-04-24 10:50:26 -0400
commitc960ebd52fee06becf1b943a4a4eeae566a35a81 (patch)
treed26eb137985d96bb2257b04e62086ade0223d1fe
parent539c3a87546f6a3baf8bd33b1633c1dc07f66496 (diff)
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.
-rw-r--r--collector.c82
-rw-r--r--perf_counter.h1
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,