]> granicus.if.org Git - sysstat/commitdiff
Merge branch 'shaleen-bathla-master'
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 9 Oct 2022 15:06:26 +0000 (17:06 +0200)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 9 Oct 2022 15:06:26 +0000 (17:06 +0200)
Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
1  2 
man/mpstat.1
mpstat.c

diff --cc man/mpstat.1
index 08e45a5a19b9ce70ad003ce5219a06621c64b273,31ad48733b2562557bad20d97f011e7fdc3c93e1..29086c702fd11343b4b33dd0dd1eff0c46d0687f
@@@ -1,10 -1,10 +1,10 @@@
  .\" mpstat manual page - (C) 2000-2020 Sebastien Godard (sysstat <at> orange.fr)
--.TH MPSTAT 1 "AUGUST 2020" Linux "Linux User's Manual" -*- nroff -*-
++.TH MPSTAT 1 "OCTOBER 2022" Linux "Linux User's Manual" -*- nroff -*-
  .SH NAME
  mpstat \- Report processors related statistics.
  
  .SH SYNOPSIS
- .B mpstat [ -A ] [ --dec={ 0 | 1 | 2 } ] [ -n ] [ -u ] [ -T ] [ -V ] [ -I {
 -.B mpstat [ -A ] [ --dec={ 0 | 1 | 2 } ] [ -n ] [ -u ] [ -T ] [ -V ] [ -H ] [ -I {
++.B mpstat [ -A ] [ --dec={ 0 | 1 | 2 } ] [ -H ] [ -n ] [ -u ] [ -T ] [ -V ] [ -I {
  .IB "keyword" "[,...] | ALL } ] [ -N { " "node_list " "| ALL } ] [ -o JSON ] [ -P {"
  .IB "cpu_list " "| ALL } ] [ " "interval " "[ " "count " "] ]"
  
@@@ -44,6 -44,8 +44,9 @@@ unless these options are explicitly se
  .B --dec={ 0 | 1 | 2 }
  Specify the number of decimal places to use (0 to 2, default value is 2).
  .TP
 -Detect and Display stats of physically hotplugged vCPUs also
+ .B -H
++Also detect and display statistics for physically hotplugged vCPUs.
++.TP
  .BI "-I { " "keyword" "[,...] | ALL }"
  Report interrupts statistics.
  .RI "Possible " "keywords " "are"
diff --cc mpstat.c
index 103241003631ba25bfb37b6f39103c561669c0d3,8f7957d3dc0aa9baa2ce2001bf9bc8984cb0e8c9..ab478c56911fcbd552015b0e76c0239a4c39267c
+++ b/mpstat.c
@@@ -1,6 -1,7 +1,7 @@@
  /*
   * mpstat: per-processor statistics
   * (C) 2000-2022 by Sebastien GODARD (sysstat <at> orange.fr)
 - * Copyright (c) 2022, Oracle and/or its affiliates.
++ * Copyright (C) 2022 Oracle and/or its affiliates.
   *
   ***************************************************************************
   * This program is free software; you can redistribute it and/or modify it *
@@@ -49,25 -50,25 +50,25 @@@ char *sccsid(void) { return (SCCSID); 
  unsigned long long uptime_cs[3] = {0, 0, 0};
  
  /* NOTE: Use array of _char_ for bitmaps to avoid endianness problems...*/
--unsigned char *cpu_bitmap;    /* Bit 0: Global; Bit 1: 1st proc; etc. */
--unsigned char *node_bitmap;   /* Bit 0: Global; Bit 1: 1st NUMA node; etc. */
++unsigned char *cpu_bitmap = NULL;     /* Bit 0: Global; Bit 1: 1st proc; etc. */
++unsigned char *node_bitmap = NULL;    /* Bit 0: Global; Bit 1: 1st NUMA node; etc. */
  
  /* Structures used to save CPU and NUMA nodes CPU stats */
--struct stats_cpu *st_cpu[3];
--struct stats_cpu *st_node[3];
++struct stats_cpu *st_cpu[3] = {NULL, NULL, NULL};
++struct stats_cpu *st_node[3] = {NULL, NULL, NULL};
  
  /*
   * Structure used to save total number of interrupts received
   * among all CPU and for each CPU.
   */
--struct stats_global_irq *st_irq[3];
++struct stats_global_irq *st_irq[3] = {NULL, NULL, NULL};
  
  /*
   * Structures used to save, for each interrupt, the number
   * received by each CPU.
   */
--struct stats_irqcpu *st_irqcpu[3];
--struct stats_irqcpu *st_softirqcpu[3];
++struct stats_irqcpu *st_irqcpu[3] = {NULL, NULL, NULL};
++struct stats_irqcpu *st_softirqcpu[3] = {NULL, NULL, NULL};
  
  /*
   * Number of CPU per node, e.g.:
   * cpu_per_node[1]: nr of CPU for node 0
   * etc.
   */
--int *cpu_per_node;
++int *cpu_per_node = NULL;
  
  /*
   * Node number the CPU belongs to, e.g.:
   * cpu2node[0]: node nr for CPU 0
   */
--int *cpu2node;
++int *cpu2node = NULL;
  
  /* CPU topology */
--struct cpu_topology *st_cpu_topology;
++struct cpu_topology *st_cpu_topology = NULL;
  
  struct tm mp_tstamp[3];
  
@@@ -134,7 -135,7 +135,7 @@@ void usage(char *progname
                progname);
  
        fprintf(stderr, _("Options are:\n"
-                         "[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]\n"
 -                        "[ -A ] [ -n ] [ -T ] [ -u ] [ -V ] [ -H ]\n"
++                        "[ -A ] [ -H ] [ -n ] [ -T ] [ -u ] [ -V ]\n"
                          "[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]\n"
                          "[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]\n"));
        exit(1);
@@@ -175,64 -176,58 +176,61 @@@ void int_handler(int sig
   * IN:
   * @nr_cpus   Number of CPUs. This is the real number of available CPUs + 1
   *            because we also have to allocate a structure for CPU 'all'.
 - * @reset     reset the memory only when set to TRUE
++ * @reset     Reset the memory only when set to TRUE.
   ***************************************************************************
   */
- void salloc_mp_struct(int nr_cpus)
+ void salloc_mp_struct(int nr_cpus, int reset)
  {
        int i;
  
        for (i = 0; i < 3; i++) {
  
-               if ((st_cpu[i] = (struct stats_cpu *) malloc(STATS_CPU_SIZE * nr_cpus))
+               if ((st_cpu[i] = (struct stats_cpu *) realloc(st_cpu[i], STATS_CPU_SIZE * nr_cpus))
                    == NULL) {
-                       perror("malloc");
+                       perror("realloc");
                        exit(4);
                }
-               memset(st_cpu[i], 0, STATS_CPU_SIZE * nr_cpus);
  
-               if ((st_node[i] = (struct stats_cpu *) malloc(STATS_CPU_SIZE * nr_cpus))
+               if ((st_node[i] = (struct stats_cpu *) realloc(st_node[i], STATS_CPU_SIZE * nr_cpus))
                    == NULL) {
-                       perror("malloc");
+                       perror("realloc");
                        exit(4);
                }
-               memset(st_node[i], 0, STATS_CPU_SIZE * nr_cpus);
  
-               if ((st_irq[i] = (struct stats_global_irq *) malloc(STATS_GLOBAL_IRQ_SIZE * nr_cpus))
 -              if ((st_irq[i] = (struct stats_global_irq *) realloc(st_irq[i], STATS_GLOBAL_IRQ_SIZE * nr_cpus))
++              if ((st_irq[i] = (struct stats_global_irq *) realloc(st_irq[i],
++                                                                   STATS_GLOBAL_IRQ_SIZE * nr_cpus))
                    == NULL) {
-                       perror("malloc");
+                       perror("realloc");
                        exit(4);
                }
-               memset(st_irq[i], 0, STATS_GLOBAL_IRQ_SIZE * nr_cpus);
  
-               if ((st_irqcpu[i] = (struct stats_irqcpu *) malloc(STATS_IRQCPU_SIZE * nr_cpus * irqcpu_nr))
 -              if ((st_irqcpu[i] = (struct stats_irqcpu *) realloc(st_irqcpu[i], STATS_IRQCPU_SIZE * nr_cpus * irqcpu_nr))
++              if ((st_irqcpu[i] = (struct stats_irqcpu *) realloc(st_irqcpu[i],
++                                                                  STATS_IRQCPU_SIZE * nr_cpus * irqcpu_nr))
                    == NULL) {
-                       perror("malloc");
+                       perror("realloc");
                        exit(4);
                }
-               memset(st_irqcpu[i], 0, STATS_IRQCPU_SIZE * nr_cpus * irqcpu_nr);
  
-               if ((st_softirqcpu[i] = (struct stats_irqcpu *) malloc(STATS_IRQCPU_SIZE * nr_cpus * softirqcpu_nr))
 -              if ((st_softirqcpu[i] = (struct stats_irqcpu *) realloc(st_softirqcpu[i], STATS_IRQCPU_SIZE * nr_cpus * softirqcpu_nr))
++              if ((st_softirqcpu[i] = (struct stats_irqcpu *) realloc(st_softirqcpu[i],
++                                                                      STATS_IRQCPU_SIZE * nr_cpus * softirqcpu_nr))
                     == NULL) {
-                       perror("malloc");
+                       perror("realloc");
                        exit(4);
                }
-               memset(st_softirqcpu[i], 0, STATS_IRQCPU_SIZE * nr_cpus * softirqcpu_nr);
        }
  
-       if ((cpu_bitmap = (unsigned char *) malloc((nr_cpus >> 3) + 1)) == NULL) {
-               perror("malloc");
+       if ((cpu_bitmap = (unsigned char *) realloc(cpu_bitmap, (nr_cpus >> 3) + 1)) == NULL) {
+               perror("realloc");
                exit(4);
        }
-       memset(cpu_bitmap, 0, (nr_cpus >> 3) + 1);
  
-       if ((node_bitmap = (unsigned char *) malloc((nr_cpus >> 3) + 1)) == NULL) {
-               perror("malloc");
+       if ((node_bitmap = (unsigned char *) realloc(node_bitmap, (nr_cpus >> 3) + 1)) == NULL) {
+               perror("realloc");
                exit(4);
        }
-       memset(node_bitmap, 0, (nr_cpus >> 3) + 1);
  
-       if ((cpu_per_node = (int *) malloc(sizeof(int) * nr_cpus)) == NULL) {
-               perror("malloc");
+       if ((cpu_per_node = (int *) realloc(cpu_per_node, sizeof(int) * nr_cpus)) == NULL) {
+               perror("realloc");
                exit(4);
        }
  
                exit(4);
        }
  
-       if ((st_cpu_topology = (struct cpu_topology *) malloc(sizeof(struct cpu_topology) * nr_cpus)) == NULL) {
-               perror("malloc");
 -      if ((st_cpu_topology = (struct cpu_topology *) realloc(st_cpu_topology, sizeof(struct cpu_topology) * nr_cpus)) == NULL) {
++      if ((st_cpu_topology = (struct cpu_topology *) realloc(st_cpu_topology,
++                                                             sizeof(struct cpu_topology) * nr_cpus)) == NULL) {
+               perror("realloc");
                exit(4);
        }
+       if (reset == TRUE) {
+               for (i = 0; i < 3; i++) {
+                       memset(st_cpu[i], 0, STATS_CPU_SIZE * nr_cpus);
+                       memset(st_node[i], 0, STATS_CPU_SIZE * nr_cpus);
+                       memset(st_irq[i], 0, STATS_GLOBAL_IRQ_SIZE * nr_cpus);
+                       memset(st_irqcpu[i], 0, STATS_IRQCPU_SIZE * nr_cpus * irqcpu_nr);
+                       memset(st_softirqcpu[i], 0, STATS_IRQCPU_SIZE * nr_cpus * softirqcpu_nr);
+               }
+               memset(cpu_bitmap, 0, (nr_cpus >> 3) + 1);
+               memset(node_bitmap, 0, (nr_cpus >> 3) + 1);
+       }
  }
  
  /*
@@@ -1951,13 -1958,18 +1962,17 @@@ void read_interrupts_stat(char *file, s
   * IN:
   * @dis_hdr   Set to TRUE if the header line must always be printed.
   * @rows      Number of rows of screen.
 - * OUT:
 - * @new_cpu_nr        Return 0 as default.
 - *            Return new_cpu_nr (!=0) if physical vCPU hotplug occured.
+  *
++ * RETURNS:
++ * Total number of physical CPUs if a least one new (virtual) CPU has been
++ * hotplugged, and 0 otherwise.
   ***************************************************************************
   */
void rw_mpstat_loop(int dis_hdr, int rows)
int rw_mpstat_loop(int dis_hdr, int rows)
  {
        struct stats_cpu *scc;
--      int i;
++      int i, new_cpu_nr;
        int curr = 1, dis = 1;
 -      int new_cpu_nr = 0;
        unsigned long lines = rows;
  
        /* Read system uptime and CPU stats */
                                curr ^= 1;
                        }
                }
 -              /* -H option is given and vCPU physical hotplug occured */
 -              if (USE_OPTION_H(flags)) {
 -                      if (new_cpu_nr > cpu_nr) {
++              if (count && USE_OPTION_H(flags)) {
++                      /* Check if a vCPU has been physically hotplugged */
+                       new_cpu_nr = get_cpu_nr(~0, TRUE);
 -                      }
++                      if (new_cpu_nr > cpu_nr)
+                               return new_cpu_nr;
+               }
        }
        while (count);
  
        else {
                write_stats_avg(curr, dis_hdr);
        }
 - * Detect physical vCPU hotplug and call rw_mpstat_loop to display stats
+       return 0;
+ }
+ /*
+  ***************************************************************************
 -      int new_cpu_nr = 0;
++ * Start mpstat loop until end of count or when a vCPU has been physically
++ * hotplugged.
+  *
+  * IN:
+  * @dis_hdr   Set to TRUE if the header line must always be printed.
+  * @rows      Number of rows of screen.
+  ***************************************************************************
+  */
+ void mpstat_loop(int dis_hdr, int rows)
+ {
 -      while (1) {
++      int new_cpu_nr = 1;
 -              if (new_cpu_nr == 0) {
 -                      return;
 -              }
 -              else {
++      while (new_cpu_nr) {
+               /* Main loop for reading-writing stats */
+               new_cpu_nr = rw_mpstat_loop(dis_hdr, rows);
+               /* Handle vCPU physical hotplug */
 -                                      NR_IRQCPU_PREALLOC;
++              if (new_cpu_nr) {
+                       /* Update the highest processor number */
+                       cpu_nr = new_cpu_nr;
+                       /* Recalculate number of interrupts per processor */
+                       irqcpu_nr = get_irqcpu_nr(INTERRUPTS, NR_IRQS, cpu_nr) +
++                                  NR_IRQCPU_PREALLOC;
+                       /* Recalculate number of soft interrupts per processor */
+                       softirqcpu_nr = get_irqcpu_nr(SOFTIRQS, NR_IRQS, cpu_nr) +
+                                       NR_IRQCPU_PREALLOC;
+                       /*
+                        * Reallocate cpu stats structs :
+                        * global, proc0, proc1, ..., proc$(prev_cpu_nr-1).
+                        * global, proc0, proc1, ..., proc$(prev_cpu_nr-1), ..., proc$(cpu_nr-1).
+                        */
+                       salloc_mp_struct(cpu_nr + 1, FALSE);
+                       /* Get NUMA node placement */
+                       node_nr = get_node_placement(cpu_nr, cpu_per_node, cpu2node);
+               }
+       }
  }
  
  /*
@@@ -2270,6 -2336,6 +2336,11 @@@ int main(int argc, char **argv
                                        actset = TRUE;
                                        break;
  
++                              case 'H':
++                                      /* Display physically hotplugged vCPU */
++                                      flags |= F_OPTION_H;
++                                      break;
++
                                case 'n':
                                        /* Display CPU stats based on NUMA node placement */
                                        if (node_nr >= 0) {