[sysprof/ftrace: 2/16] Use the binary ftrace format.



commit 8556da58d8a46226ec0aa00ec672103f61a6da52
Author: Soren Sandmann Pedersen <sandmann daimi au dk>
Date:   Sat May 10 21:04:56 2008 +0000

    Use the binary ftrace format.

 collector.c |  120 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 103 insertions(+), 17 deletions(-)
---
diff --git a/collector.c b/collector.c
index 37e4a5d..8f4b28f 100644
--- a/collector.c
+++ b/collector.c
@@ -338,10 +338,100 @@ typedef struct Entry
     glong location;
 } Entry;
 
-static char *
-parse_line (char *line, Entry *entry)
+static int
+read4 (const guchar *line)
+{
+    return (line[0] << 0) | (line[1] << 8) | (line[2] << 16) | (line[3] << 24);
+}
+
+static guint64
+read8 (const guchar *line)
+{
+    guint64 rl, rh;
+
+    rl = read4 (line);
+    rh = read4 (line);
+
+    return (rh << 32) | rl;
+}
+
+/* Format of a trace entry:
+ *
+ *
+ *  pid			4 bytes
+ *  cpu			1 byte
+ *  t			8 bytes
+ *  arg1 (type)		4 bytes on 32 bit, 8 bytes on 64
+ *  arg2 (address)	4 bytes on 32 bit, 8 bytes on 64
+ *  arg3 (location)	4 bytes on 32 bit, 8 bytes on 64
+ *
+ *  TOTAL: 25 bytes on x86
+ */
+static const guchar *
+parse_line (const guchar *line, int len, Entry *entry)
 {
     char *eol;
+
+    if (len >= 25)
+    {
+	int i;
+
+#if 0
+	g_print ("%p: \n", line);
+	for (i = 0; i < 25; ++i)
+	{
+	    g_print ("%2x ", (unsigned char)line[i]);
+	}
+	g_print ("\n");
+#endif
+	
+	entry->pid = read4 (line + 0);
+	entry->cpu = *(line + 4);
+	entry->timestamp = read8 (line + 5);
+	entry->type = read4 (line + 13);
+	entry->address = read4 (line + 17);
+	entry->location = read4 (line + 21);
+
+#if 0
+	g_print ("Entry:\n");
+	g_print ("- pid: %d (%x)\n", entry->pid, entry->pid);
+	g_print ("- cpu: %d\n", entry->cpu);
+	g_print ("- timestamp: %lld\n", entry->timestamp);
+	g_print ("- type: %ld\n", entry->type);
+	g_print ("- address: %ld\n", entry->address);
+	g_print ("- location: %ld\n", entry->location);
+#endif
+
+	if (entry->type < -1 || entry->type > 3 || entry->pid < 0)
+	{
+	    g_printerr ("bad entry: %d\n", entry->type);
+	    g_printerr ("Entry:\n");
+	    g_printerr ("- pid: %d (%x)\n", entry->pid, entry->pid);
+	    g_printerr ("- cpu: %d\n", entry->cpu);
+	    g_printerr ("- timestamp: %lld\n", entry->timestamp);
+	    g_printerr ("- type: %ld\n", entry->type);
+	    g_printerr ("- address: %ld\n", entry->address);
+	    g_printerr ("- location: %ld\n", entry->location);
+	    g_printerr ("%p: \n", line);
+	    for (i = 0; i < 25; ++i)
+	    {
+		g_printerr ("%2x ", (unsigned char)line[i]);
+	    }
+	    g_printerr ("\n");
+	    
+	    g_assert (FALSE);
+	}
+	
+	return line + 25;
+    }
+
+    return NULL;
+}
+#if 0
+    
+    for (i = 0; i < len; ++i)
+    {
+    
     
     while ((eol = strchr (line, '\n')))
     {
@@ -361,14 +451,6 @@ parse_line (char *line, Entry *entry)
 			 &(entry->location)))
 	{
 #if 0
-	    g_print ("line: %s", line);
-	    g_print ("Entry:\n");
-	    g_print ("- pid: %d\n", entry->pid);
-	    g_print ("- cpu: %d\n", entry->cpu);
-	    g_print ("- timestamp: %lld\n", entry->timestamp);
-	    g_print ("- type: %ld\n", entry->type);
-	    g_print ("- address: %ld\n", entry->address);
-	    g_print ("- location: %ld\n", entry->location);
 #endif
 	    
 	    return eol + 1;
@@ -382,7 +464,7 @@ parse_line (char *line, Entry *entry)
     }
 
     return NULL;
-}
+#endif
 
 static CPUInfo *
 find_cpu_info (Collector *collector, int pid)
@@ -403,7 +485,7 @@ static gboolean
 process_entry (Collector *collector, Entry *entry)
 {
     CPUInfo *info = NULL;
-	
+
     /* There can be up to N_CPU stacktraces in progress at the same
      * time, but processes can move between CPU's in the middle of
      * the stack-tracing, so we can't have CPU specific states.
@@ -470,7 +552,7 @@ static void
 parse_input (Collector *collector)
 {
     Entry entry;
-    char *str, *s;
+    const guchar *str, *s;
     int len;
     /* Four states */
     gboolean ignoring;
@@ -479,15 +561,17 @@ parse_input (Collector *collector)
     gboolean update = FALSE;
     
     str = collector->input->str;
+    len = collector->input->len;
 
-    while ((s = parse_line (str, &entry)))
+    while ((s = parse_line (str, len, &entry)))
     {
 	process_entry (collector, &entry);
 
+	len -= (s - str);
 	str = s;
     }
 
-    g_string_erase (collector->input, 0, str - collector->input->str);
+    g_string_erase (collector->input, 0, collector->input->len - len);
 }
 
 /* */
@@ -522,6 +606,7 @@ on_read (gpointer data)
     
     first = collector->n_samples == 0;
 
+#if 0
     /* Sometimes we get nul bytes in the input. This is inconvenient, so
      * replace them with newlines.
      */
@@ -530,6 +615,7 @@ on_read (gpointer data)
 	if (input[i] == 0)
 	    input[i] = '\n';
     }
+#endif
     
     g_string_append_len (collector->input, input, n_bytes);
 
@@ -579,7 +665,7 @@ start_tracing (Collector *collector,
 	return FALSE;
     }
 
-    if (!write_text ("/sys/kernel/debug/tracing/iter_ctrl", "nobin\n"))
+    if (!write_text ("/sys/kernel/debug/tracing/iter_ctrl", "bin\n"))
     {
 	g_print ("Failed to make binary\n");
 	return FALSE;
@@ -593,7 +679,7 @@ start_tracing (Collector *collector,
     }
 #endif
 
-    fd = open ("/sys/kernel/debug/tracing/trace_pipe", O_RDONLY);
+    fd = open ("/sys/kernel/debug/tracing/trace_pipe", O_RDONLY | O_NONBLOCK);
     if (fd < 0)
     {
 	g_print ("Failed to open trace pipe\n");



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