Changeset dec16a2 in mainline for uspace/app/top/top.c


Ignore:
Timestamp:
2010-04-18T16:52:47Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5c45ca8
Parents:
e535eeb
Message:
  • sysinfo items "system.tasks" and "system.threads" now return complete statistics of all tasks and threads (statistics of individual tasks and threads can be still acquited from "system.tasks.#" and "system.threads.#")
  • update user space functions accordingly
  • cleanup top — it is fully functional again
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/top/top.c

    re535eeb rdec16a2  
    11/*
    22 * Copyright (c) 2010 Stanislav Kozina
     3 * Copyright (c) 2010 Martin Decky
    34 * All rights reserved.
    45 *
     
    3839#include <stdlib.h>
    3940#include <unistd.h>
    40 #include <uptime.h>
    4141#include <task.h>
    4242#include <thread.h>
    4343#include <sys/time.h>
    44 #include <load.h>
    45 #include <ps.h>
    4644#include <arch/barrier.h>
     45#include <errno.h>
    4746#include "screen.h"
    4847#include "input.h"
    4948#include "top.h"
    50 #include "ps.h"
    51 
    52 #define UPDATE_INTERVAL 1
    53 
    54 #define DAY 86400
    55 #define HOUR 3600
    56 #define MINUTE 60
     49
     50#define NAME  "top"
     51
     52#define UPDATE_INTERVAL  1
     53
     54#define DAY     86400
     55#define HOUR    3600
     56#define MINUTE  60
    5757
    5858int operation_type;
    5959
    60 static void read_data(data_t *target)
     60static const char *read_data(data_t *target)
    6161{
    62         /* Read current time */
     62        /* Initialize data */
     63        target->load = NULL;
     64        target->cpus = NULL;
     65        target->cpus_perc = NULL;
     66        target->tasks = NULL;
     67        target->tasks_perc = NULL;
     68        target->threads = NULL;
     69        target->physmem = NULL;
     70       
     71        /* Get current time */
    6372        struct timeval time;
    64         if (gettimeofday(&time, NULL) != 0) {
    65                 printf("Cannot get time of day!\n");
    66                 exit(1);
    67         }
     73        if (gettimeofday(&time, NULL) != EOK)
     74                return "Cannot get time of day";
     75       
    6876        target->hours = (time.tv_sec % DAY) / HOUR;
    6977        target->minutes = (time.tv_sec % HOUR) / MINUTE;
    7078        target->seconds = time.tv_sec % MINUTE;
    71 
    72         /* Read uptime */
    73         uint64_t uptime;
    74         get_uptime(&uptime);
    75         target->uptime_d = uptime / DAY;
    76         target->uptime_h = (uptime % DAY) / HOUR;
    77         target->uptime_m = (uptime % HOUR) / MINUTE;
    78         target->uptime_s = uptime % MINUTE;
    79 
    80         /* Read load */
    81         get_load(target->load);
    82 
    83         /* Read task ids */
    84         target->task_count = get_tasks(&target->taskinfos);
    85 
    86         /* Read all threads */
    87         target->thread_count = get_threads(&target->thread_infos);
    88 
    89         /* Read cpu infos */
    90         target->cpu_count = get_cpu_infos(&target->cpus);
    91 
    92         /* Read mem info */
    93         get_mem_info(&target->mem_info);
     79       
     80        /* Get uptime */
     81        sysarg_t uptime = stats_get_uptime();
     82        target->udays = uptime / DAY;
     83        target->uhours = (uptime % DAY) / HOUR;
     84        target->uminutes = (uptime % HOUR) / MINUTE;
     85        target->useconds = uptime % MINUTE;
     86       
     87        /* Get load */
     88        target->load = stats_get_load(&(target->load_count));
     89        if (target->load == NULL)
     90                return "Cannot get system load";
     91       
     92        /* Get CPUs */
     93        target->cpus = stats_get_cpus(&(target->cpus_count));
     94        if (target->cpus == NULL)
     95                return "Cannot get CPUs";
     96       
     97        target->cpus_perc =
     98            (perc_cpu_t *) calloc(target->cpus_count, sizeof(perc_cpu_t));
     99        if (target->cpus_perc == NULL)
     100                return "Not enough memory for CPU utilization";
     101       
     102        /* Get tasks */
     103        target->tasks = stats_get_tasks(&(target->tasks_count));
     104        if (target->tasks == NULL)
     105                return "Cannot get tasks";
     106       
     107        target->tasks_perc =
     108            (perc_task_t *) calloc(target->tasks_count, sizeof(perc_task_t));
     109        if (target->tasks_perc == NULL)
     110                return "Not enough memory for task utilization";
     111       
     112        /* Get threads */
     113        target->threads = stats_get_threads(&(target->threads_count));
     114        if (target->threads == NULL)
     115                return "Cannot get threads";
     116       
     117        /* Get physical memory */
     118        target->physmem = stats_get_physmem();
     119        if (target->physmem == NULL)
     120                return "Cannot get physical memory";
     121       
     122        return NULL;
    94123}
    95124
    96125/** Computes percentage differencies from old_data to new_data
    97126 *
    98  * @param old_data      Pointer to old data strucutre.
    99  * @param new_data      Pointer to actual data where percetages are stored.
    100  *
    101  */
    102 static void compute_percentages(data_t *old_data, data_t *new_data)
     127 * @param old_data Pointer to old data strucutre.
     128 * @param new_data Pointer to actual data where percetages are stored.
     129 *
     130 */
     131static const char *compute_percentages(data_t *old_data, data_t *new_data)
    103132{
    104         /* Foreach cpu, compute total ticks and divide it between user and
    105          * system */
    106         unsigned int i;
    107         new_data->cpu_perc = malloc(new_data->cpu_count * sizeof(cpu_perc_t));
    108         for (i = 0; i < new_data->cpu_count; ++i) {
    109                 uint64_t idle = new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks;
    110                 uint64_t busy = new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks;
     133        /* Allocate memory */
     134       
     135        uint64_t *ucycles_diff = calloc(new_data->tasks_count, sizeof(uint64_t));
     136        if (ucycles_diff == NULL)
     137                return "Not enough memory for user utilization";
     138       
     139        uint64_t *kcycles_diff = calloc(new_data->tasks_count, sizeof(uint64_t));
     140        if (kcycles_diff == NULL) {
     141                free(ucycles_diff);
     142                return "Not enough memory for kernel utilization";
     143        }
     144       
     145        /* For each CPU: Compute total ticks and divide it between
     146           user and kernel */
     147       
     148        size_t i;
     149        for (i = 0; i < new_data->cpus_count; i++) {
     150                uint64_t idle =
     151                    new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks;
     152                uint64_t busy =
     153                    new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks;
    111154                uint64_t sum = idle + busy;
    112                 FRACTION_TO_FLOAT(new_data->cpu_perc[i].idle, idle * 100, sum);
    113                 FRACTION_TO_FLOAT(new_data->cpu_perc[i].busy, busy * 100, sum);
    114         }
    115 
     155               
     156                FRACTION_TO_FLOAT(new_data->cpus_perc[i].idle, idle * 100, sum);
     157                FRACTION_TO_FLOAT(new_data->cpus_perc[i].busy, busy * 100, sum);
     158        }
     159       
    116160        /* For all tasks compute sum and differencies of all cycles */
    117         uint64_t mem_total = 1; /*< Must NOT be null! */
    118         uint64_t ucycles_total = 1; /*< Must NOT be null! */
    119         uint64_t kcycles_total = 1; /*< Must NOT be null! */
    120         uint64_t *ucycles_diff = malloc(new_data->task_count * sizeof(uint64_t));
    121         uint64_t *kcycles_diff = malloc(new_data->task_count * sizeof(uint64_t));
    122         unsigned int j = 0;
    123         for (i = 0; i < new_data->task_count; ++i) {
    124                 /* Jump over all death tasks */
    125                 while (old_data->taskinfos[j].taskid < new_data->taskinfos[i].taskid)
    126                         ++j;
    127                 if (old_data->taskinfos[j].taskid > new_data->taskinfos[i].taskid) {
     161       
     162        uint64_t virtmem_total = 1;  /* Must NOT be zero */
     163        uint64_t ucycles_total = 1;  /* Must NOT be zero */
     164        uint64_t kcycles_total = 1;  /* Must NOT be zero */
     165       
     166        for (i = 0; i < new_data->tasks_count; i++) {
     167                /* Match task with the previous instance */
     168               
     169                bool found = false;
     170                size_t j;
     171                for (j = 0; j < old_data->tasks_count; j++) {
     172                        if (new_data->tasks[i].task_id == old_data->tasks[j].task_id) {
     173                                found = true;
     174                                break;
     175                        }
     176                }
     177               
     178                if (!found) {
    128179                        /* This is newly borned task, ignore it */
    129180                        ucycles_diff[i] = 0;
     
    131182                        continue;
    132183                }
    133                 /* Now we now we have task with same id */
    134                 ucycles_diff[i] = new_data->taskinfos[i].ucycles - old_data->taskinfos[j].ucycles;
    135                 kcycles_diff[i] = new_data->taskinfos[i].kcycles - old_data->taskinfos[j].kcycles;
    136 
    137                 mem_total += new_data->taskinfos[i].virt_mem;
     184               
     185                ucycles_diff[i] =
     186                    new_data->tasks[i].ucycles - old_data->tasks[j].ucycles;
     187                kcycles_diff[i] =
     188                    new_data->tasks[i].kcycles - old_data->tasks[j].kcycles;
     189               
     190                virtmem_total += new_data->tasks[i].virtmem;
    138191                ucycles_total += ucycles_diff[i];
    139192                kcycles_total += kcycles_diff[i];
    140193        }
    141 
    142         /* And now compute percental change */
    143         new_data->task_perc = malloc(new_data->task_count * sizeof(task_perc_t));
    144         for (i = 0; i < new_data->task_count; ++i) {
    145                 FRACTION_TO_FLOAT(new_data->task_perc[i].mem, new_data->taskinfos[i].virt_mem * 100, mem_total);
    146                 FRACTION_TO_FLOAT(new_data->task_perc[i].ucycles, ucycles_diff[i] * 100, ucycles_total);
    147                 FRACTION_TO_FLOAT(new_data->task_perc[i].kcycles, kcycles_diff[i] * 100, kcycles_total);
    148         }
    149 
    150         /* Wait until coprocessor finishes its work */
    151         write_barrier();
    152 
    153         /* And free temporary structures */
     194       
     195        /* For each task: Compute percential change */
     196       
     197        for (i = 0; i < new_data->tasks_count; i++) {
     198                FRACTION_TO_FLOAT(new_data->tasks_perc[i].virtmem,
     199                    new_data->tasks[i].virtmem * 100, virtmem_total);
     200                FRACTION_TO_FLOAT(new_data->tasks_perc[i].ucycles,
     201                    ucycles_diff[i] * 100, ucycles_total);
     202                FRACTION_TO_FLOAT(new_data->tasks_perc[i].kcycles,
     203                    kcycles_diff[i] * 100, kcycles_total);
     204        }
     205       
     206        /* Cleanup */
     207       
    154208        free(ucycles_diff);
    155209        free(kcycles_diff);
     210       
     211        return NULL;
    156212}
    157213
    158214static void free_data(data_t *target)
    159215{
    160         free(target->taskinfos);
    161         free(target->thread_infos);
    162         free(target->cpus);
    163         free(target->cpu_perc);
    164         free(target->task_perc);
     216        if (target->load != NULL)
     217                free(target->load);
     218       
     219        if (target->cpus != NULL)
     220                free(target->cpus);
     221       
     222        if (target->cpus_perc != NULL)
     223                free(target->cpus_perc);
     224       
     225        if (target->tasks != NULL)
     226                free(target->tasks);
     227       
     228        if (target->tasks_perc != NULL)
     229                free(target->tasks_perc);
     230       
     231        if (target->threads != NULL)
     232                free(target->threads);
     233       
     234        if (target->physmem != NULL)
     235                free(target->physmem);
    165236}
    166 
    167 static inline void swap(data_t **first, data_t **second)
    168 {
    169         data_t *temp;
    170         temp = *first;
    171         *first = *second;
    172         *second = temp;
    173 }
    174 
    175 static data_t data[2];
    176237
    177238int main(int argc, char *argv[])
    178239{
    179         data_t *data1 = &data[0];
    180         data_t *data2 = &data[1];
     240        data_t data;
     241        data_t data_prev;
     242        const char *ret = NULL;
     243       
    181244        screen_init();
    182 
    183         /* Read initial stats */
    184245        printf("Reading initial data...\n");
    185         read_data(data1);
     246       
     247        if ((ret = read_data(&data_prev)) != NULL)
     248                goto out;
     249       
    186250        /* Compute some rubbish to have initialised values */
    187         compute_percentages(data1, data1);
    188 
    189         /* And paint screen until death... */
     251        if ((ret = compute_percentages(&data_prev, &data_prev)) != NULL)
     252                goto out;
     253       
     254        /* And paint screen until death */
    190255        operation_type = OP_TASKS;
    191256        while (true) {
    192257                char c = tgetchar(UPDATE_INTERVAL);
    193258                if (c < 0) {
    194                         read_data(data2);
    195                         compute_percentages(data1, data2);
    196                         free_data(data1);
    197                         print_data(data2);
    198                         swap(&data1, &data2);
     259                        if ((ret = read_data(&data)) != NULL) {
     260                                free_data(&data);
     261                                goto out;
     262                        }
     263                       
     264                        if ((ret = compute_percentages(&data_prev, &data)) != NULL) {
     265                                free_data(&data);
     266                                goto out;
     267                        }
     268                       
     269                        print_data(&data);
     270                        free_data(&data_prev);
     271                        data_prev = data;
     272                       
    199273                        continue;
    200274                }
     275               
    201276                switch (c) {
    202277                        case 'q':
    203                                 clear_screen();
    204                                 return 0;
     278                                goto out;
    205279                        case 'i':
    206                                 PRINT_WARNING("Showing IPC statistics", c);
     280                                print_warning("Showing IPC statistics");
    207281                                operation_type = OP_IPC;
    208282                                break;
    209283                        case 't':
    210                                 PRINT_WARNING("Showing task stats", c);
     284                                print_warning("Showing task statistics");
    211285                                operation_type = OP_TASKS;
    212286                                break;
    213287                        default:
    214                                 PRINT_WARNING("Unknown command: %c", c);
     288                                print_warning("Unknown command: %c", c);
    215289                                break;
    216290                }
    217 
    218         }
    219 
    220         free_data(data1);
    221         free_data(data2);
     291        }
     292       
     293out:
     294        screen_done();
     295        free_data(&data_prev);
     296       
     297        if (ret != NULL) {
     298                fprintf(stderr, "%s: %s\n", NAME, ret);
     299                return 1;
     300        }
     301       
    222302        return 0;
    223303}
Note: See TracChangeset for help on using the changeset viewer.