Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/procps/iostat.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/procps/iostat.c

    r2725 r3232  
    88 */
    99
    10 //applet:IF_IOSTAT(APPLET(iostat, _BB_DIR_BIN, _BB_SUID_DROP))
    11 
    12 //kbuild:lib-$(CONFIG_IOSTAT) += iostat.o
    13 
    1410//config:config IOSTAT
    1511//config:   bool "iostat"
     
    1814//config:     Report CPU and I/O statistics
    1915
     16//applet:IF_IOSTAT(APPLET(iostat, BB_DIR_BIN, BB_SUID_DROP))
     17
     18//kbuild:lib-$(CONFIG_IOSTAT) += iostat.o
     19
    2020#include "libbb.h"
    21 #include <sys/utsname.h>  /* Need struct utsname */
     21#include <sys/utsname.h>  /* struct utsname */
    2222
    2323//#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
     
    2525
    2626#define MAX_DEVICE_NAME 12
    27 #define CURRENT          0
    28 #define LAST             1
     27#define MAX_DEVICE_NAME_STR "12"
    2928
    3029#if 1
     
    4039#endif
    4140
    42 struct stats_cpu {
    43     cputime_t cpu_user;
    44     cputime_t cpu_nice;
    45     cputime_t cpu_system;
    46     cputime_t cpu_idle;
    47     cputime_t cpu_iowait;
    48     cputime_t cpu_steal;
    49     cputime_t cpu_irq;
    50     cputime_t cpu_softirq;
    51     cputime_t cpu_guest;
     41enum {
     42    STATS_CPU_USER,
     43    STATS_CPU_NICE,
     44    STATS_CPU_SYSTEM,
     45    STATS_CPU_IDLE,
     46    STATS_CPU_IOWAIT,
     47    STATS_CPU_IRQ,
     48    STATS_CPU_SOFTIRQ,
     49    STATS_CPU_STEAL,
     50    STATS_CPU_GUEST,
     51
     52    GLOBAL_UPTIME,
     53    SMP_UPTIME,
     54
     55    N_STATS_CPU,
    5256};
    5357
    54 struct stats_dev {
    55     char dname[MAX_DEVICE_NAME];
     58typedef struct {
     59    cputime_t vector[N_STATS_CPU];
     60} stats_cpu_t;
     61
     62typedef struct {
     63    stats_cpu_t *prev;
     64    stats_cpu_t *curr;
     65    cputime_t itv;
     66} stats_cpu_pair_t;
     67
     68typedef struct {
    5669    unsigned long long rd_sectors;
    5770    unsigned long long wr_sectors;
    5871    unsigned long rd_ops;
    5972    unsigned long wr_ops;
    60 };
    61 
    62 /* List of devices entered on the command line */
    63 struct device_list {
    64     char dname[MAX_DEVICE_NAME];
    65 };
     73} stats_dev_data_t;
     74
     75typedef struct stats_dev {
     76    struct stats_dev *next;
     77    char dname[MAX_DEVICE_NAME + 1];
     78    stats_dev_data_t prev_data;
     79    stats_dev_data_t curr_data;
     80} stats_dev_t;
    6681
    6782/* Globals. Sort by size and access frequency. */
    6883struct globals {
    6984    smallint show_all;
    70     unsigned devlist_i;             /* Index to the list of devices */
    7185    unsigned total_cpus;            /* Number of CPUs */
    7286    unsigned clk_tck;               /* Number of clock ticks per second */
    73     struct device_list *dlist;
    74     struct stats_dev *saved_stats_dev;
     87    llist_t *dev_name_list;         /* List of devices entered on the command line */
     88    stats_dev_t *stats_dev_list;
    7589    struct tm tmtime;
     90    struct {
     91        const char *str;
     92        unsigned div;
     93    } unit;
    7694};
    7795#define G (*ptr_to_globals)
    7896#define INIT_G() do { \
    7997    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     98    G.unit.str = "Blk"; \
     99    G.unit.div = 1; \
    80100} while (0)
    81101
     
    102122static void print_header(void)
    103123{
    104     char buf[16];
     124    char buf[32];
    105125    struct utsname uts;
    106126
    107     if (uname(&uts) < 0)
    108         bb_perror_msg_and_die("uname");
    109 
     127    uname(&uts); /* never fails */
     128
     129    /* Date representation for the current locale */
    110130    strftime(buf, sizeof(buf), "%x", &G.tmtime);
    111131
    112     printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n\n",
     132    printf("%s %s (%s) \t%s \t_%s_\t(%u CPU)\n\n",
    113133            uts.sysname, uts.release, uts.nodename,
    114134            buf, uts.machine, G.total_cpus);
     
    124144static void print_timestamp(void)
    125145{
    126     char buf[20];
     146    char buf[64];
     147    /* %x: date representation for the current locale */
     148    /* %X: time representation for the current locale */
    127149    strftime(buf, sizeof(buf), "%x %X", &G.tmtime);
    128150    printf("%s\n", buf);
    129151}
    130152
     153static cputime_t get_smp_uptime(void)
     154{
     155    FILE *fp;
     156    unsigned long sec, dec;
     157
     158    fp = xfopen_for_read("/proc/uptime");
     159
     160    if (fscanf(fp, "%lu.%lu", &sec, &dec) != 2)
     161        bb_error_msg_and_die("can't read '%s'", "/proc/uptime");
     162
     163    fclose(fp);
     164
     165    return (cputime_t)sec * G.clk_tck + dec * G.clk_tck / 100;
     166}
     167
    131168/* Fetch CPU statistics from /proc/stat */
    132 static void get_cpu_statistics(struct stats_cpu *sc)
     169static void get_cpu_statistics(stats_cpu_t *sc)
    133170{
    134171    FILE *fp;
     
    140177
    141178    while (fgets(buf, sizeof(buf), fp)) {
    142         /* Does the line starts with "cpu "? */
    143         if (starts_with_cpu(buf) && buf[3] == ' ') {
    144             sscanf(buf + 4 + 1,
    145                 "%"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"
    146                 FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u",
    147                 &sc->cpu_user, &sc->cpu_nice, &sc->cpu_system,
    148                 &sc->cpu_idle, &sc->cpu_iowait, &sc->cpu_irq,
    149                 &sc->cpu_softirq, &sc->cpu_steal, &sc->cpu_guest);
    150         }
     179        int i;
     180        char *ibuf;
     181
     182        /* Does the line start with "cpu "? */
     183        if (!starts_with_cpu(buf) || buf[3] != ' ') {
     184            continue;
     185        }
     186        ibuf = buf + 4;
     187        for (i = STATS_CPU_USER; i <= STATS_CPU_GUEST; i++) {
     188            ibuf = skip_whitespace(ibuf);
     189            sscanf(ibuf, "%"FMT_DATA"u", &sc->vector[i]);
     190            if (i != STATS_CPU_GUEST) {
     191                sc->vector[GLOBAL_UPTIME] += sc->vector[i];
     192            }
     193            ibuf = skip_non_whitespace(ibuf);
     194        }
     195        break;
     196    }
     197
     198    if (this_is_smp()) {
     199        sc->vector[SMP_UPTIME] = get_smp_uptime();
    151200    }
    152201
    153202    fclose(fp);
    154 }
    155 
    156 static cputime_t get_smp_uptime(void)
    157 {
    158     FILE *fp;
    159     char buf[sizeof(long)*3 * 2 + 4];
    160     unsigned long sec, dec;
    161 
    162     fp = xfopen_for_read("/proc/uptime");
    163 
    164     if (fgets(buf, sizeof(buf), fp))
    165         if (sscanf(buf, "%lu.%lu", &sec, &dec) != 2)
    166             bb_error_msg_and_die("can't read /proc/uptime");
    167 
    168     fclose(fp);
    169 
    170     return (cputime_t)sec * G.clk_tck + dec * G.clk_tck / 100;
    171 }
    172 
    173 /*
    174  * Obtain current uptime in jiffies.
    175  * Uptime is sum of individual CPUs' uptimes.
    176  */
    177 static cputime_t get_uptime(const struct stats_cpu *sc)
    178 {
    179     /* NB: Don't include cpu_guest, it is already in cpu_user */
    180     return sc->cpu_user + sc->cpu_nice + sc->cpu_system + sc->cpu_idle +
    181         + sc->cpu_iowait + sc->cpu_irq + sc->cpu_steal + sc->cpu_softirq;
    182203}
    183204
     
    220241}
    221242
    222 static void print_stats_cpu_struct(const struct stats_cpu *p,
    223         const struct stats_cpu *c, cputime_t itv)
    224 {
    225     printf("         %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f\n",
    226         percent_value(p->cpu_user   , c->cpu_user   , itv),
    227         percent_value(p->cpu_nice   , c->cpu_nice   , itv),
    228         percent_value(p->cpu_system + p->cpu_softirq + p->cpu_irq,
    229             c->cpu_system + c->cpu_softirq + c->cpu_irq, itv),
    230         percent_value(p->cpu_iowait , c->cpu_iowait , itv),
    231         percent_value(p->cpu_steal  , c->cpu_steal  , itv),
    232         percent_value(p->cpu_idle   , c->cpu_idle   , itv)
     243static void print_stats_cpu_struct(stats_cpu_pair_t *stats)
     244{
     245    cputime_t *p = stats->prev->vector;
     246    cputime_t *c = stats->curr->vector;
     247    printf("        %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",
     248        percent_value(p[STATS_CPU_USER]  , c[STATS_CPU_USER]  , stats->itv),
     249        percent_value(p[STATS_CPU_NICE]  , c[STATS_CPU_NICE]  , stats->itv),
     250        percent_value(p[STATS_CPU_SYSTEM] + p[STATS_CPU_SOFTIRQ] + p[STATS_CPU_IRQ],
     251            c[STATS_CPU_SYSTEM] + c[STATS_CPU_SOFTIRQ] + c[STATS_CPU_IRQ], stats->itv),
     252        percent_value(p[STATS_CPU_IOWAIT], c[STATS_CPU_IOWAIT], stats->itv),
     253        percent_value(p[STATS_CPU_STEAL] , c[STATS_CPU_STEAL] , stats->itv),
     254        percent_value(p[STATS_CPU_IDLE]  , c[STATS_CPU_IDLE]  , stats->itv)
    233255    );
    234256}
    235257
    236 static void print_stats_dev_struct(const struct stats_dev *p,
    237         const struct stats_dev *c, cputime_t itv)
    238 {
    239     int unit = 1;
    240 
    241     if (option_mask32 & OPT_k)
    242         unit = 2;
    243     else if (option_mask32 & OPT_m)
    244         unit = 2048;
    245 
     258static void cpu_report(stats_cpu_pair_t *stats)
     259{
     260    /* Always print a header */
     261    puts("avg-cpu:  %user   %nice %system %iowait  %steal   %idle");
     262
     263    /* Print current statistics */
     264    print_stats_cpu_struct(stats);
     265}
     266
     267static void print_stats_dev_struct(stats_dev_t *stats_dev, cputime_t itv)
     268{
     269    stats_dev_data_t *p = &stats_dev->prev_data;
     270    stats_dev_data_t *c = &stats_dev->curr_data;
    246271    if (option_mask32 & OPT_z)
    247272        if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops)
    248273            return;
    249274
    250     printf("%-13s", c->dname);
    251     printf(" %8.2f %12.2f %12.2f %10llu %10llu \n",
    252         percent_value(p->rd_ops + p->wr_ops ,
    253         /**/          c->rd_ops + c->wr_ops , itv),
    254         percent_value(p->rd_sectors, c->rd_sectors, itv) / unit,
    255         percent_value(p->wr_sectors, c->wr_sectors, itv) / unit,
    256         (c->rd_sectors - p->rd_sectors) / unit,
    257         (c->wr_sectors - p->wr_sectors) / unit);
    258 }
    259 
    260 static void cpu_report(const struct stats_cpu *last,
    261         const struct stats_cpu *cur,
    262         cputime_t itv)
    263 {
    264     /* Always print a header */
    265     puts("avg-cpu:  %user   %nice %system %iowait  %steal   %idle");
    266 
    267     /* Print current statistics */
    268     print_stats_cpu_struct(last, cur, itv);
     275    printf("%-13s %8.2f %12.2f %12.2f %10llu %10llu\n",
     276        stats_dev->dname,
     277        percent_value(p->rd_ops + p->wr_ops, c->rd_ops + c->wr_ops, itv),
     278        percent_value(p->rd_sectors, c->rd_sectors, itv) / G.unit.div,
     279        percent_value(p->wr_sectors, c->wr_sectors, itv) / G.unit.div,
     280        (c->rd_sectors - p->rd_sectors) / G.unit.div,
     281        (c->wr_sectors - p->wr_sectors) / G.unit.div
     282    );
    269283}
    270284
    271285static void print_devstat_header(void)
    272286{
    273     printf("Device:            tps");
    274 
    275     if (option_mask32 & OPT_m)
    276         puts("    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn");
    277     else if (option_mask32 & OPT_k)
    278         puts("    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn");
    279     else
    280         puts("   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn");
     287    printf("Device:%15s%6s%s/s%6s%s/s%6s%s%6s%s\n",
     288        "tps",
     289        G.unit.str, "_read", G.unit.str, "_wrtn",
     290        G.unit.str, "_read", G.unit.str, "_wrtn"
     291    );
    281292}
    282293
     
    290301}
    291302
    292 /*
    293  * Return number of numbers on cmdline.
    294  * Reasonable values are only 0 (no interval/count specified),
    295  * 1 (interval specified) and 2 (both interval and count specified)
    296  */
    297 static int numbers_on_cmdline(int argc, char *argv[])
    298 {
    299     int sum = 0;
    300 
    301     if (isdigit(argv[argc-1][0]))
    302         sum++;
    303     if (argc > 2 && isdigit(argv[argc-2][0]))
    304         sum++;
    305 
    306     return sum;
    307 }
    308 
    309 static int is_dev_in_dlist(const char *dev)
    310 {
    311     int i;
    312 
    313     /* Go through the device list */
    314     for (i = 0; i < G.devlist_i; i++)
    315         if (strcmp(G.dlist[i].dname, dev) == 0)
    316             /* Found a match */
    317             return 1;
    318 
    319     /* No match found */
    320     return 0;
     303static stats_dev_t *stats_dev_find_or_new(const char *dev_name)
     304{
     305    stats_dev_t **curr = &G.stats_dev_list;
     306
     307    while (*curr != NULL) {
     308        if (strcmp((*curr)->dname, dev_name) == 0)
     309            return *curr;
     310        curr = &(*curr)->next;
     311    }
     312
     313    *curr = xzalloc(sizeof(stats_dev_t));
     314    strncpy((*curr)->dname, dev_name, MAX_DEVICE_NAME);
     315    return *curr;
     316}
     317
     318static void stats_dev_free(stats_dev_t *stats_dev)
     319{
     320    if (stats_dev) {
     321        stats_dev_free(stats_dev->next);
     322        free(stats_dev);
     323    }
    321324}
    322325
    323326static void do_disk_statistics(cputime_t itv)
    324327{
     328    char buf[128];
     329    char dev_name[MAX_DEVICE_NAME + 1];
     330    unsigned long long rd_sec_or_dummy;
     331    unsigned long long wr_sec_or_dummy;
     332    stats_dev_data_t *curr_data;
     333    stats_dev_t *stats_dev;
    325334    FILE *fp;
    326335    int rc;
    327     int i = 0;
    328     char buf[128];
    329     unsigned major, minor;
    330     unsigned long wr_ops, dummy; /* %*lu for suppress the conversion wouldn't work */
    331     unsigned long long rd_sec_or_wr_ops;
    332     unsigned long long rd_sec_or_dummy, wr_sec_or_dummy, wr_sec;
    333     struct stats_dev sd;
    334336
    335337    fp = xfopen_for_read("/proc/diskstats");
    336 
    337338    /* Read and possibly print stats from /proc/diskstats */
    338339    while (fgets(buf, sizeof(buf), fp)) {
    339         rc = sscanf(buf, "%u %u %s %lu %llu %llu %llu %lu %lu %llu %lu %lu %lu %lu",
    340             &major, &minor, sd.dname, &sd.rd_ops,
    341             &rd_sec_or_dummy, &rd_sec_or_wr_ops, &wr_sec_or_dummy,
    342             &wr_ops, &dummy, &wr_sec, &dummy, &dummy, &dummy, &dummy);
    343 
    344         switch (rc) {
    345         case 14:
    346             sd.wr_ops = wr_ops;
    347             sd.rd_sectors = rd_sec_or_wr_ops;
    348             sd.wr_sectors = wr_sec;
    349             break;
    350         case 7:
    351             sd.rd_sectors = rd_sec_or_dummy;
    352             sd.wr_ops = (unsigned long)rd_sec_or_wr_ops;
    353             sd.wr_sectors = wr_sec_or_dummy;
    354             break;
    355         default:
    356             break;
    357         }
    358 
    359         if (!G.devlist_i && !is_partition(sd.dname)) {
    360             /* User didn't specify device */
    361             if (!G.show_all && !sd.rd_ops && !sd.wr_ops) {
    362                 /* Don't print unused device */
     340        sscanf(buf, "%*s %*s %"MAX_DEVICE_NAME_STR"s", dev_name);
     341        if (G.dev_name_list) {
     342            /* Is device name in list? */
     343            if (!llist_find_str(G.dev_name_list, dev_name))
    363344                continue;
    364             }
    365             print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv);
    366             G.saved_stats_dev[i] = sd;
    367             i++;
    368         } else {
    369             /* Is device in device list? */
    370             if (is_dev_in_dlist(sd.dname)) {
    371                 /* Print current statistics */
    372                 print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv);
    373                 G.saved_stats_dev[i] = sd;
    374                 i++;
    375             } else
    376                 continue;
    377         }
     345        } else if (is_partition(dev_name)) {
     346            continue;
     347        }
     348
     349        stats_dev = stats_dev_find_or_new(dev_name);
     350        curr_data = &stats_dev->curr_data;
     351
     352        rc = sscanf(buf, "%*s %*s %*s %lu %llu %llu %llu %lu %*s %llu",
     353            &curr_data->rd_ops,
     354            &rd_sec_or_dummy,
     355            &curr_data->rd_sectors,
     356            &wr_sec_or_dummy,
     357            &curr_data->wr_ops,
     358            &curr_data->wr_sectors);
     359        if (rc != 6) {
     360            curr_data->rd_sectors = rd_sec_or_dummy;
     361            curr_data->wr_sectors = wr_sec_or_dummy;
     362            //curr_data->rd_ops = ;
     363            curr_data->wr_ops = (unsigned long)curr_data->rd_sectors;
     364        }
     365
     366        if (!G.dev_name_list /* User didn't specify device */
     367         && !G.show_all
     368         && curr_data->rd_ops == 0
     369         && curr_data->wr_ops == 0
     370        ) {
     371            /* Don't print unused device */
     372            continue;
     373        }
     374
     375        /* Print current statistics */
     376        print_stats_dev_struct(stats_dev, itv);
     377        stats_dev->prev_data = *curr_data;
    378378    }
    379379
     
    388388    /* Fetch current disk statistics */
    389389    do_disk_statistics(itv);
    390 }
    391 
    392 static void save_to_devlist(const char *dname)
    393 {
    394     int i;
    395     struct device_list *tmp = G.dlist;
    396 
    397     if (strncmp(dname, "/dev/", 5) == 0)
    398         /* We'll ignore prefix '/dev/' */
    399         dname += 5;
    400 
    401     /* Go through the list */
    402     for (i = 0; i < G.devlist_i; i++, tmp++)
    403         if (strcmp(tmp->dname, dname) == 0)
    404             /* Already in the list */
    405             return;
    406 
    407     /* Add device name to the list */
    408     strncpy(tmp->dname, dname, MAX_DEVICE_NAME - 1);
    409 
    410     /* Update device list index */
    411     G.devlist_i++;
    412 }
    413 
    414 static unsigned get_number_of_devices(void)
    415 {
    416     FILE *fp;
    417     char buf[128];
    418     int rv;
    419     unsigned n = 0;
    420     unsigned long rd_ops, wr_ops;
    421     char dname[MAX_DEVICE_NAME];
    422 
    423     fp = xfopen_for_read("/proc/diskstats");
    424 
    425     while (fgets(buf, sizeof(buf), fp)) {
    426         rv = sscanf(buf, "%*d %*d %s %lu %*u %*u %*u %lu",
    427                 dname, &rd_ops, &wr_ops);
    428         if (rv == 2 || is_partition(dname))
    429             /* A partition */
    430             continue;
    431         if (!rd_ops && !wr_ops) {
    432             /* Unused device */
    433             if (!G.show_all)
    434                 continue;
    435         }
    436         n++;
    437     }
    438 
    439     fclose(fp);
    440     return n;
    441 }
    442 
    443 static int number_of_ALL_on_cmdline(char **argv)
    444 {
    445     int alls = 0;
    446 
    447     /* Iterate over cmd line arguments, count "ALL" */
    448     while (*argv)
    449         if (strcmp(*argv++, "ALL") == 0)
    450             alls++;
    451 
    452     return alls;
    453390}
    454391
     
    457394//usage:#define iostat_full_usage "\n\n"
    458395//usage:       "Report CPU and I/O statistics\n"
    459 //usage:     "\nOptions:"
    460396//usage:     "\n    -c  Show CPU utilization"
    461397//usage:     "\n    -d  Show device utilization"
     
    466402
    467403int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    468 int iostat_main(int argc, char **argv)
    469 {
    470     int opt, dev_num;
    471     unsigned interval = 0;
     404int iostat_main(int argc UNUSED_PARAM, char **argv)
     405{
     406    int opt;
     407    unsigned interval;
    472408    int count;
    473     cputime_t global_uptime[2] = { 0 };
    474     cputime_t smp_uptime[2] = { 0 };
    475     cputime_t itv;
    476     struct stats_cpu stats_cur, stats_last;
     409    stats_cpu_t stats_data[2];
     410    smallint current_stats;
    477411
    478412    INIT_G();
    479413
    480     memset(&stats_last, 0, sizeof(stats_last));
     414    memset(&stats_data, 0, sizeof(stats_data));
    481415
    482416    /* Get number of clock ticks per sec */
     
    497431
    498432    argv += optind;
    499     argc -= optind;
    500 
    501     dev_num = argc - numbers_on_cmdline(argc, argv);
    502     /* We don't want to allocate space for 'ALL' */
    503     dev_num -= number_of_ALL_on_cmdline(argv);
    504     if (dev_num > 0)
    505         /* Make space for device list */
    506         G.dlist = xzalloc(sizeof(G.dlist[0]) * dev_num);
    507433
    508434    /* Store device names into device list */
    509435    while (*argv && !isdigit(*argv[0])) {
    510         if (strcmp(*argv, "ALL") != 0)
     436        if (strcmp(*argv, "ALL") != 0) {
    511437            /* If not ALL, save device name */
    512             save_to_devlist(*argv);
    513         else
     438            char *dev_name = skip_dev_pfx(*argv);
     439            if (!llist_find_str(G.dev_name_list, dev_name)) {
     440                llist_add_to(&G.dev_name_list, dev_name);
     441            }
     442        } else {
    514443            G.show_all = 1;
     444        }
    515445        argv++;
    516446    }
    517447
     448    interval = 0;
    518449    count = 1;
    519450    if (*argv) {
     
    527458    }
    528459
    529     /* Allocate space for device stats */
    530     if (opt & OPT_d) {
    531         G.saved_stats_dev = xzalloc(sizeof(G.saved_stats_dev[0]) *
    532                 (dev_num ? dev_num : get_number_of_devices())
    533         );
    534     }
     460    if (opt & OPT_m) {
     461        G.unit.str = " MB";
     462        G.unit.div = 2048;
     463    }
     464
     465    if (opt & OPT_k) {
     466        G.unit.str = " kB";
     467        G.unit.div = 2;
     468    }
     469
     470    get_localtime(&G.tmtime);
    535471
    536472    /* Display header */
    537473    print_header();
    538474
     475    current_stats = 0;
    539476    /* Main loop */
    540477    for (;;) {
     478        stats_cpu_pair_t stats;
     479
     480        stats.prev = &stats_data[current_stats ^ 1];
     481        stats.curr = &stats_data[current_stats];
     482
    541483        /* Fill the time structure */
    542484        get_localtime(&G.tmtime);
    543485
    544486        /* Fetch current CPU statistics */
    545         get_cpu_statistics(&stats_cur);
    546 
    547         /* Fetch current uptime */
    548         global_uptime[CURRENT] = get_uptime(&stats_cur);
     487        get_cpu_statistics(stats.curr);
    549488
    550489        /* Get interval */
    551         itv = get_interval(global_uptime[LAST], global_uptime[CURRENT]);
     490        stats.itv = get_interval(
     491            stats.prev->vector[GLOBAL_UPTIME],
     492            stats.curr->vector[GLOBAL_UPTIME]
     493        );
    552494
    553495        if (opt & OPT_t)
     
    555497
    556498        if (opt & OPT_c) {
    557             cpu_report(&stats_last, &stats_cur, itv);
     499            cpu_report(&stats);
    558500            if (opt & OPT_d)
    559501                /* Separate outputs by a newline */
     
    563505        if (opt & OPT_d) {
    564506            if (this_is_smp()) {
    565                 smp_uptime[CURRENT] = get_smp_uptime();
    566                 itv = get_interval(smp_uptime[LAST], smp_uptime[CURRENT]);
    567                 smp_uptime[LAST] = smp_uptime[CURRENT];
     507                stats.itv = get_interval(
     508                    stats.prev->vector[SMP_UPTIME],
     509                    stats.curr->vector[SMP_UPTIME]
     510                );
    568511            }
    569             dev_report(itv);
    570         }
     512            dev_report(stats.itv);
     513        }
     514
     515        bb_putchar('\n');
    571516
    572517        if (count > 0) {
     
    575520        }
    576521
    577         /* Backup current stats */
    578         global_uptime[LAST] = global_uptime[CURRENT];
    579         stats_last = stats_cur;
    580 
    581         bb_putchar('\n');
     522        /* Swap stats */
     523        current_stats ^= 1;
     524
    582525        sleep(interval);
    583526    }
    584527
    585     bb_putchar('\n');
    586 
    587528    if (ENABLE_FEATURE_CLEAN_UP) {
     529        llist_free(G.dev_name_list, NULL);
     530        stats_dev_free(G.stats_dev_list);
    588531        free(&G);
    589         free(G.dlist);
    590         free(G.saved_stats_dev);
    591532    }
    592533
Note: See TracChangeset for help on using the changeset viewer.