[ovs-dev] [PATCH 2/2] timeval: Add new "backtrace" appctl command.

Ethan Jackson ethan at nicira.com
Mon Oct 15 00:13:07 UTC 2012


Good point.  Here's an incremental that switches to a pre-allocated array of 50
elements.

---
 lib/timeval.c | 44 +++++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/lib/timeval.c b/lib/timeval.c
index 345c9ae..4763f47 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -32,7 +32,6 @@
 #include "dummy.h"
 #include "dynamic-string.h"
 #include "fatal-signal.h"
-#include "list.h"
 #include "signals.h"
 #include "unixctl.h"
 #include "util.h"
@@ -70,16 +69,16 @@ static bool time_stopped;           /* Disables real-time updates, if true. */
 /* Time in milliseconds at which to die with SIGALRM (if not LLONG_MAX). */
 static long long int deadline = LLONG_MAX;
 
-static struct unixctl_conn *backtrace_conn = NULL;
-static struct list traces = LIST_INITIALIZER(&traces);
-static size_t n_traces OVS_UNUSED = 0;
-
 struct trace {
-    struct list node;    /* In 'traces' list. */
     void *backtrace[32]; /* Populated by backtrace(). */
     size_t n_frames;     /* Number of frames in 'backtrace'. */
 };
 
+#define MAX_TRACES 50
+static struct unixctl_conn *backtrace_conn = NULL;
+static struct trace *traces = NULL;
+static size_t n_traces = 0;
+
 static void set_up_timer(void);
 static void set_up_signal(int flags);
 static void sigalrm_handler(int);
@@ -397,11 +396,8 @@ sigalrm_handler(int sig_nr OVS_UNUSED)
     monotonic_tick = true;
 
 #if HAVE_EXECINFO_H
-    if (backtrace_conn) {
-        struct trace *trace = xmalloc(sizeof *trace);
-
-        n_traces++;
-        list_push_back(&traces, &trace->node);
+    if (backtrace_conn && n_traces < MAX_TRACES) {
+        struct trace *trace = &traces[n_traces++];
         trace->n_frames = backtrace(trace->backtrace,
                                     ARRAY_SIZE(trace->backtrace));
     }
@@ -612,30 +608,30 @@ static void
 trace_run(void)
 {
 #if HAVE_EXECINFO_H
-    if (backtrace_conn && n_traces >= 50) {
+    if (backtrace_conn && n_traces >= MAX_TRACES) {
         struct ds ds = DS_EMPTY_INITIALIZER;
-        struct trace *trace, *next;
         size_t i;
 
-        i = 1;
-        LIST_FOR_EACH_SAFE (trace, next, node, &traces) {
+        for (i = 0; i < n_traces; i++) {
+            struct trace *trace = &traces[i];
             char **frame_strs;
             size_t j;
 
             frame_strs = backtrace_symbols(trace->backtrace, trace->n_frames);
 
-            ds_put_format(&ds, "Backtrace %zu\n", i);
+            ds_put_format(&ds, "Backtrace %zu\n", i + 1);
             for (j = 0; j < trace->n_frames; j++) {
                 ds_put_format(&ds, "%s\n", frame_strs[j]);
             }
             ds_put_cstr(&ds, "\n");
 
             free(frame_strs);
-            list_remove(&trace->node);
-            free(trace);
-            i++;
         }
+
+        free(traces);
+        traces = NULL;
         n_traces = 0;
+
         unixctl_command_reply(backtrace_conn, ds_cstr(&ds));
         backtrace_conn = NULL;
     }
@@ -686,6 +682,16 @@ backtrace_cb(struct unixctl_conn *conn,
              void *aux OVS_UNUSED)
 {
     assert(HAVE_EXECINFO_H && CACHE_TIME);
+
+    if (backtrace_conn) {
+        unixctl_command_reply_error(conn, "In Use");
+        return;
+    }
+
+    assert(!traces);
+    traces = xmalloc(MAX_TRACES * sizeof *traces);
+    n_traces = 0;
+
     backtrace_conn = conn;
 }
 
-- 
1.7.12




More information about the dev mailing list