[sysprof] Use the SET_OUTPUT ioctl to direct all output to the same buffer



commit c960ebd52fee06becf1b943a4a4eeae566a35a81
Author: Søren Sandmann Pedersen <sandmann daimi au dk>
Date:   Sat Apr 24 10:49:18 2010 -0400

    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,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]