[sysprof] Also filter out NMI stack



commit 1b64f1d92446e148586972b7e885b7b81a33ba7e
Author: Søren Sandmann Pedersen <ssp l3000 localdomain>
Date:   Thu Oct 29 07:40:51 2009 -0400

    Also filter out NMI stack

 tracker.c |  253 ++++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 134 insertions(+), 119 deletions(-)
---
diff --git a/tracker.c b/tracker.c
index c8f7915..7b0dc9e 100644
--- a/tracker.c
+++ b/tracker.c
@@ -19,7 +19,7 @@ typedef struct exit_t exit_t;
 struct tracker_t
 {
     StackStash *stash;
-    
+
     size_t	n_event_bytes;
     size_t	n_allocated_bytes;
     uint8_t *	events;
@@ -87,16 +87,16 @@ get_lines (const char *format, pid_t pid)
     char *filename = g_strdup_printf (format, pid);
     char **result = NULL;
     char *contents;
-    
+
     if (g_file_get_contents (filename, &contents, NULL, NULL))
     {
         result = g_strsplit (contents, "\n", -1);
-	
+
         g_free (contents);
     }
-    
+
     g_free (filename);
-    
+
     return result;
 }
 
@@ -105,7 +105,7 @@ fake_new_process (tracker_t *tracker, pid_t pid)
 {
     char **lines;
     gboolean done = FALSE;
-    
+
     if ((lines = get_lines ("/proc/%d/cmdline", pid)))
     {
 	if (lines[0] && strlen (lines[0]) > 0)
@@ -121,7 +121,7 @@ fake_new_process (tracker_t *tracker, pid_t pid)
     if (!done && (lines = get_lines ("/proc/%d/status", pid)))
     {
         int i;
-       
+
         for (i = 0; lines[i] != NULL; ++i)
         {
             if (strncmp ("Name:", lines[i], 5) == 0)
@@ -148,11 +148,11 @@ static void
 fake_new_map (tracker_t *tracker, pid_t pid)
 {
     char **lines;
-    
+
     if ((lines = get_lines ("/proc/%d/maps", pid)))
     {
         int i;
-	
+
         for (i = 0; lines[i] != NULL; ++i)
         {
             char file[256];
@@ -161,13 +161,13 @@ fake_new_map (tracker_t *tracker, pid_t pid)
             gulong offset;
             gulong inode;
             int count;
-	    
+
 	    file[255] = '\0';
-	    
+
             count = sscanf (
                 lines[i], "%lx-%lx %*15s %lx %*x:%*x %lu %255s",
                 &start, &end, &offset, &inode, file);
-	    
+
             if (count == 5)
             {
                 if (strcmp (file, "[vdso]") == 0)
@@ -181,11 +181,11 @@ fake_new_map (tracker_t *tracker, pid_t pid)
                     offset = 0;
                     inode = 0;
                 }
-		
+
 		tracker_add_map (tracker, pid, start, end, offset, inode, file);
             }
         }
-	
+
         g_strfreev (lines);
     }
 }
@@ -195,24 +195,24 @@ populate_from_proc (tracker_t *tracker)
 {
     GDir *proc = g_dir_open ("/proc", 0, NULL);
     const char *name;
-    
+
     if (!proc)
         return;
-    
+
     while ((name = g_dir_read_name (proc)))
     {
         pid_t pid;
         char *end;
-	
+
         pid = strtol (name, &end, 10);
-	
+
         if (*end == 0)
         {
 	    fake_new_process (tracker, pid);
 	    fake_new_map (tracker, pid);
 	}
     }
-    
+
     g_dir_close (proc);
 }
 
@@ -229,7 +229,7 @@ time_diff (const GTimeVal *first,
 {
     double first_ms = timeval_to_ms (first);
     double second_ms = timeval_to_ms (second);
-    
+
     return first_ms - second_ms;
 }
 
@@ -238,21 +238,21 @@ tracker_new (void)
 {
     tracker_t *tracker = g_new0 (tracker_t, 1);
     GTimeVal before, after;
-    
+
     tracker->n_event_bytes = 0;
     tracker->n_allocated_bytes = DEFAULT_SIZE;
     tracker->events = g_malloc (DEFAULT_SIZE);
-    
+
     tracker->stash = stack_stash_new (NULL);
-    
+
     g_get_current_time (&before);
-    
+
     populate_from_proc (tracker);
-    
+
     g_get_current_time (&after);
-    
+
     g_print ("Time to populate %f\n", time_diff (&after, &before));
-    
+
     return tracker;
 }
 
@@ -281,14 +281,14 @@ tracker_append (tracker_t *tracker,
     if (tracker->n_allocated_bytes - tracker->n_event_bytes < n_bytes)
     {
 	size_t new_size = tracker->n_allocated_bytes * 2;
-	
+
 	tracker->events = g_realloc (tracker->events, new_size);
-	
+
 	tracker->n_allocated_bytes = new_size;
     }
-    
+
     g_assert (tracker->n_allocated_bytes - tracker->n_event_bytes >= n_bytes);
-    
+
     memcpy (tracker->events + tracker->n_event_bytes, event, n_bytes);
 
     tracker->n_event_bytes += n_bytes;
@@ -303,7 +303,7 @@ tracker_add_process (tracker_t * tracker,
 
     event.header = MAKE_HEADER (NEW_PROCESS, pid);
     COPY_STRING (event.command_line, command_line);
-    
+
     tracker_append (tracker, &event, sizeof (event));
 }
 
@@ -341,14 +341,14 @@ tracker_add_map (tracker_t * tracker,
 		 const char *filename)
 {
     new_map_t event;
-    
+
     event.header = MAKE_HEADER (NEW_MAP, pid);
     COPY_STRING (event.filename, filename);
     event.start = start;
     event.end = end;
     event.offset = offset;
     event.inode = inode;
-    
+
     tracker_append (tracker, &event, sizeof (event));
 }
 
@@ -359,10 +359,10 @@ tracker_add_sample  (tracker_t *tracker,
 		     int        n_ips)
 {
     sample_t event;
-    
+
     event.header = MAKE_HEADER (SAMPLE, pid);
     event.trace = stack_stash_add_trace (tracker->stash, ips, n_ips, 1);
-    
+
     tracker_append (tracker, &event, sizeof (event));
 }
 
@@ -374,9 +374,9 @@ typedef struct map_t map_t;
 struct process_t
 {
     pid_t       pid;
-    
+
     char *      comm;
-    
+
     GPtrArray *	maps;
 };
 
@@ -411,33 +411,33 @@ create_map (state_t *state, new_map_t *new_map)
     map_t *map;
     int i;
     pid_t pid = GET_PID (new_map->header);
-    
+
     process = g_hash_table_lookup (
 	state->processes_by_pid, GINT_TO_POINTER (pid));
-    
+
     if (!process)
 	return;
-    
+
     map = g_new0 (map_t, 1);
     map->filename = g_strdup (new_map->filename);
     map->start = new_map->start;
     map->end = new_map->end;
     map->offset = new_map->offset;
     map->inode = new_map->inode;
-    
+
     /* Remove existing maps that overlap the new one */
     for (i = 0; i < process->maps->len; ++i)
     {
         map_t *m = process->maps->pdata[i];
-	
+
         if (m->start < map->end && m->end > map->start)
         {
             destroy_map (m);
-	    
+
             g_ptr_array_remove_index (process->maps, i);
         }
     }
-    
+
     g_ptr_array_add (process->maps, map);
 }
 
@@ -445,16 +445,16 @@ static void
 destroy_process (process_t *process)
 {
     int i;
-    
+
     g_free (process->comm);
-    
+
     for (i = 0; i < process->maps->len; ++i)
     {
 	map_t *map = process->maps->pdata[i];
-	
+
 	destroy_map (map);
     }
-    
+
     g_ptr_array_free (process->maps, TRUE);
     g_free (process);
 }
@@ -463,7 +463,7 @@ static void
 create_process (state_t *state, new_process_t *new_process)
 {
     process_t *process = g_new0 (process_t, 1);
-    
+
     process->pid = GET_PID (new_process->header);
     process->comm = g_strdup (new_process->command_line);
     process->maps = g_ptr_array_new ();
@@ -471,7 +471,7 @@ create_process (state_t *state, new_process_t *new_process)
 #if 0
     g_print ("new comm process %d\n", new_process->pid);
 #endif
-    
+
     g_hash_table_insert (
 	state->processes_by_pid, GINT_TO_POINTER (process->pid), process);
 }
@@ -503,21 +503,21 @@ process_fork (state_t *state, fork_t *fork)
 #if 0
 	g_print ("new child %d\n", fork->child_pid);
 #endif
-	
+
 	process->pid = fork->child_pid;
 	process->comm = g_strdup (parent? parent->comm : "<unknown>");
 	process->maps = g_ptr_array_new ();
-	
+
 	if (parent)
 	{
 	    for (i = 0; i < parent->maps->len; ++i)
 	    {
 		map_t *map = copy_map (parent->maps->pdata[i]);
-		
+
 		g_ptr_array_add (process->maps, map);
 	    }
 	}
-	
+
 	g_hash_table_insert (
 	    state->processes_by_pid, GINT_TO_POINTER (process->pid), process);
     }
@@ -533,7 +533,7 @@ process_exit (state_t *state, exit_t *exit)
 #if 0
     g_print ("Exit for %d\n", exit->pid);
 #endif
-    
+
     /* ignore for now */
 }
 
@@ -541,7 +541,7 @@ static void
 free_process (gpointer data)
 {
     process_t *process = data;
-    
+
     destroy_process (process);
 }
 
@@ -549,19 +549,19 @@ static state_t *
 state_new (void)
 {
     state_t *state = g_new0 (state_t, 1);
-    
+
     state->processes_by_pid =
 	g_hash_table_new_full (g_direct_hash, g_direct_equal,
 			       NULL, free_process);
-    
+
     state->unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal);
     state->unique_comms = g_hash_table_new (g_str_hash, g_str_equal);
     state->bin_files = g_hash_table_new_full (g_str_hash, g_str_equal,
 					      g_free,
 					      (GDestroyNotify)bin_file_free);
-    
+
     return state;
-}    
+}
 
 static void
 state_free (state_t *state)
@@ -570,7 +570,7 @@ state_free (state_t *state)
     g_hash_table_destroy (state->unique_symbols);
     g_hash_table_destroy (state->unique_comms);
     g_hash_table_destroy (state->bin_files);
-    
+
     g_free (state);
 }
 
@@ -584,27 +584,27 @@ static void
 parse_kallsym_line (const char *line, GArray *table)
 {
     char **tokens = g_strsplit_set (line, " \t", -1);
-    
+
     if (tokens[0] && tokens[1] && tokens[2])
     {
 	glong address;
 	char *endptr;
-	
+
 	address = strtoul (tokens[0], &endptr, 16);
-	
+
 	if (*endptr == '\0'			&&
 	    (strcmp (tokens[1], "T") == 0	||
 	     strcmp (tokens[1], "t") == 0))
 	{
 	    kernel_symbol_t sym;
-	    
+
 	    sym.address = address;
 	    sym.name = g_strdup (tokens[2]);
-	    
+
 	    g_array_append_val (table, sym);
 	}
     }
-    
+
     g_strfreev (tokens);
 }
 
@@ -614,24 +614,24 @@ parse_kallsyms (const char *kallsyms,
 {
     const char *sol;
     const char *eol;
-    
+
     sol = kallsyms;
     eol = strchr (sol, '\n');
     while (eol)
     {
 	char *line = g_strndup (sol, eol - sol);
-	
+
 	parse_kallsym_line (line, table);
-	
+
 	g_free (line);
-	
+
 	sol = eol + 1;
 	eol = strchr (sol, '\n');
     }
-    
+
     if (table->len <= 1)
 	return FALSE;
-    
+
     return TRUE;
 }
 
@@ -640,7 +640,7 @@ compare_syms (gconstpointer a, gconstpointer b)
 {
     const kernel_symbol_t *sym_a = a;
     const kernel_symbol_t *sym_b = b;
-    
+
     if (sym_a->address > sym_b->address)
 	return 1;
     else if (sym_a->address == sym_b->address)
@@ -665,16 +665,16 @@ do_lookup (kernel_symbol_t *symbols,
 	{
 	    if (address >= symbols[last].address)
 		return &(symbols[last]);
-	    
+
 	    last--;
 	}
-	
+
 	return NULL;
     }
     else
     {
 	int mid = (first + last) / 2;
-	
+
 	if (symbols[mid].address > address)
 	    return do_lookup (symbols, address, first, mid);
 	else
@@ -687,11 +687,11 @@ get_kernel_symbols (void)
 {
     static GArray *kernel_syms;
     static gboolean initialized = FALSE;
-    
+
 #if 0
     find_kernel_binary();
 #endif
-    
+
     if (!initialized)
     {
 	char *kallsyms;
@@ -700,7 +700,7 @@ get_kernel_symbols (void)
 	    if (kallsyms)
 	    {
 		kernel_syms = g_array_new (TRUE, TRUE, sizeof (kernel_symbol_t));
-		
+
 		if (parse_kallsyms (kallsyms, kernel_syms))
 		{
 		    g_array_sort (kernel_syms, compare_syms);
@@ -711,24 +711,25 @@ get_kernel_symbols (void)
 		    kernel_syms = NULL;
 		}
 	    }
-	    
+
 	    g_free (kallsyms);
 	}
-	
+
 	if (!kernel_syms)
 	{
 	    g_print ("Warning: /proc/kallsyms could not be "
 		     "read. Kernel symbols will not be available\n");
 	}
-	
+
 	initialized = TRUE;
     }
-    
+
     return kernel_syms;
 }
 
 static const char skip_kernel_symbols[][32]  =
 {
+    /* IRQ stack */
     "common_interrupt",
     "apic_timer_interrupt",
     "smp_apic_timer_interrupt",
@@ -739,6 +740,20 @@ static const char skip_kernel_symbols[][32]  =
     "__perf_event_overflow",
     "perf_prepare_sample",
     "perf_callchain",
+
+    /* NMI stack */
+    "nmi_stack_correct",
+    "do_nmi",
+    "notify_die",
+    "atomic_notifier_call_chain",
+    "notifier_call_chain",
+    "perf_event_nmi_handler",
+    "intel_pmu_handle_irq",
+    "perf_event_overflow",
+    "__perf_event_overflow",
+    "perf_prepare_sample",
+    "perf_callchain",
+
     ""
 };
 
@@ -750,12 +765,12 @@ lookup_kernel_symbol (gulong address)
     const char *sym;
     const char *s;
     int i;
-    
+
     if (ksyms->len == 0)
 	return NULL;
-    
+
     result = do_lookup ((kernel_symbol_t *)ksyms->data, address, 0, ksyms->len - 1);
-    
+
     sym = result? result->name : NULL;
 
 
@@ -791,14 +806,14 @@ static char *
 unique_dup (GHashTable *unique_symbols, const char *sym)
 {
     char *result;
-    
+
     result = g_hash_table_lookup (unique_symbols, sym);
     if (!result)
     {
 	result = elf_demangle (sym);
 	g_hash_table_insert (unique_symbols, (char *)sym, result);
     }
-    
+
     return result;
 }
 
@@ -806,15 +821,15 @@ static map_t *
 process_locate_map (process_t *process, gulong addr)
 {
     int i;
-    
+
     for (i = 0; i < process->maps->len; ++i)
     {
 	map_t *map = process->maps->pdata[i];
-	
+
 	if (addr >= map->start && addr < map->end)
 	    return map;
     }
-    
+
     return NULL;
 }
 
@@ -837,7 +852,7 @@ make_message (state_t *state, const char *format, ...)
     else
     {
 	result = message;
-	
+
 	g_hash_table_insert (state->unique_comms, result, result);
     }
 
@@ -866,9 +881,9 @@ lookup_symbol (state_t    *state,
 	       gboolean    kernel)
 {
     const char *sym;
-    
+
     g_assert (process);
-    
+
     if (kernel)
     {
 	sym = lookup_kernel_symbol (address);
@@ -876,7 +891,7 @@ lookup_symbol (state_t    *state,
     else
     {
 	map_t *map = process_locate_map (process, address);
-    
+
 	if (!map)
 	{
 	    sym = make_message (state, "No map [%s]", process->comm);
@@ -885,7 +900,7 @@ lookup_symbol (state_t    *state,
 	{
 	    bin_file_t *bin_file = state_get_bin_file (state, map->filename);
 	    const bin_symbol_t *bin_sym;
-	    
+
 	    address -= map->start;
 	    address += map->offset;
 
@@ -899,12 +914,12 @@ lookup_symbol (state_t    *state,
 	    else
 	    {
 		bin_sym = bin_file_lookup_symbol (bin_file, address);
-		
+
 		sym = bin_symbol_get_name (bin_file, bin_sym);
 	    }
 	}
     }
-    
+
     if (sym)
 	return unique_dup (state->unique_symbols, sym);
     else
@@ -916,7 +931,7 @@ struct context_info_t
 {
     enum perf_callchain_context	context;
     char			name[32];
-};    
+};
 
 static const context_info_t context_info[] =
 {
@@ -934,15 +949,15 @@ static const context_info_t *
 get_context_info (enum perf_callchain_context context)
 {
     int i;
-    
+
     for (i = 0; i < sizeof (context_info) / sizeof (context_info[0]); ++i)
     {
 	const context_info_t *info = &context_info[i];
-	
+
 	if (info->context == context)
 	    return info;
     }
-    
+
     return NULL;
 }
 
@@ -960,7 +975,7 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
 
     process = g_hash_table_lookup (
 	state->processes_by_pid, GINT_TO_POINTER (pid));
-    
+
     if (!process)
     {
 	static gboolean warned;
@@ -973,7 +988,7 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
 	}
 	return;
     }
-    
+
     len = 5;
     for (n = sample->trace; n != NULL; n = n->parent)
 	len++;
@@ -982,14 +997,14 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
 	resolved_traces = g_new (uint64_t, len);
     else
 	resolved_traces = stack_addrs;
-    
+
     len = 0;
     for (n = sample->trace; n != NULL; n = n->parent)
     {
 	uint64_t address = n->data;
 	const context_info_t *new_context;
 	const char *symbol;
-	
+
 	new_context = get_context_info (address);
 	if (new_context)
 	{
@@ -997,16 +1012,16 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
 		symbol = unique_dup (state->unique_symbols, context->name);
 	    else
 		symbol = NULL;
-	    
+
 	    context = new_context;
 	}
 	else
 	{
 	    gboolean kernel = context && context->context == PERF_CONTEXT_KERNEL;
-	    
+
 	    symbol = lookup_symbol (state, process, address, kernel);
 	}
-	
+
 	if (symbol)
 	    resolved_traces[len++] = POINTER_TO_U64 (symbol);
     }
@@ -1021,9 +1036,9 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
 	resolved_traces[len++] =
 	    POINTER_TO_U64 (unique_dup (state->unique_symbols, context->name));
     }
-	
+
     cmdline = make_message (state, "[%s]", process->comm);
-    
+
     resolved_traces[len++] = POINTER_TO_U64 (cmdline);
     resolved_traces[len++] = POINTER_TO_U64 (
 	unique_dup (state->unique_symbols, everything));
@@ -1042,22 +1057,22 @@ tracker_create_profile (tracker_t *tracker)
     Profile *profile;
     state_t *state;
     uint8_t *event;
-    
+
     state = state_new ();
     resolved_stash = stack_stash_new (g_free);
-    
+
     event = tracker->events;
     while (event < end)
     {
 	event_type_t type = GET_TYPE (*(uint32_t *)event);
-	
+
 	switch (type)
 	{
 	case NEW_PROCESS:
 	    create_process (state, (new_process_t *)event);
 	    event += sizeof (new_process_t);
 	    break;
-	    
+
 	case NEW_MAP:
 	    create_map (state, (new_map_t *)event);
 	    event += sizeof (new_map_t);
@@ -1072,7 +1087,7 @@ tracker_create_profile (tracker_t *tracker)
 	    process_exit (state, (exit_t *)event);
 	    event += sizeof (exit_t);
 	    break;
-	    
+
 	case SAMPLE:
 	    process_sample (state, resolved_stash, (sample_t *)event);
 	    event += sizeof (sample_t);
@@ -1084,6 +1099,6 @@ tracker_create_profile (tracker_t *tracker)
 
     state_free (state);
     stack_stash_unref (resolved_stash);
-    
+
     return profile;
 }



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