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

[Xen-devel] [PATCH 3 of 4] Improve xentrace to use VIRQ_TBUF interrupts as well as a user-specified



# HG changeset patch
# User Michael.Fetterman@xxxxxxxxxxxx
# Date 1202591471 0
# Node ID f904468403b4d47dbebc54c76473c28b24066681
# Parent  9ff80e7b54528e06c8e0dc0ad8d8da09afca7f16
Improve xentrace to use VIRQ_TBUF interrupts as well as a user-specified
polling interval in order to determine when to empty the trace buffers.
Removed the old and unused/unimplemented new_data_threshold logic.

Signed-off-by: Michael A Fetterman <Michael.Fetterman@xxxxxxxxxxxx>

diff -r 9ff80e7b5452 -r f904468403b4 tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Sat Feb 09 21:11:09 2008 +0000
+++ b/tools/xentrace/xentrace.c Sat Feb 09 21:11:11 2008 +0000
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <getopt.h>
 #include <assert.h>
+#include <sys/poll.h>
 
 #include <xen/xen.h>
 #include <xen/trace.h>
@@ -40,9 +41,6 @@ do {                                    
 
 /***** Compile time configuration of defaults ********************************/
 
-/* when we've got more records than this waiting, we log it to the output */
-#define NEW_DATA_THRESH 1
-
 /* sleep for this long (milliseconds) between checking the trace buffers */
 #define POLL_SLEEP_MILLIS 100
 
@@ -51,8 +49,7 @@ do {                                    
 
 typedef struct settings_st {
     char *outfile;
-    struct timespec poll_sleep;
-    unsigned long new_data_thresh;
+    unsigned long poll_sleep; /* milliseconds to sleep between polls */
     uint32_t evt_mask;
     uint32_t cpu_mask;
     unsigned long tbuf_size;
@@ -63,23 +60,13 @@ settings_t opts;
 
 int interrupted = 0; /* gets set if we get a SIGHUP */
 
+static int xc_handle = -1;
+static int event_fd = -1;
+static int virq_port = -1;
+
 void close_handler(int signal)
 {
     interrupted = 1;
-}
-
-/**
- * millis_to_timespec - convert a time in milliseconds to a struct timespec
- * @millis:             time interval in milliseconds
- */
-struct timespec millis_to_timespec(unsigned long millis)
-{
-    struct timespec spec;
-    
-    spec.tv_sec = millis / 1000;
-    spec.tv_nsec = (millis % 1000) * 1000;
-
-    return spec;
 }
 
 /**
@@ -143,13 +130,7 @@ void write_buffer(unsigned int cpu, unsi
 
 static void get_tbufs(unsigned long *mfn, unsigned long *size)
 {
-    int xc_handle = xc_interface_open();
     int ret;
-
-    if ( xc_handle < 0 ) 
-    {
-        exit(EXIT_FAILURE);
-    }
 
     if(!opts.tbuf_size)
       opts.tbuf_size = DEFAULT_TBUF_SIZE;
@@ -161,8 +142,6 @@ static void get_tbufs(unsigned long *mfn
         perror("Couldn't enable trace buffers");
         exit(1);
     }
-
-    xc_interface_close(xc_handle);
 }
 
 /**
@@ -176,22 +155,12 @@ struct t_buf *map_tbufs(unsigned long tb
 struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
                         unsigned long size)
 {
-    int xc_handle;
     struct t_buf *tbufs_mapped;
-
-    xc_handle = xc_interface_open();
-
-    if ( xc_handle < 0 ) 
-    {
-        exit(EXIT_FAILURE);
-    }
 
     tbufs_mapped = xc_map_foreign_range(xc_handle, DOMID_XEN,
                                         size * num, PROT_READ | PROT_WRITE,
                                         tbufs_mfn);
 
-    xc_interface_close(xc_handle);
-
     if ( tbufs_mapped == 0 ) 
     {
         PERROR("Failed to mmap trace buffers");
@@ -210,7 +179,6 @@ void set_mask(uint32_t mask, int type)
 void set_mask(uint32_t mask, int type)
 {
     int ret = 0;
-    int xc_handle = xc_interface_open(); /* for accessing control interface */
 
     if (type == 1) {
         ret = xc_tbuf_set_cpu_mask(xc_handle, mask);
@@ -220,8 +188,6 @@ void set_mask(uint32_t mask, int type)
         fprintf(stderr, "change evtmask to 0x%x\n", mask);
     }
 
-    xc_interface_close(xc_handle);
-
     if ( ret != 0 )
     {
         PERROR("Failure to get trace buffer pointer from Xen and set the new 
mask");
@@ -295,7 +261,6 @@ unsigned int get_num_cpus(void)
 unsigned int get_num_cpus(void)
 {
     xc_physinfo_t physinfo = { 0 };
-    int xc_handle = xc_interface_open();
     int ret;
     
     ret = xc_physinfo(xc_handle, &physinfo);
@@ -306,9 +271,68 @@ unsigned int get_num_cpus(void)
         exit(EXIT_FAILURE);
     }
 
-    xc_interface_close(xc_handle);
-
     return physinfo.nr_cpus;
+}
+
+/**
+ * event_init - setup to receive the VIRQ_TBUF event
+ */
+void event_init(void)
+{
+    int rc;
+
+    rc = xc_evtchn_open();
+    if (rc < 0) {
+        perror(xc_get_last_error()->message);
+        exit(EXIT_FAILURE);
+    }
+    event_fd = rc;
+
+    rc = xc_evtchn_bind_virq(event_fd, VIRQ_TBUF);
+    if (rc == -1) {
+        PERROR("failed to bind to VIRQ port");
+        exit(EXIT_FAILURE);
+    }
+    virq_port = rc;
+}
+
+/**
+ * wait_for_event_or_timeout - sleep for the specified number of milliseconds,
+ *                             or until an VIRQ_TBUF event occurs
+ */
+void wait_for_event_or_timeout(unsigned long milliseconds)
+{
+    int rc;
+    struct pollfd fd = { .fd = event_fd,
+                         .events = POLLIN | POLLERR };
+    int port;
+
+    rc = poll(&fd, 1, milliseconds);
+    if (rc == -1) {
+        if (errno == EINTR)
+            return;
+        PERROR("poll exitted with an error");
+        exit(EXIT_FAILURE);
+    }
+
+    if (rc == 1) {
+        port = xc_evtchn_pending(event_fd);
+        if (port == -1) {
+            PERROR("failed to read port from evtchn");
+            exit(EXIT_FAILURE);
+        }
+        if (port != virq_port) {
+            fprintf(stderr,
+                    "unexpected port returned from evtchn (got %d vs expected 
%d)\n",
+                    port, virq_port);
+            exit(EXIT_FAILURE);
+        }
+        rc = xc_evtchn_unmask(event_fd, port);
+        if (rc == -1) {
+            PERROR("failed to write port to evtchn");
+            exit(EXIT_FAILURE);
+        }
+    }
 }
 
 
@@ -329,6 +353,9 @@ int monitor_tbufs(int outfd)
     unsigned long size;          /* size of a single trace buffer            */
 
     unsigned long data_size;
+
+    /* prepare to listen for VIRQ_TBUF */
+    event_init();
 
     /* get number of logical CPUs (and therefore number of trace buffers) */
     num = get_num_cpus();
@@ -405,7 +432,7 @@ int monitor_tbufs(int outfd)
             meta[i]->cons = prod;
         }
 
-        nanosleep(&opts.poll_sleep, NULL);
+        wait_for_event_or_timeout(opts.poll_sleep);
     }
 
     /* cleanup */
@@ -425,7 +452,7 @@ int monitor_tbufs(int outfd)
 #define xstr(x) str(x)
 #define str(x) #x
 
-const char *program_version     = "xentrace v1.1";
+const char *program_version     = "xentrace v1.2";
 const char *program_bug_address = "<mark.a.williamson@xxxxxxxxx>";
 
 void usage(void)
@@ -444,9 +471,6 @@ void usage(void)
 "                          N.B. that the trace buffer cannot be resized.\n" \
 "                          if it has already been set this boot cycle,\n" \
 "                          this argument will be ignored.\n" \
-"  -t, --log-thresh=l      Set number, l, of new records required to\n" \
-"                          trigger a write to output (default " \
-                           xstr(NEW_DATA_THRESH) ").\n" \
 "  -?, --help              Show this message\n" \
 "  -V, --version           Print program version\n" \
 "\n" \
@@ -525,12 +549,8 @@ void parse_args(int argc, char **argv)
     {
         switch ( option )
         {
-        case 't': /* set new records threshold for logging */
-            opts.new_data_thresh = argtol(optarg, 0);
-            break;
-
         case 's': /* set sleep time (given in milliseconds) */
-            opts.poll_sleep = millis_to_timespec(argtol(optarg, 0));
+            opts.poll_sleep = argtol(optarg, 0);
             break;
 
         case 'c': /* set new cpu mask for filtering*/
@@ -574,13 +594,19 @@ int main(int argc, char **argv)
     struct sigaction act;
 
     opts.outfile = 0;
-    opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS);
-    opts.new_data_thresh = NEW_DATA_THRESH;
+    opts.poll_sleep = POLL_SLEEP_MILLIS;
     opts.evt_mask = 0;
     opts.cpu_mask = 0;
 
     parse_args(argc, argv);
-    
+
+    xc_handle = xc_interface_open();
+    if ( xc_handle < 0 ) 
+    {
+        perror(xc_get_last_error()->message);
+        exit(EXIT_FAILURE);
+    }
+
     if ( opts.evt_mask != 0 )
         set_mask(opts.evt_mask, 0);
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.