ia64/xen-unstable

changeset 17015:7a415bce11c9

xentrace: 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@cl.cam.ac.uk>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 11 09:46:53 2008 +0000 (2008-02-11)
parents 98e9d5d4b309
children c68ce89542c7
files tools/xentrace/xentrace.c
line diff
     1.1 --- a/tools/xentrace/xentrace.c	Mon Feb 11 09:46:21 2008 +0000
     1.2 +++ b/tools/xentrace/xentrace.c	Mon Feb 11 09:46:53 2008 +0000
     1.3 @@ -23,6 +23,7 @@
     1.4  #include <string.h>
     1.5  #include <getopt.h>
     1.6  #include <assert.h>
     1.7 +#include <sys/poll.h>
     1.8  
     1.9  #include <xen/xen.h>
    1.10  #include <xen/trace.h>
    1.11 @@ -40,9 +41,6 @@ do {                                    
    1.12  
    1.13  /***** Compile time configuration of defaults ********************************/
    1.14  
    1.15 -/* when we've got more records than this waiting, we log it to the output */
    1.16 -#define NEW_DATA_THRESH 1
    1.17 -
    1.18  /* sleep for this long (milliseconds) between checking the trace buffers */
    1.19  #define POLL_SLEEP_MILLIS 100
    1.20  
    1.21 @@ -51,8 +49,7 @@ do {                                    
    1.22  
    1.23  typedef struct settings_st {
    1.24      char *outfile;
    1.25 -    struct timespec poll_sleep;
    1.26 -    unsigned long new_data_thresh;
    1.27 +    unsigned long poll_sleep; /* milliseconds to sleep between polls */
    1.28      uint32_t evt_mask;
    1.29      uint32_t cpu_mask;
    1.30      unsigned long tbuf_size;
    1.31 @@ -63,26 +60,16 @@ settings_t opts;
    1.32  
    1.33  int interrupted = 0; /* gets set if we get a SIGHUP */
    1.34  
    1.35 +static int xc_handle = -1;
    1.36 +static int event_fd = -1;
    1.37 +static int virq_port = -1;
    1.38 +
    1.39  void close_handler(int signal)
    1.40  {
    1.41      interrupted = 1;
    1.42  }
    1.43  
    1.44  /**
    1.45 - * millis_to_timespec - convert a time in milliseconds to a struct timespec
    1.46 - * @millis:             time interval in milliseconds
    1.47 - */
    1.48 -struct timespec millis_to_timespec(unsigned long millis)
    1.49 -{
    1.50 -    struct timespec spec;
    1.51 -    
    1.52 -    spec.tv_sec = millis / 1000;
    1.53 -    spec.tv_nsec = (millis % 1000) * 1000;
    1.54 -
    1.55 -    return spec;
    1.56 -}
    1.57 -
    1.58 -/**
    1.59   * write_buffer - write a section of the trace buffer
    1.60   * @cpu      - source buffer CPU ID
    1.61   * @start
    1.62 @@ -143,14 +130,8 @@ void write_buffer(unsigned int cpu, unsi
    1.63  
    1.64  static void get_tbufs(unsigned long *mfn, unsigned long *size)
    1.65  {
    1.66 -    int xc_handle = xc_interface_open();
    1.67      int ret;
    1.68  
    1.69 -    if ( xc_handle < 0 ) 
    1.70 -    {
    1.71 -        exit(EXIT_FAILURE);
    1.72 -    }
    1.73 -
    1.74      if(!opts.tbuf_size)
    1.75        opts.tbuf_size = DEFAULT_TBUF_SIZE;
    1.76  
    1.77 @@ -161,8 +142,6 @@ static void get_tbufs(unsigned long *mfn
    1.78          perror("Couldn't enable trace buffers");
    1.79          exit(1);
    1.80      }
    1.81 -
    1.82 -    xc_interface_close(xc_handle);
    1.83  }
    1.84  
    1.85  /**
    1.86 @@ -176,22 +155,12 @@ static void get_tbufs(unsigned long *mfn
    1.87  struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
    1.88                          unsigned long size)
    1.89  {
    1.90 -    int xc_handle;
    1.91      struct t_buf *tbufs_mapped;
    1.92  
    1.93 -    xc_handle = xc_interface_open();
    1.94 -
    1.95 -    if ( xc_handle < 0 ) 
    1.96 -    {
    1.97 -        exit(EXIT_FAILURE);
    1.98 -    }
    1.99 -
   1.100      tbufs_mapped = xc_map_foreign_range(xc_handle, DOMID_XEN,
   1.101                                          size * num, PROT_READ | PROT_WRITE,
   1.102                                          tbufs_mfn);
   1.103  
   1.104 -    xc_interface_close(xc_handle);
   1.105 -
   1.106      if ( tbufs_mapped == 0 ) 
   1.107      {
   1.108          PERROR("Failed to mmap trace buffers");
   1.109 @@ -210,7 +179,6 @@ struct t_buf *map_tbufs(unsigned long tb
   1.110  void set_mask(uint32_t mask, int type)
   1.111  {
   1.112      int ret = 0;
   1.113 -    int xc_handle = xc_interface_open(); /* for accessing control interface */
   1.114  
   1.115      if (type == 1) {
   1.116          ret = xc_tbuf_set_cpu_mask(xc_handle, mask);
   1.117 @@ -220,8 +188,6 @@ void set_mask(uint32_t mask, int type)
   1.118          fprintf(stderr, "change evtmask to 0x%x\n", mask);
   1.119      }
   1.120  
   1.121 -    xc_interface_close(xc_handle);
   1.122 -
   1.123      if ( ret != 0 )
   1.124      {
   1.125          PERROR("Failure to get trace buffer pointer from Xen and set the new mask");
   1.126 @@ -295,7 +261,6 @@ unsigned char **init_rec_ptrs(struct t_b
   1.127  unsigned int get_num_cpus(void)
   1.128  {
   1.129      xc_physinfo_t physinfo = { 0 };
   1.130 -    int xc_handle = xc_interface_open();
   1.131      int ret;
   1.132      
   1.133      ret = xc_physinfo(xc_handle, &physinfo);
   1.134 @@ -306,9 +271,68 @@ unsigned int get_num_cpus(void)
   1.135          exit(EXIT_FAILURE);
   1.136      }
   1.137  
   1.138 -    xc_interface_close(xc_handle);
   1.139 +    return physinfo.nr_cpus;
   1.140 +}
   1.141  
   1.142 -    return physinfo.nr_cpus;
   1.143 +/**
   1.144 + * event_init - setup to receive the VIRQ_TBUF event
   1.145 + */
   1.146 +void event_init(void)
   1.147 +{
   1.148 +    int rc;
   1.149 +
   1.150 +    rc = xc_evtchn_open();
   1.151 +    if (rc < 0) {
   1.152 +        perror(xc_get_last_error()->message);
   1.153 +        exit(EXIT_FAILURE);
   1.154 +    }
   1.155 +    event_fd = rc;
   1.156 +
   1.157 +    rc = xc_evtchn_bind_virq(event_fd, VIRQ_TBUF);
   1.158 +    if (rc == -1) {
   1.159 +        PERROR("failed to bind to VIRQ port");
   1.160 +        exit(EXIT_FAILURE);
   1.161 +    }
   1.162 +    virq_port = rc;
   1.163 +}
   1.164 +
   1.165 +/**
   1.166 + * wait_for_event_or_timeout - sleep for the specified number of milliseconds,
   1.167 + *                             or until an VIRQ_TBUF event occurs
   1.168 + */
   1.169 +void wait_for_event_or_timeout(unsigned long milliseconds)
   1.170 +{
   1.171 +    int rc;
   1.172 +    struct pollfd fd = { .fd = event_fd,
   1.173 +                         .events = POLLIN | POLLERR };
   1.174 +    int port;
   1.175 +
   1.176 +    rc = poll(&fd, 1, milliseconds);
   1.177 +    if (rc == -1) {
   1.178 +        if (errno == EINTR)
   1.179 +            return;
   1.180 +        PERROR("poll exitted with an error");
   1.181 +        exit(EXIT_FAILURE);
   1.182 +    }
   1.183 +
   1.184 +    if (rc == 1) {
   1.185 +        port = xc_evtchn_pending(event_fd);
   1.186 +        if (port == -1) {
   1.187 +            PERROR("failed to read port from evtchn");
   1.188 +            exit(EXIT_FAILURE);
   1.189 +        }
   1.190 +        if (port != virq_port) {
   1.191 +            fprintf(stderr,
   1.192 +                    "unexpected port returned from evtchn (got %d vs expected %d)\n",
   1.193 +                    port, virq_port);
   1.194 +            exit(EXIT_FAILURE);
   1.195 +        }
   1.196 +        rc = xc_evtchn_unmask(event_fd, port);
   1.197 +        if (rc == -1) {
   1.198 +            PERROR("failed to write port to evtchn");
   1.199 +            exit(EXIT_FAILURE);
   1.200 +        }
   1.201 +    }
   1.202  }
   1.203  
   1.204  
   1.205 @@ -330,6 +354,9 @@ int monitor_tbufs(int outfd)
   1.206  
   1.207      unsigned long data_size;
   1.208  
   1.209 +    /* prepare to listen for VIRQ_TBUF */
   1.210 +    event_init();
   1.211 +
   1.212      /* get number of logical CPUs (and therefore number of trace buffers) */
   1.213      num = get_num_cpus();
   1.214  
   1.215 @@ -405,7 +432,7 @@ int monitor_tbufs(int outfd)
   1.216              meta[i]->cons = prod;
   1.217          }
   1.218  
   1.219 -        nanosleep(&opts.poll_sleep, NULL);
   1.220 +        wait_for_event_or_timeout(opts.poll_sleep);
   1.221      }
   1.222  
   1.223      /* cleanup */
   1.224 @@ -425,7 +452,7 @@ int monitor_tbufs(int outfd)
   1.225  #define xstr(x) str(x)
   1.226  #define str(x) #x
   1.227  
   1.228 -const char *program_version     = "xentrace v1.1";
   1.229 +const char *program_version     = "xentrace v1.2";
   1.230  const char *program_bug_address = "<mark.a.williamson@intel.com>";
   1.231  
   1.232  void usage(void)
   1.233 @@ -444,9 +471,6 @@ void usage(void)
   1.234  "                          N.B. that the trace buffer cannot be resized.\n" \
   1.235  "                          if it has already been set this boot cycle,\n" \
   1.236  "                          this argument will be ignored.\n" \
   1.237 -"  -t, --log-thresh=l      Set number, l, of new records required to\n" \
   1.238 -"                          trigger a write to output (default " \
   1.239 -                           xstr(NEW_DATA_THRESH) ").\n" \
   1.240  "  -?, --help              Show this message\n" \
   1.241  "  -V, --version           Print program version\n" \
   1.242  "\n" \
   1.243 @@ -525,12 +549,8 @@ void parse_args(int argc, char **argv)
   1.244      {
   1.245          switch ( option )
   1.246          {
   1.247 -        case 't': /* set new records threshold for logging */
   1.248 -            opts.new_data_thresh = argtol(optarg, 0);
   1.249 -            break;
   1.250 -
   1.251          case 's': /* set sleep time (given in milliseconds) */
   1.252 -            opts.poll_sleep = millis_to_timespec(argtol(optarg, 0));
   1.253 +            opts.poll_sleep = argtol(optarg, 0);
   1.254              break;
   1.255  
   1.256          case 'c': /* set new cpu mask for filtering*/
   1.257 @@ -574,13 +594,19 @@ int main(int argc, char **argv)
   1.258      struct sigaction act;
   1.259  
   1.260      opts.outfile = 0;
   1.261 -    opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS);
   1.262 -    opts.new_data_thresh = NEW_DATA_THRESH;
   1.263 +    opts.poll_sleep = POLL_SLEEP_MILLIS;
   1.264      opts.evt_mask = 0;
   1.265      opts.cpu_mask = 0;
   1.266  
   1.267      parse_args(argc, argv);
   1.268 -    
   1.269 +
   1.270 +    xc_handle = xc_interface_open();
   1.271 +    if ( xc_handle < 0 ) 
   1.272 +    {
   1.273 +        perror(xc_get_last_error()->message);
   1.274 +        exit(EXIT_FAILURE);
   1.275 +    }
   1.276 +
   1.277      if ( opts.evt_mask != 0 )
   1.278          set_mask(opts.evt_mask, 0);
   1.279