Changes in uspace/app/top/top.c [9e05055:172aad6] in mainline


Ignore:
File:
1 edited

Legend:

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

    r9e05055 r172aad6  
    4444#include <arch/barrier.h>
    4545#include <errno.h>
     46#include <sort.h>
    4647#include "screen.h"
    4748#include "input.h"
     
    5657#define MINUTE  60
    5758
    58 int operation_type;
     59op_mode_t op_mode = OP_TASKS;
     60sort_mode_t sort_mode = SORT_TASK_CYCLES;
     61bool excs_all = false;
    5962
    6063static const char *read_data(data_t *target)
     
    6669        target->tasks = NULL;
    6770        target->tasks_perc = NULL;
     71        target->tasks_map = NULL;
    6872        target->threads = NULL;
     73        target->exceptions = NULL;
     74        target->exceptions_perc = NULL;
    6975        target->physmem = NULL;
     76        target->ucycles_diff = NULL;
     77        target->kcycles_diff = NULL;
     78        target->ecycles_diff = NULL;
     79        target->ecount_diff = NULL;
    7080       
    7181        /* Get current time */
     
    110120                return "Not enough memory for task utilization";
    111121       
     122        target->tasks_map =
     123            (size_t *) calloc(target->tasks_count, sizeof(size_t));
     124        if (target->tasks_map == NULL)
     125                return "Not enough memory for task map";
     126       
    112127        /* Get threads */
    113128        target->threads = stats_get_threads(&(target->threads_count));
     
    115130                return "Cannot get threads";
    116131       
     132        /* Get Exceptions */
     133        target->exceptions = stats_get_exceptions(&(target->exceptions_count));
     134        if (target->exceptions == NULL)
     135                return "Cannot get exceptions";
     136       
     137        target->exceptions_perc =
     138            (perc_exc_t *) calloc(target->exceptions_count, sizeof(perc_exc_t));
     139        if (target->exceptions_perc == NULL)
     140                return "Not enough memory for exception utilization";
     141       
    117142        /* Get physical memory */
    118143        target->physmem = stats_get_physmem();
    119144        if (target->physmem == NULL)
    120145                return "Cannot get physical memory";
     146       
     147        target->ucycles_diff = calloc(target->tasks_count,
     148            sizeof(uint64_t));
     149        if (target->ucycles_diff == NULL)
     150                return "Not enough memory for user utilization";
     151       
     152        /* Allocate memory for computed values */
     153        target->kcycles_diff = calloc(target->tasks_count,
     154            sizeof(uint64_t));
     155        if (target->kcycles_diff == NULL)
     156                return "Not enough memory for kernel utilization";
     157       
     158        target->ecycles_diff = calloc(target->exceptions_count,
     159            sizeof(uint64_t));
     160        if (target->ecycles_diff == NULL)
     161                return "Not enough memory for exception cycles utilization";
     162       
     163        target->ecount_diff = calloc(target->exceptions_count,
     164            sizeof(uint64_t));
     165        if (target->ecount_diff == NULL)
     166                return "Not enough memory for exception count utilization";
    121167       
    122168        return NULL;
     
    129175 *
    130176 */
    131 static const char *compute_percentages(data_t *old_data, data_t *new_data)
    132 {
    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
     177static void compute_percentages(data_t *old_data, data_t *new_data)
     178{
     179        /* For each CPU: Compute total cycles and divide it between
    146180           user and kernel */
    147181       
     
    149183        for (i = 0; i < new_data->cpus_count; i++) {
    150184                uint64_t idle =
    151                     new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks;
     185                    new_data->cpus[i].idle_cycles - old_data->cpus[i].idle_cycles;
    152186                uint64_t busy =
    153                     new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks;
     187                    new_data->cpus[i].busy_cycles - old_data->cpus[i].busy_cycles;
    154188                uint64_t sum = idle + busy;
    155189               
     
    160194        /* For all tasks compute sum and differencies of all cycles */
    161195       
    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 */
     196        uint64_t virtmem_total = 0;
     197        uint64_t ucycles_total = 0;
     198        uint64_t kcycles_total = 0;
    165199       
    166200        for (i = 0; i < new_data->tasks_count; i++) {
     
    178212                if (!found) {
    179213                        /* This is newly borned task, ignore it */
    180                         ucycles_diff[i] = 0;
    181                         kcycles_diff[i] = 0;
     214                        new_data->ucycles_diff[i] = 0;
     215                        new_data->kcycles_diff[i] = 0;
    182216                        continue;
    183217                }
    184218               
    185                 ucycles_diff[i] =
     219                new_data->ucycles_diff[i] =
    186220                    new_data->tasks[i].ucycles - old_data->tasks[j].ucycles;
    187                 kcycles_diff[i] =
     221                new_data->kcycles_diff[i] =
    188222                    new_data->tasks[i].kcycles - old_data->tasks[j].kcycles;
    189223               
    190224                virtmem_total += new_data->tasks[i].virtmem;
    191                 ucycles_total += ucycles_diff[i];
    192                 kcycles_total += kcycles_diff[i];
    193         }
    194        
    195         /* For each task: Compute percential change */
     225                ucycles_total += new_data->ucycles_diff[i];
     226                kcycles_total += new_data->kcycles_diff[i];
     227        }
     228       
     229        /* For each task compute percential change */
    196230       
    197231        for (i = 0; i < new_data->tasks_count; i++) {
     
    199233                    new_data->tasks[i].virtmem * 100, virtmem_total);
    200234                FRACTION_TO_FLOAT(new_data->tasks_perc[i].ucycles,
    201                     ucycles_diff[i] * 100, ucycles_total);
     235                    new_data->ucycles_diff[i] * 100, ucycles_total);
    202236                FRACTION_TO_FLOAT(new_data->tasks_perc[i].kcycles,
    203                     kcycles_diff[i] * 100, kcycles_total);
    204         }
    205        
    206         /* Cleanup */
    207        
    208         free(ucycles_diff);
    209         free(kcycles_diff);
    210        
    211         return NULL;
     237                    new_data->kcycles_diff[i] * 100, kcycles_total);
     238        }
     239       
     240        /* For all exceptions compute sum and differencies of cycles */
     241       
     242        uint64_t ecycles_total = 0;
     243        uint64_t ecount_total = 0;
     244       
     245        for (i = 0; i < new_data->exceptions_count; i++) {
     246                /*
     247                 * March exception with the previous instance.
     248                 * This is quite paranoid since exceptions do not
     249                 * usually disappear, but it does not hurt.
     250                 */
     251               
     252                bool found = false;
     253                size_t j;
     254                for (j = 0; j < old_data->exceptions_count; j++) {
     255                        if (new_data->exceptions[i].id == old_data->exceptions[j].id) {
     256                                found = true;
     257                                break;
     258                        }
     259                }
     260               
     261                if (!found) {
     262                        /* This is a new exception, ignore it */
     263                        new_data->ecycles_diff[i] = 0;
     264                        new_data->ecount_diff[i] = 0;
     265                        continue;
     266                }
     267               
     268                new_data->ecycles_diff[i] =
     269                    new_data->exceptions[i].cycles - old_data->exceptions[j].cycles;
     270                new_data->ecount_diff[i] =
     271                    new_data->exceptions[i].count - old_data->exceptions[i].count;
     272               
     273                ecycles_total += new_data->ecycles_diff[i];
     274                ecount_total += new_data->ecount_diff[i];
     275        }
     276       
     277        /* For each exception compute percential change */
     278       
     279        for (i = 0; i < new_data->exceptions_count; i++) {
     280                FRACTION_TO_FLOAT(new_data->exceptions_perc[i].cycles,
     281                    new_data->ecycles_diff[i] * 100, ecycles_total);
     282                FRACTION_TO_FLOAT(new_data->exceptions_perc[i].count,
     283                    new_data->ecount_diff[i] * 100, ecount_total);
     284        }
     285}
     286
     287static int cmp_data(void *a, void *b, void *arg)
     288{
     289        size_t ia = *((size_t *) a);
     290        size_t ib = *((size_t *) b);
     291        data_t *data = (data_t *) arg;
     292       
     293        uint64_t acycles = data->ucycles_diff[ia] + data->kcycles_diff[ia];
     294        uint64_t bcycles = data->ucycles_diff[ib] + data->kcycles_diff[ib];
     295       
     296        if (acycles > bcycles)
     297                return -1;
     298       
     299        if (acycles < bcycles)
     300                return 1;
     301       
     302        return 0;
     303}
     304
     305static void sort_data(data_t *data)
     306{
     307        size_t i;
     308       
     309        for (i = 0; i < data->tasks_count; i++)
     310                data->tasks_map[i] = i;
     311       
     312        qsort((void *) data->tasks_map, data->tasks_count,
     313            sizeof(size_t), cmp_data, (void *) data);
    212314}
    213315
     
    232334                free(target->threads);
    233335       
     336        if (target->exceptions != NULL)
     337                free(target->exceptions);
     338       
     339        if (target->exceptions_perc != NULL)
     340                free(target->exceptions_perc);
     341       
    234342        if (target->physmem != NULL)
    235343                free(target->physmem);
     344       
     345        if (target->ucycles_diff != NULL)
     346                free(target->ucycles_diff);
     347       
     348        if (target->kcycles_diff != NULL)
     349                free(target->kcycles_diff);
     350       
     351        if (target->ecycles_diff != NULL)
     352                free(target->ecycles_diff);
     353       
     354        if (target->ecount_diff != NULL)
     355                free(target->ecount_diff);
    236356}
    237357
     
    249369       
    250370        /* Compute some rubbish to have initialised values */
    251         if ((ret = compute_percentages(&data_prev, &data_prev)) != NULL)
    252                 goto out;
     371        compute_percentages(&data_prev, &data_prev);
    253372       
    254373        /* And paint screen until death */
    255         operation_type = OP_TASKS;
    256374        while (true) {
    257375                int c = tgetchar(UPDATE_INTERVAL);
     
    262380                        }
    263381                       
    264                         if ((ret = compute_percentages(&data_prev, &data)) != NULL) {
    265                                 free_data(&data);
    266                                 goto out;
    267                         }
    268                        
     382                        compute_percentages(&data_prev, &data);
     383                        sort_data(&data);
    269384                        print_data(&data);
    270385                        free_data(&data_prev);
     
    275390               
    276391                switch (c) {
     392                        case 't':
     393                                print_warning("Showing task statistics");
     394                                op_mode = OP_TASKS;
     395                                break;
     396                        case 'i':
     397                                print_warning("Showing IPC statistics");
     398                                op_mode = OP_IPC;
     399                                break;
     400                        case 'e':
     401                                print_warning("Showing exception statistics");
     402                                op_mode = OP_EXCS;
     403                                break;
     404                        case 'h':
     405                                print_warning("Showing help");
     406                                op_mode = OP_HELP;
     407                                break;
    277408                        case 'q':
    278409                                goto out;
    279                         case 'i':
    280                                 print_warning("Showing IPC statistics");
    281                                 operation_type = OP_IPC;
    282                                 break;
    283                         case 't':
    284                                 print_warning("Showing task statistics");
    285                                 operation_type = OP_TASKS;
    286                                 break;
     410                        case 'a':
     411                                if (op_mode == OP_EXCS) {
     412                                        excs_all = !excs_all;
     413                                        if (excs_all)
     414                                                print_warning("Showing all exceptions");
     415                                        else
     416                                                print_warning("Showing only hot exceptions");
     417                                        break;
     418                                }
    287419                        default:
    288                                 print_warning("Unknown command: %c", c);
     420                                print_warning("Unknown command \"%c\", use \"h\" for help", c);
    289421                                break;
    290422                }
Note: See TracChangeset for help on using the changeset viewer.