Changes in / [f76696f:1db6dfd] in mainline


Ignore:
Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/tester/print/print1.c

    rf76696f r1db6dfd  
    4242       
    4343        TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n");
    44         TPRINTF("Expected output: \"    text\"\n");
     44        TPRINTF("Expected output: \"text\"\n");
    4545        TPRINTF("Real output:     \"%8.10s\"\n\n", "text");
    4646       
     
    4949        TPRINTF("Real output:     \"%8.10s\"\n\n", "very long text");
    5050       
    51         TPRINTF("Testing printf(\"%%-*.*s\", 7, 7, \"text\"):\n");
    52         TPRINTF("Expected output: \"text   \"\n");
    53         TPRINTF("Real output:     \"%-*.*s\"\n\n", 7, 7, "text");
    54        
    5551        return NULL;
    5652}
  • uspace/app/top/screen.c

    rf76696f r1db6dfd  
    3737
    3838#include <stdio.h>
    39 #include <stdlib.h>
    4039#include <io/console.h>
    4140#include <io/style.h>
     
    4443#include <stats.h>
    4544#include <inttypes.h>
    46 #include <macros.h>
    4745#include "screen.h"
    4846#include "top.h"
     
    5048#define USEC_COUNT  1000000
    5149
     50static sysarg_t warn_col = 0;
     51static sysarg_t warn_row = 0;
    5252static suseconds_t timeleft = 0;
    5353
    5454console_ctrl_t *console;
    5555
    56 static sysarg_t warning_col = 0;
    57 static sysarg_t warning_row = 0;
    58 static suseconds_t warning_timeleft = 0;
    59 static char *warning_text = NULL;
    60 
    6156static void screen_style_normal(void)
    6257{
     
    6964        console_flush(console);
    7065        console_set_style(console, STYLE_INVERTED);
    71 }
    72 
    73 static void screen_style_emphasis(void)
    74 {
    75         console_flush(console);
    76         console_set_style(console, STYLE_EMPHASIS);
    7766}
    7867
     
    137126void screen_done(void)
    138127{
    139         free(warning_text);
    140         warning_text = NULL;
    141 
    142128        screen_restart(true);
    143129       
     
    291277}
    292278
    293 static inline void print_help_head(void)
     279static inline void print_tasks_head(void)
    294280{
    295281        screen_style_inverted();
    296         printf("Help");
     282        printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
     283            " [%%user] [%%kern] [name");
    297284        screen_newline();
    298285        screen_style_normal();
    299286}
    300287
    301 static inline void print_help(void)
     288static inline void print_tasks(data_t *data)
    302289{
    303290        sysarg_t cols;
     
    305292        screen_get_size(&cols, &rows);
    306293       
    307         screen_newline();
    308        
    309         printf("Operation modes:");
    310         screen_newline();
    311        
    312         printf(" t .. tasks statistics");
    313         screen_newline();
    314        
    315         printf(" i .. IPC statistics");
    316         screen_newline();
    317        
    318         printf(" e .. exceptions statistics");
    319         screen_newline();
    320        
    321         printf("      a .. toggle display of all/hot exceptions");
    322         screen_newline();
    323 
    324         printf(" h .. toggle this help screen");
    325         screen_newline();
    326 
    327         screen_newline();
    328 
    329         printf("Other keys:");
    330         screen_newline();
    331        
    332         printf(" s .. choose column to sort by");
    333         screen_newline();
    334        
    335         printf(" r .. toggle reversed sorting");
    336         screen_newline();
    337        
    338         printf(" q .. quit");
    339         screen_newline();
    340        
    341294        sysarg_t col;
    342295        sysarg_t row;
    343296        screen_get_pos(&col, &row);
    344297       
     298        size_t i;
     299        for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
     300                stats_task_t *task = data->tasks + data->tasks_map[i];
     301                perc_task_t *perc = data->tasks_perc + data->tasks_map[i];
     302               
     303                uint64_t resmem;
     304                const char *resmem_suffix;
     305                bin_order_suffix(task->resmem, &resmem, &resmem_suffix, true);
     306               
     307                uint64_t virtmem;
     308                const char *virtmem_suffix;
     309                bin_order_suffix(task->virtmem, &virtmem, &virtmem_suffix, true);
     310               
     311                printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s ",
     312                    task->task_id, task->threads, resmem, resmem_suffix);
     313                print_percent(perc->resmem, 2);
     314                printf(" %6" PRIu64 "%s ", virtmem, virtmem_suffix);
     315                print_percent(perc->virtmem, 2);
     316                puts(" ");
     317                print_percent(perc->ucycles, 2);
     318                puts(" ");
     319                print_percent(perc->kcycles, 2);
     320                puts(" ");
     321                print_string(task->name);
     322               
     323                screen_newline();
     324        }
     325       
    345326        while (row < rows) {
    346327                screen_newline();
     
    349330}
    350331
    351 static inline void print_table_head(const table_t *table)
     332static inline void print_ipc_head(void)
     333{
     334        screen_style_inverted();
     335        printf("[taskid] [cls snt] [cls rcv] [ans snt]"
     336            " [ans rcv] [irq rcv] [forward] [name");
     337        screen_newline();
     338        screen_style_normal();
     339}
     340
     341static inline void print_ipc(data_t *data)
    352342{
    353343        sysarg_t cols;
    354344        sysarg_t rows;
    355345        screen_get_size(&cols, &rows);
    356 
     346       
     347        sysarg_t col;
     348        sysarg_t row;
     349        screen_get_pos(&col, &row);
     350       
     351        size_t i;
     352        for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
     353                uint64_t call_sent;
     354                uint64_t call_received;
     355                uint64_t answer_sent;
     356                uint64_t answer_received;
     357                uint64_t irq_notif_received;
     358                uint64_t forwarded;
     359               
     360                char call_sent_suffix;
     361                char call_received_suffix;
     362                char answer_sent_suffix;
     363                char answer_received_suffix;
     364                char irq_notif_received_suffix;
     365                char forwarded_suffix;
     366               
     367                order_suffix(data->tasks[i].ipc_info.call_sent, &call_sent,
     368                    &call_sent_suffix);
     369                order_suffix(data->tasks[i].ipc_info.call_received,
     370                    &call_received, &call_received_suffix);
     371                order_suffix(data->tasks[i].ipc_info.answer_sent,
     372                    &answer_sent, &answer_sent_suffix);
     373                order_suffix(data->tasks[i].ipc_info.answer_received,
     374                    &answer_received, &answer_received_suffix);
     375                order_suffix(data->tasks[i].ipc_info.irq_notif_received,
     376                    &irq_notif_received, &irq_notif_received_suffix);
     377                order_suffix(data->tasks[i].ipc_info.forwarded, &forwarded,
     378                    &forwarded_suffix);
     379               
     380                printf("%-8" PRIu64 " %8" PRIu64 "%c %8" PRIu64 "%c"
     381                     " %8" PRIu64 "%c %8" PRIu64 "%c %8" PRIu64 "%c"
     382                     " %8" PRIu64 "%c ", data->tasks[i].task_id,
     383                     call_sent, call_sent_suffix,
     384                     call_received, call_received_suffix,
     385                     answer_sent, answer_sent_suffix,
     386                     answer_received, answer_received_suffix,
     387                     irq_notif_received, irq_notif_received_suffix,
     388                     forwarded, forwarded_suffix);
     389                print_string(data->tasks[i].name);
     390               
     391                screen_newline();
     392        }
     393       
     394        while (row < rows) {
     395                screen_newline();
     396                row++;
     397        }
     398}
     399
     400static inline void print_excs_head(void)
     401{
    357402        screen_style_inverted();
    358         for (size_t i = 0; i < table->num_columns; i++) {
    359                 const char *name = table->columns[i].name;
    360                 int width = table->columns[i].width;
    361                 if (i != 0) {
    362                         puts(" ");
    363                 }
    364                 if (width == 0) {
    365                         sysarg_t col;
    366                         sysarg_t row;
    367                         screen_get_pos(&col, &row);
    368                         width = cols - col - 1;
    369                 }
    370                 printf("[%-*.*s]", width - 2, width - 2, name);
    371         }
     403        printf("[exc   ] [count   ] [%%count] [cycles  ] [%%cycles] [description");
    372404        screen_newline();
    373405        screen_style_normal();
    374406}
    375407
    376 static inline void print_table(const table_t *table)
     408static inline void print_excs(data_t *data)
    377409{
    378410        sysarg_t cols;
     
    385417       
    386418        size_t i;
    387         for (i = 0; (i < table->num_fields) && (row < rows); i++) {
    388                 size_t column_index = i % table->num_columns;
    389                 int width = table->columns[column_index].width;
    390                 field_t *field = &table->fields[i];
    391 
    392                 if (column_index != 0) {
    393                         puts(" ");
    394                 }
    395 
    396                 if (width == 0) {
    397                         screen_get_pos(&col, &row);
    398                         width = cols - col - 1;
    399                 }
    400 
    401                 switch (field->type) {
    402                         case FIELD_EMPTY:
    403                                 printf("%*s", width, "");
    404                                 break;
    405                         case FIELD_UINT:
    406                                 printf("%*" PRIu64, width, field->uint);
    407                                 break;
    408                         case FIELD_UINT_SUFFIX_BIN: {
    409                                 uint64_t val = field->uint;
    410                                 const char *suffix;
    411                                 width -= 3;
    412                                 bin_order_suffix(val, &val, &suffix, true);
    413                                 printf("%*" PRIu64 "%s", width, val, suffix);
    414                                 break;
    415                                 }
    416                         case FIELD_UINT_SUFFIX_DEC: {
    417                                 uint64_t val = field->uint;
    418                                 char suffix;
    419                                 width -= 1;
    420                                 order_suffix(val, &val, &suffix);
    421                                 printf("%*" PRIu64 "%c", width, val, suffix);
    422                                 break;
    423                                 }
    424                         case FIELD_PERCENT:
    425                                 width -= 5; /* nnn.% */
    426                                 if (width > 2) {
    427                                         printf("%*s", width - 2, "");
    428                                         width = 2;
    429                                 }
    430                                 print_percent(field->fixed, width);
    431                                 break;
    432                         case FIELD_STRING:
    433                                 printf("%-*.*s", width, width, field->string);
    434                                 break;
    435                 }
    436 
    437                 if (column_index == table->num_columns - 1) {
    438                         screen_newline();
    439                         row++;
    440                 }
     419        for (i = 0; (i < data->exceptions_count) && (row < rows); i++) {
     420                /* Filter-out cold exceptions if not instructed otherwise */
     421                if ((!excs_all) && (!data->exceptions[i].hot))
     422                        continue;
     423               
     424                uint64_t count;
     425                uint64_t cycles;
     426               
     427                char count_suffix;
     428                char cycles_suffix;
     429               
     430                order_suffix(data->exceptions[i].count, &count, &count_suffix);
     431                order_suffix(data->exceptions[i].cycles, &cycles, &cycles_suffix);
     432               
     433                printf("%-8u %9" PRIu64 "%c  ",
     434                     data->exceptions[i].id, count, count_suffix);
     435                print_percent(data->exceptions_perc[i].count, 2);
     436                printf(" %9" PRIu64 "%c   ", cycles, cycles_suffix);
     437                print_percent(data->exceptions_perc[i].cycles, 2);
     438                puts(" ");
     439                print_string(data->exceptions[i].desc);
     440               
     441                screen_newline();
     442                row++;
    441443        }
    442444       
     
    447449}
    448450
    449 static inline void print_sort(table_t *table)
     451static void print_help(void)
    450452{
    451453        sysarg_t cols;
     
    456458        sysarg_t row;
    457459        screen_get_pos(&col, &row);
    458 
    459         size_t num = min(table->num_columns, rows - row);
    460         for (size_t i = 0; i < num; i++) {
    461                 printf("%c - %s", table->columns[i].key, table->columns[i].name);
     460       
     461        screen_newline();
     462       
     463        printf("Operation modes:");
     464        screen_newline();
     465       
     466        printf(" t .. tasks statistics");
     467        screen_newline();
     468       
     469        printf(" i .. IPC statistics");
     470        screen_newline();
     471       
     472        printf(" e .. exceptions statistics");
     473        screen_newline();
     474       
     475        printf("      a .. toggle display of all/hot exceptions");
     476        screen_newline();
     477       
     478        row += 6;
     479       
     480        while (row < rows) {
    462481                screen_newline();
    463482                row++;
    464483        }
    465        
    466         while (row < rows) {
    467                 screen_newline();
    468                 row++;
    469         }
    470 }
    471 
    472 static inline void print_warning(void)
    473 {
    474         screen_get_pos(&warning_col, &warning_row);
    475         if (warning_timeleft > 0) {
    476                 screen_style_emphasis();
    477                 print_string(warning_text);
    478                 screen_style_normal();
    479         } else {
    480                 free(warning_text);
    481                 warning_text = NULL;
    482         }
    483         screen_newline();
    484484}
    485485
     
    492492        print_cpu_info(data);
    493493        print_physmem_info(data);
    494         print_warning();
    495        
    496         switch (screen_mode) {
    497         case SCREEN_TABLE:
    498                 print_table_head(&data->table);
    499                 print_table(&data->table);
     494       
     495        /* Empty row for warnings */
     496        screen_get_pos(&warn_col, &warn_row);
     497        screen_newline();
     498       
     499        switch (op_mode) {
     500        case OP_TASKS:
     501                print_tasks_head();
     502                print_tasks(data);
    500503                break;
    501         case SCREEN_SORT:
    502                 print_sort(&data->table);
     504        case OP_IPC:
     505                print_ipc_head();
     506                print_ipc(data);
    503507                break;
    504         case SCREEN_HELP:
    505                 print_help_head();
     508        case OP_EXCS:
     509                print_excs_head();
     510                print_excs(data);
     511                break;
     512        case OP_HELP:
     513                print_tasks_head();
    506514                print_help();
    507515        }
     
    510518}
    511519
    512 void show_warning(const char *fmt, ...)
    513 {
    514         sysarg_t cols;
    515         sysarg_t rows;
    516         screen_get_size(&cols, &rows);
    517 
    518         size_t warning_text_size = 1 + cols * sizeof(*warning_text);
    519         free(warning_text);
    520         warning_text = malloc(warning_text_size);
    521         if (!warning_text)
    522                 return;
    523 
     520void print_warning(const char *fmt, ...)
     521{
     522        screen_moveto(warn_col, warn_row);
     523       
    524524        va_list args;
    525525        va_start(args, fmt);
    526         vsnprintf(warning_text, warning_text_size, fmt, args);
     526        vprintf(fmt, args);
    527527        va_end(args);
    528528       
    529         warning_timeleft = 2 * USEC_COUNT;
    530 
    531         screen_moveto(warning_col, warning_row);
    532         print_warning();
     529        screen_newline();
    533530        console_flush(console);
    534531}
     
    558555                kbd_event_t event;
    559556               
    560                 warning_timeleft -= timeleft;
    561557                if (!console_get_kbd_event_timeout(console, &event, &timeleft)) {
    562558                        timeleft = 0;
    563559                        return -1;
    564560                }
    565                 warning_timeleft += timeleft;
    566561               
    567562                if (event.type == KEY_PRESS)
  • uspace/app/top/screen.h

    rf76696f r1db6dfd  
    4343extern void screen_done(void);
    4444extern void print_data(data_t *);
    45 extern void show_warning(const char *, ...);
     45extern void print_warning(const char *, ...);
    4646
    4747extern int tgetchar(unsigned int);
  • uspace/app/top/top.c

    rf76696f r1db6dfd  
    5555#define MINUTE  60
    5656
    57 typedef enum {
    58         OP_TASKS,
    59         OP_IPC,
    60         OP_EXCS,
    61 } op_mode_t;
    62 
    63 static const column_t task_columns[] = {
    64         {"taskid",   't',  8},
    65         {"thrds",    'h',  7},
    66         {"resident", 'r', 10},
    67         {"%resi",    'R',  7},
    68         {"virtual",  'v',  9},
    69         {"%virt",    'V',  7},
    70         {"%user",    'U',  7},
    71         {"%kern",    'K',  7},
    72         {"name",     'd',  0},
    73 };
    74 
    75 enum {
    76         TASK_COL_ID = 0,
    77         TASK_COL_NUM_THREADS,
    78         TASK_COL_RESIDENT,
    79         TASK_COL_PERCENT_RESIDENT,
    80         TASK_COL_VIRTUAL,
    81         TASK_COL_PERCENT_VIRTUAL,
    82         TASK_COL_PERCENT_USER,
    83         TASK_COL_PERCENT_KERNEL,
    84         TASK_COL_NAME,
    85         TASK_NUM_COLUMNS,
    86 };
    87 
    88 static const column_t ipc_columns[] = {
    89         {"taskid",  't', 8},
    90         {"cls snt", 'c', 9},
    91         {"cls rcv", 'C', 9},
    92         {"ans snt", 'a', 9},
    93         {"ans rcv", 'A', 9},
    94         {"forward", 'f', 9},
    95         {"name",    'd', 0},
    96 };
    97 
    98 enum {
    99         IPC_COL_TASKID = 0,
    100         IPC_COL_CLS_SNT,
    101         IPC_COL_CLS_RCV,
    102         IPC_COL_ANS_SNT,
    103         IPC_COL_ANS_RCV,
    104         IPC_COL_FORWARD,
    105         IPC_COL_NAME,
    106         IPC_NUM_COLUMNS,
    107 };
    108 
    109 static const column_t exception_columns[] = {
    110         {"exc",         'e',  8},
    111         {"count",       'n', 10},
    112         {"%count",      'N',  8},
    113         {"cycles",      'c', 10},
    114         {"%cycles",     'C',  9},
    115         {"description", 'd',  0},
    116 };
    117 
    118 enum {
    119         EXCEPTION_COL_ID = 0,
    120         EXCEPTION_COL_COUNT,
    121         EXCEPTION_COL_PERCENT_COUNT,
    122         EXCEPTION_COL_CYCLES,
    123         EXCEPTION_COL_PERCENT_CYCLES,
    124         EXCEPTION_COL_DESCRIPTION,
    125         EXCEPTION_NUM_COLUMNS,
    126 };
    127 
    128 screen_mode_t screen_mode = SCREEN_TABLE;
    129 static op_mode_t op_mode = OP_TASKS;
    130 static size_t sort_column = TASK_COL_PERCENT_USER;
    131 static int sort_reverse = -1;
    132 static bool excs_all = false;
     57op_mode_t op_mode = OP_TASKS;
     58sort_mode_t sort_mode = SORT_TASK_CYCLES;
     59bool excs_all = false;
    13360
    13461static const char *read_data(data_t *target)
     
    14067        target->tasks = NULL;
    14168        target->tasks_perc = NULL;
     69        target->tasks_map = NULL;
    14270        target->threads = NULL;
    14371        target->exceptions = NULL;
     
    14876        target->ecycles_diff = NULL;
    14977        target->ecount_diff = NULL;
    150         target->table.name = NULL;
    151         target->table.num_columns = 0;
    152         target->table.columns = NULL;
    153         target->table.num_fields = 0;
    154         target->table.fields = NULL;
    15578       
    15679        /* Get current time */
     
    194117        if (target->tasks_perc == NULL)
    195118                return "Not enough memory for task utilization";
     119       
     120        target->tasks_map =
     121            (size_t *) calloc(target->tasks_count, sizeof(size_t));
     122        if (target->tasks_map == NULL)
     123                return "Not enough memory for task map";
    196124       
    197125        /* Get threads */
     
    361289static int cmp_data(void *a, void *b, void *arg)
    362290{
    363         field_t *fa = (field_t *)a + sort_column;
    364         field_t *fb = (field_t *)b + sort_column;
    365        
    366         if (fa->type > fb->type)
    367                 return 1 * sort_reverse;
    368 
    369         if (fa->type < fb->type)
    370                 return -1 * sort_reverse;
    371 
    372         switch (fa->type) {
    373                 case FIELD_EMPTY:
    374                         return 0;
    375                 case FIELD_UINT_SUFFIX_BIN: /* fallthrough */
    376                 case FIELD_UINT_SUFFIX_DEC: /* fallthrough */
    377                 case FIELD_UINT:
    378                         if (fa->uint > fb->uint)
    379                                 return 1 * sort_reverse;
    380                         if (fa->uint < fb->uint)
    381                                 return -1 * sort_reverse;
    382                         return 0;
    383                 case FIELD_PERCENT:
    384                         if (fa->fixed.upper * fb->fixed.lower
    385                             > fb->fixed.upper * fa->fixed.lower)
    386                                 return 1 * sort_reverse;
    387                         if (fa->fixed.upper * fb->fixed.lower
    388                             < fb->fixed.upper * fa->fixed.lower)
    389                                 return -1 * sort_reverse;
    390                         return 0;
    391                 case FIELD_STRING:
    392                         return str_cmp(fa->string, fb->string) * sort_reverse;
    393         }
    394 
     291        size_t ia = *((size_t *) a);
     292        size_t ib = *((size_t *) b);
     293        data_t *data = (data_t *) arg;
     294       
     295        uint64_t acycles = data->ucycles_diff[ia] + data->kcycles_diff[ia];
     296        uint64_t bcycles = data->ucycles_diff[ib] + data->kcycles_diff[ib];
     297       
     298        if (acycles > bcycles)
     299                return -1;
     300       
     301        if (acycles < bcycles)
     302                return 1;
     303       
    395304        return 0;
    396305}
    397306
    398 static void sort_table(table_t *table)
    399 {
    400         if (sort_column >= table->num_columns)
    401                 sort_column = 0;
    402         /* stable sort is probably best, so we use gsort */
    403         gsort((void *) table->fields, table->num_fields / table->num_columns,
    404             sizeof(field_t) * table->num_columns, cmp_data, NULL);
    405 }
    406 
    407 static const char *fill_task_table(data_t *data)
    408 {
    409         data->table.name = "Tasks";
    410         data->table.num_columns = TASK_NUM_COLUMNS;
    411         data->table.columns = task_columns;
    412         data->table.num_fields = data->tasks_count * TASK_NUM_COLUMNS;
    413         data->table.fields = calloc(data->table.num_fields,
    414             sizeof(field_t));
    415         if (data->table.fields == NULL)
    416                 return "Not enough memory for table fields";
    417 
    418         field_t *field = data->table.fields;
    419         for (size_t i = 0; i < data->tasks_count; i++) {
    420                 stats_task_t *task = &data->tasks[i];
    421                 perc_task_t *perc = &data->tasks_perc[i];
    422                 field[TASK_COL_ID].type = FIELD_UINT;
    423                 field[TASK_COL_ID].uint = task->task_id;
    424                 field[TASK_COL_NUM_THREADS].type = FIELD_UINT;
    425                 field[TASK_COL_NUM_THREADS].uint = task->threads;
    426                 field[TASK_COL_RESIDENT].type = FIELD_UINT_SUFFIX_BIN;
    427                 field[TASK_COL_RESIDENT].uint = task->resmem;
    428                 field[TASK_COL_PERCENT_RESIDENT].type = FIELD_PERCENT;
    429                 field[TASK_COL_PERCENT_RESIDENT].fixed = perc->resmem;
    430                 field[TASK_COL_VIRTUAL].type = FIELD_UINT_SUFFIX_BIN;
    431                 field[TASK_COL_VIRTUAL].uint = task->virtmem;
    432                 field[TASK_COL_PERCENT_VIRTUAL].type = FIELD_PERCENT;
    433                 field[TASK_COL_PERCENT_VIRTUAL].fixed = perc->virtmem;
    434                 field[TASK_COL_PERCENT_USER].type = FIELD_PERCENT;
    435                 field[TASK_COL_PERCENT_USER].fixed = perc->ucycles;
    436                 field[TASK_COL_PERCENT_KERNEL].type = FIELD_PERCENT;
    437                 field[TASK_COL_PERCENT_KERNEL].fixed = perc->kcycles;
    438                 field[TASK_COL_NAME].type = FIELD_STRING;
    439                 field[TASK_COL_NAME].string = task->name;
    440                 field += TASK_NUM_COLUMNS;
    441         }
    442 
    443         return NULL;
    444 }
    445 
    446 static const char *fill_ipc_table(data_t *data)
    447 {
    448         data->table.name = "IPC";
    449         data->table.num_columns = IPC_NUM_COLUMNS;
    450         data->table.columns = ipc_columns;
    451         data->table.num_fields = data->tasks_count * IPC_NUM_COLUMNS;
    452         data->table.fields = calloc(data->table.num_fields,
    453             sizeof(field_t));
    454         if (data->table.fields == NULL)
    455                 return "Not enough memory for table fields";
    456 
    457         field_t *field = data->table.fields;
    458         for (size_t i = 0; i < data->tasks_count; i++) {
    459                 field[IPC_COL_TASKID].type = FIELD_UINT;
    460                 field[IPC_COL_TASKID].uint = data->tasks[i].task_id;
    461                 field[IPC_COL_CLS_SNT].type = FIELD_UINT_SUFFIX_DEC;
    462                 field[IPC_COL_CLS_SNT].uint = data->tasks[i].ipc_info.call_sent;
    463                 field[IPC_COL_CLS_RCV].type = FIELD_UINT_SUFFIX_DEC;
    464                 field[IPC_COL_CLS_RCV].uint = data->tasks[i].ipc_info.call_received;
    465                 field[IPC_COL_ANS_SNT].type = FIELD_UINT_SUFFIX_DEC;
    466                 field[IPC_COL_ANS_SNT].uint = data->tasks[i].ipc_info.answer_sent;
    467                 field[IPC_COL_ANS_RCV].type = FIELD_UINT_SUFFIX_DEC;
    468                 field[IPC_COL_ANS_RCV].uint = data->tasks[i].ipc_info.answer_received;
    469                 field[IPC_COL_FORWARD].type = FIELD_UINT_SUFFIX_DEC;
    470                 field[IPC_COL_FORWARD].uint = data->tasks[i].ipc_info.forwarded;
    471                 field[IPC_COL_NAME].type = FIELD_STRING;
    472                 field[IPC_COL_NAME].string = data->tasks[i].name;
    473                 field += IPC_NUM_COLUMNS;
    474         }
    475 
    476         return NULL;
    477 }
    478 
    479 static const char *fill_exception_table(data_t *data)
    480 {
    481         data->table.name = "Exceptions";
    482         data->table.num_columns = EXCEPTION_NUM_COLUMNS;
    483         data->table.columns = exception_columns;
    484         data->table.num_fields = data->exceptions_count *
    485             EXCEPTION_NUM_COLUMNS;
    486         data->table.fields = calloc(data->table.num_fields, sizeof(field_t));
    487         if (data->table.fields == NULL)
    488                 return "Not enough memory for table fields";
    489 
    490         field_t *field = data->table.fields;
    491         for (size_t i = 0; i < data->exceptions_count; i++) {
    492                 if (!excs_all && !data->exceptions[i].hot)
    493                         continue;
    494                 field[EXCEPTION_COL_ID].type = FIELD_UINT;
    495                 field[EXCEPTION_COL_ID].uint = data->exceptions[i].id;
    496                 field[EXCEPTION_COL_COUNT].type = FIELD_UINT_SUFFIX_DEC;
    497                 field[EXCEPTION_COL_COUNT].uint = data->exceptions[i].count;
    498                 field[EXCEPTION_COL_PERCENT_COUNT].type = FIELD_PERCENT;
    499                 field[EXCEPTION_COL_PERCENT_COUNT].fixed = data->exceptions_perc[i].count;
    500                 field[EXCEPTION_COL_CYCLES].type = FIELD_UINT_SUFFIX_DEC;
    501                 field[EXCEPTION_COL_CYCLES].uint = data->exceptions[i].cycles;
    502                 field[EXCEPTION_COL_PERCENT_CYCLES].type = FIELD_PERCENT;
    503                 field[EXCEPTION_COL_PERCENT_CYCLES].fixed = data->exceptions_perc[i].cycles;
    504                 field[EXCEPTION_COL_DESCRIPTION].type = FIELD_STRING;
    505                 field[EXCEPTION_COL_DESCRIPTION].string = data->exceptions[i].desc;
    506                 field += EXCEPTION_NUM_COLUMNS;
    507         }
    508 
    509         /* in case any cold exceptions were ignored */
    510         data->table.num_fields = field - data->table.fields;
    511 
    512         return NULL;
    513 }
    514 
    515 static const char *fill_table(data_t *data)
    516 {
    517         if (data->table.fields != NULL) {
    518                 free(data->table.fields);
    519                 data->table.fields = NULL;
    520         }
    521 
    522         switch (op_mode) {
    523                 case OP_TASKS:
    524                         return fill_task_table(data);
    525                 case OP_IPC:
    526                         return fill_ipc_table(data);
    527                 case OP_EXCS:
    528                         return fill_exception_table(data);
    529         }
    530         return NULL;
     307static void sort_data(data_t *data)
     308{
     309        size_t i;
     310       
     311        for (i = 0; i < data->tasks_count; i++)
     312                data->tasks_map[i] = i;
     313       
     314        qsort((void *) data->tasks_map, data->tasks_count,
     315            sizeof(size_t), cmp_data, (void *) data);
    531316}
    532317
     
    571356        if (target->ecount_diff != NULL)
    572357                free(target->ecount_diff);
    573 
    574         if (target->table.fields != NULL)
    575                 free(target->table.fields);
    576358}
    577359
     
    585367        printf("Reading initial data...\n");
    586368       
    587         if ((ret = read_data(&data)) != NULL)
     369        if ((ret = read_data(&data_prev)) != NULL)
    588370                goto out;
    589371       
    590372        /* Compute some rubbish to have initialised values */
    591         compute_percentages(&data, &data);
     373        compute_percentages(&data_prev, &data_prev);
    592374       
    593375        /* And paint screen until death */
    594376        while (true) {
    595377                int c = tgetchar(UPDATE_INTERVAL);
    596 
    597                 if (c < 0) { /* timeout */
    598                         data_prev = data;
     378                if (c < 0) {
    599379                        if ((ret = read_data(&data)) != NULL) {
    600                                 free_data(&data_prev);
     380                                free_data(&data);
    601381                                goto out;
    602382                        }
    603383                       
    604384                        compute_percentages(&data_prev, &data);
     385                        sort_data(&data);
     386                        print_data(&data);
    605387                        free_data(&data_prev);
    606 
    607                         c = -1;
    608                 }
    609 
    610                 if (screen_mode == SCREEN_HELP && c >= 0) {
    611                         if (c == 'h' || c == '?')
    612                                 c = -1;
    613                         /* go back to table and handle the key */
    614                         screen_mode = SCREEN_TABLE;
    615                 }
    616 
    617                 if (screen_mode == SCREEN_SORT && c >= 0) {
    618                         for (size_t i = 0; i < data.table.num_columns; i++) {
    619                                 if (data.table.columns[i].key == c) {
    620                                         sort_column = i;
    621                                         screen_mode = SCREEN_TABLE;
    622                                 }
    623                         }
    624 
    625                         c = -1;
    626                 }
    627 
     388                        data_prev = data;
     389                       
     390                        continue;
     391                }
     392               
    628393                switch (c) {
    629                         case -1: /* do nothing */
    630                                 break;
    631394                        case 't':
     395                                print_warning("Showing task statistics");
    632396                                op_mode = OP_TASKS;
    633397                                break;
    634398                        case 'i':
     399                                print_warning("Showing IPC statistics");
    635400                                op_mode = OP_IPC;
    636401                                break;
    637402                        case 'e':
     403                                print_warning("Showing exception statistics");
    638404                                op_mode = OP_EXCS;
    639405                                break;
    640                         case 's':
    641                                 screen_mode = SCREEN_SORT;
    642                                 break;
    643                         case 'r':
    644                                 sort_reverse = -sort_reverse;
    645                                 break;
    646406                        case 'h':
    647                         case '?':
    648                                 screen_mode = SCREEN_HELP;
     407                                print_warning("Showing help");
     408                                op_mode = OP_HELP;
    649409                                break;
    650410                        case 'q':
     
    654414                                        excs_all = !excs_all;
    655415                                        if (excs_all)
    656                                                 show_warning("Showing all exceptions");
     416                                                print_warning("Showing all exceptions");
    657417                                        else
    658                                                 show_warning("Showing only hot exceptions");
     418                                                print_warning("Showing only hot exceptions");
    659419                                        break;
    660420                                }
    661                                 /* fallthrough */
    662421                        default:
    663                                 show_warning("Unknown command \"%c\", use \"h\" for help", c);
    664                                 continue; /* don't redraw */
    665                 }
    666 
    667                 if ((ret = fill_table(&data)) != NULL) {
    668                         goto out;
    669                 }
    670                 sort_table(&data.table);
    671                 print_data(&data);
     422                                print_warning("Unknown command \"%c\", use \"h\" for help", c);
     423                                break;
     424                }
    672425        }
    673426       
    674427out:
    675428        screen_done();
    676         free_data(&data);
     429        free_data(&data_prev);
    677430       
    678431        if (ret != NULL) {
  • uspace/app/top/top.h

    rf76696f r1db6dfd  
    5151
    5252typedef enum {
    53         SCREEN_TABLE,
    54         SCREEN_SORT,
    55         SCREEN_HELP,
    56 } screen_mode_t;
     53        OP_TASKS,
     54        OP_IPC,
     55        OP_EXCS,
     56        OP_HELP
     57} op_mode_t;
    5758
    58 extern screen_mode_t screen_mode;
     59typedef enum {
     60        SORT_TASK_CYCLES
     61} sort_mode_t;
     62
     63extern op_mode_t op_mode;
     64extern sort_mode_t sort_mode;
     65extern bool excs_all;
    5966
    6067typedef struct {
     
    8087} perc_exc_t;
    8188
    82 typedef enum {
    83         FIELD_EMPTY, FIELD_UINT, FIELD_UINT_SUFFIX_BIN, FIELD_UINT_SUFFIX_DEC,
    84         FIELD_PERCENT, FIELD_STRING
    85 } field_type_t;
    86 
    87 typedef struct {
    88         field_type_t type;
    89         union {
    90                 fixed_float fixed;
    91                 uint64_t uint;
    92                 const char *string;
    93         };
    94 } field_t;
    95 
    96 typedef struct {
    97         const char *name;
    98         char key;
    99         int width;
    100 } column_t;
    101 
    102 typedef struct {
    103         const char *name;
    104         size_t num_columns;
    105         const column_t *columns;
    106         size_t num_fields;
    107         field_t *fields;
    108 } table_t;
    109 
    11089typedef struct {
    11190        time_t hours;
     
    128107        stats_task_t *tasks;
    129108        perc_task_t *tasks_perc;
     109        size_t *tasks_map;
    130110       
    131111        size_t threads_count;
     
    142122        uint64_t *ecycles_diff;
    143123        uint64_t *ecount_diff;
    144 
    145         table_t table;
    146124} data_t;
    147125
  • uspace/lib/c/generic/io/printf_core.c

    rf76696f r1db6dfd  
    283283        /* Print leading spaces. */
    284284        size_t strw = str_length(str);
    285         if (precision == 0 || precision > strw)
     285        if (precision == 0)
    286286                precision = strw;
    287287       
     
    331331        /* Print leading spaces. */
    332332        size_t strw = wstr_length(str);
    333         if (precision == 0 || precision > strw)
     333        if (precision == 0)
    334334                precision = strw;
    335335       
Note: See TracChangeset for help on using the changeset viewer.