Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 5042706 in mainline


Ignore:
Timestamp:
2014-11-14T19:57:51Z (6 years ago)
Author:
Martin Decky <martin@…>
Branches:
master
Children:
99d8c82, b412168
Parents:
1ab8539
Message:

update C demos

Location:
uspace/dist/src/c/demos
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/dist/src/c/demos/tetris/shapes.c

    r1ab8539 r5042706  
    6969
    7070const struct shape shapes[] = {
    71         /*  0 */  {  7,  7, { TL, TC, MR }, 0xff042d},
    72         /*  1 */  {  8,  8, { TC, TR, ML }, 0xff9304},
    73         /*  2 */  {  9, 11, { ML, MR, BC }, 0xbeff04},
    74         /*  3 */  {  3,  3, { TL, TC, ML }, 0x63ff04},
    75         /*  4 */  { 12, 14, { ML, BL, MR }, 0xce04ff},
    76         /*  5 */  { 15, 17, { ML, BR, MR }, 0xff04cf},
    77         /*  6 */  { 18, 18, { ML, MR, 2  }, 0x7604ff},  /* sticks out */
    78         /*  7 */  {  0,  0, { TC, ML, BL }, 0xff042d},
    79         /*  8 */  {  1,  1, { TC, MR, BR }, 0xff9304},
    80         /*  9 */  { 10,  2, { TC, MR, BC }, 0xbeff04},
    81         /* 10 */  { 11,  9, { TC, ML, MR }, 0xbeff04},
    82         /* 11 */  {  2, 10, { TC, ML, BC }, 0xbeff04},
    83         /* 12 */  { 13,  4, { TC, BC, BR }, 0xce04ff},
    84         /* 13 */  { 14, 12, { TR, ML, MR }, 0xce04ff},
    85         /* 14 */  {  4, 13, { TL, TC, BC }, 0xce04ff},
    86         /* 15 */  { 16,  5, { TR, TC, BC }, 0xff04cf},
    87         /* 16 */  { 17, 15, { TL, MR, ML }, 0xff04cf},
    88         /* 17 */  {  5, 16, { TC, BC, BL }, 0xff04cf},
    89         /* 18 */  {  6,  6, { TC, BC, 2 * B_COLS }, 0x7604ff}  /* sticks out */
     71        /*  0 */  {  7,  7, { TL, TC, MR }, 0x00aaaa},
     72        /*  1 */  {  8,  8, { TC, TR, ML }, 0x00aa00},
     73        /*  2 */  {  9, 11, { ML, MR, BC }, 0xaa5500},
     74        /*  3 */  {  3,  3, { TL, TC, ML }, 0x0000aa},
     75        /*  4 */  { 12, 14, { ML, BL, MR }, 0xaa00aa},
     76        /*  5 */  { 15, 17, { ML, BR, MR }, 0xffa500},
     77        /*  6 */  { 18, 18, { ML, MR, 2  }, 0xaa0000},  /* sticks out */
     78        /*  7 */  {  0,  0, { TC, ML, BL }, 0x00aaaa},
     79        /*  8 */  {  1,  1, { TC, MR, BR }, 0x00aa00},
     80        /*  9 */  { 10,  2, { TC, MR, BC }, 0xaa5500},
     81        /* 10 */  { 11,  9, { TC, ML, MR }, 0xaa5500},
     82        /* 11 */  {  2, 10, { TC, ML, BC }, 0xaa5500},
     83        /* 12 */  { 13,  4, { TC, BC, BR }, 0xaa00aa},
     84        /* 13 */  { 14, 12, { TR, ML, MR }, 0xaa00aa},
     85        /* 14 */  {  4, 13, { TL, TC, BC }, 0xaa00aa},
     86        /* 15 */  { 16,  5, { TR, TC, BC }, 0xffa500},
     87        /* 16 */  { 17, 15, { TL, MR, ML }, 0xffa500},
     88        /* 17 */  {  5, 16, { TC, BC, BL }, 0xffa500},
     89        /* 18 */  {  6,  6, { TC, BC, 2 * B_COLS }, 0xaa0000}  /* sticks out */
    9090};
    9191
  • uspace/dist/src/c/demos/top/screen.c

    r1ab8539 r5042706  
    3737
    3838#include <stdio.h>
     39#include <stdlib.h>
    3940#include <io/console.h>
    4041#include <io/style.h>
     
    4344#include <stats.h>
    4445#include <inttypes.h>
     46#include <macros.h>
    4547#include "screen.h"
    4648#include "top.h"
     
    4850#define USEC_COUNT  1000000
    4951
    50 static sysarg_t warn_col = 0;
    51 static sysarg_t warn_row = 0;
    5252static suseconds_t timeleft = 0;
    5353
    5454console_ctrl_t *console;
    5555
     56static sysarg_t warning_col = 0;
     57static sysarg_t warning_row = 0;
     58static suseconds_t warning_timeleft = 0;
     59static char *warning_text = NULL;
     60
    5661static void screen_style_normal(void)
    5762{
     
    6469        console_flush(console);
    6570        console_set_style(console, STYLE_INVERTED);
     71}
     72
     73static void screen_style_emphasis(void)
     74{
     75        console_flush(console);
     76        console_set_style(console, STYLE_EMPHASIS);
    6677}
    6778
     
    126137void screen_done(void)
    127138{
     139        free(warning_text);
     140        warning_text = NULL;
     141
    128142        screen_restart(true);
    129143       
     
    277291}
    278292
    279 static inline void print_tasks_head(void)
     293static inline void print_help_head(void)
    280294{
    281295        screen_style_inverted();
    282         printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
    283             " [%%user] [%%kern] [name");
     296        printf("Help");
    284297        screen_newline();
    285298        screen_style_normal();
    286299}
    287300
    288 static inline void print_tasks(data_t *data)
    289 {
    290         sysarg_t cols;
    291         sysarg_t rows;
    292         screen_get_size(&cols, &rows);
     301static inline void print_help(void)
     302{
     303        sysarg_t cols;
     304        sysarg_t rows;
     305        screen_get_size(&cols, &rows);
     306       
     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();
    293340       
    294341        sysarg_t col;
     
    296343        screen_get_pos(&col, &row);
    297344       
    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        
    326345        while (row < rows) {
    327346                screen_newline();
     
    330349}
    331350
    332 static inline void print_ipc_head(void)
    333 {
     351static inline void print_table_head(const table_t *table)
     352{
     353        sysarg_t cols;
     354        sysarg_t rows;
     355        screen_get_size(&cols, &rows);
     356
    334357        screen_style_inverted();
    335         printf("[taskid] [cls snt] [cls rcv] [ans snt]"
    336             " [ans rcv] [irq rcv] [forward] [name");
     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        }
    337372        screen_newline();
    338373        screen_style_normal();
    339374}
    340375
    341 static inline void print_ipc(data_t *data)
     376static inline void print_table(const table_t *table)
    342377{
    343378        sysarg_t cols;
     
    350385       
    351386        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();
     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                }
    392441        }
    393442       
     
    398447}
    399448
    400 static inline void print_excs_head(void)
    401 {
    402         screen_style_inverted();
    403         printf("[exc   ] [count   ] [%%count] [cycles  ] [%%cycles] [description");
    404         screen_newline();
    405         screen_style_normal();
    406 }
    407 
    408 static inline void print_excs(data_t *data)
     449static inline void print_sort(table_t *table)
    409450{
    410451        sysarg_t cols;
     
    415456        sysarg_t row;
    416457        screen_get_pos(&col, &row);
    417        
    418         size_t i;
    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                
     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);
    441462                screen_newline();
    442463                row++;
     
    449470}
    450471
    451 static void print_help(void)
    452 {
    453         sysarg_t cols;
    454         sysarg_t rows;
    455         screen_get_size(&cols, &rows);
    456        
    457         sysarg_t col;
    458         sysarg_t row;
    459         screen_get_pos(&col, &row);
    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) {
    481                 screen_newline();
    482                 row++;
    483         }
     472static 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        
    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);
     494        print_warning();
     495       
     496        switch (screen_mode) {
     497        case SCREEN_TABLE:
     498                print_table_head(&data->table);
     499                print_table(&data->table);
    503500                break;
    504         case OP_IPC:
    505                 print_ipc_head();
    506                 print_ipc(data);
     501        case SCREEN_SORT:
     502                print_sort(&data->table);
    507503                break;
    508         case OP_EXCS:
    509                 print_excs_head();
    510                 print_excs(data);
    511                 break;
    512         case OP_HELP:
    513                 print_tasks_head();
     504        case SCREEN_HELP:
     505                print_help_head();
    514506                print_help();
    515507        }
     
    518510}
    519511
    520 void print_warning(const char *fmt, ...)
    521 {
    522         screen_moveto(warn_col, warn_row);
    523        
     512void 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
    524524        va_list args;
    525525        va_start(args, fmt);
    526         vprintf(fmt, args);
     526        vsnprintf(warning_text, warning_text_size, fmt, args);
    527527        va_end(args);
    528528       
    529         screen_newline();
     529        warning_timeleft = 2 * USEC_COUNT;
     530
     531        screen_moveto(warning_col, warning_row);
     532        print_warning();
    530533        console_flush(console);
    531534}
     
    555558                cons_event_t event;
    556559               
     560                warning_timeleft -= timeleft;
    557561                if (!console_get_event_timeout(console, &event, &timeleft)) {
    558562                        timeleft = 0;
    559563                        return -1;
    560564                }
     565                warning_timeleft += timeleft;
    561566               
    562567                if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
  • uspace/dist/src/c/demos/top/screen.h

    r1ab8539 r5042706  
    4444extern void screen_done(void);
    4545extern void print_data(data_t *);
    46 extern void print_warning(const char *, ...)
     46extern void show_warning(const char *, ...)
    4747    PRINTF_ATTRIBUTE(1, 2);
    4848
  • uspace/dist/src/c/demos/top/top.c

    r1ab8539 r5042706  
    5555#define MINUTE  60
    5656
    57 op_mode_t op_mode = OP_TASKS;
    58 sort_mode_t sort_mode = SORT_TASK_CYCLES;
    59 bool excs_all = false;
     57typedef enum {
     58        OP_TASKS,
     59        OP_IPC,
     60        OP_EXCS,
     61} op_mode_t;
     62
     63static 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
     75enum {
     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
     88static 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
     98enum {
     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
     109static 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
     118enum {
     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
     128screen_mode_t screen_mode = SCREEN_TABLE;
     129static op_mode_t op_mode = OP_TASKS;
     130static size_t sort_column = TASK_COL_PERCENT_USER;
     131static int sort_reverse = -1;
     132static bool excs_all = false;
    60133
    61134static const char *read_data(data_t *target)
     
    67140        target->tasks = NULL;
    68141        target->tasks_perc = NULL;
    69         target->tasks_map = NULL;
    70142        target->threads = NULL;
    71143        target->exceptions = NULL;
     
    76148        target->ecycles_diff = NULL;
    77149        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;
    78155       
    79156        /* Get current time */
    80157        struct timeval time;
    81         if (gettimeofday(&time, NULL) != EOK)
    82                 return "Cannot get time of day";
     158        gettimeofday(&time, NULL);
    83159       
    84160        target->hours = (time.tv_sec % DAY) / HOUR;
     
    87163       
    88164        /* Get uptime */
    89         sysarg_t uptime = stats_get_uptime();
    90         target->udays = uptime / DAY;
    91         target->uhours = (uptime % DAY) / HOUR;
    92         target->uminutes = (uptime % HOUR) / MINUTE;
    93         target->useconds = uptime % MINUTE;
     165        struct timeval uptime;
     166        getuptime(&uptime);
     167       
     168        target->udays = uptime.tv_sec / DAY;
     169        target->uhours = (uptime.tv_sec % DAY) / HOUR;
     170        target->uminutes = (uptime.tv_sec % HOUR) / MINUTE;
     171        target->useconds = uptime.tv_sec % MINUTE;
    94172       
    95173        /* Get load */
     
    117195        if (target->tasks_perc == NULL)
    118196                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";
    124197       
    125198        /* Get threads */
     
    289362static int cmp_data(void *a, void *b, void *arg)
    290363{
    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        
     364        field_t *fa = (field_t *)a + sort_column;
     365        field_t *fb = (field_t *)b + sort_column;
     366       
     367        if (fa->type > fb->type)
     368                return 1 * sort_reverse;
     369
     370        if (fa->type < fb->type)
     371                return -1 * sort_reverse;
     372
     373        switch (fa->type) {
     374        case FIELD_EMPTY:
     375                return 0;
     376        case FIELD_UINT_SUFFIX_BIN: /* fallthrough */
     377        case FIELD_UINT_SUFFIX_DEC: /* fallthrough */
     378        case FIELD_UINT:
     379                if (fa->uint > fb->uint)
     380                        return 1 * sort_reverse;
     381                if (fa->uint < fb->uint)
     382                        return -1 * sort_reverse;
     383                return 0;
     384        case FIELD_PERCENT:
     385                if (fa->fixed.upper * fb->fixed.lower
     386                    > fb->fixed.upper * fa->fixed.lower)
     387                        return 1 * sort_reverse;
     388                if (fa->fixed.upper * fb->fixed.lower
     389                    < fb->fixed.upper * fa->fixed.lower)
     390                        return -1 * sort_reverse;
     391                return 0;
     392        case FIELD_STRING:
     393                return str_cmp(fa->string, fb->string) * sort_reverse;
     394        }
     395
    304396        return 0;
    305397}
    306398
    307 static 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);
     399static void sort_table(table_t *table)
     400{
     401        if (sort_column >= table->num_columns)
     402                sort_column = 0;
     403        /* stable sort is probably best, so we use gsort */
     404        gsort((void *) table->fields, table->num_fields / table->num_columns,
     405            sizeof(field_t) * table->num_columns, cmp_data, NULL);
     406}
     407
     408static const char *fill_task_table(data_t *data)
     409{
     410        data->table.name = "Tasks";
     411        data->table.num_columns = TASK_NUM_COLUMNS;
     412        data->table.columns = task_columns;
     413        data->table.num_fields = data->tasks_count * TASK_NUM_COLUMNS;
     414        data->table.fields = calloc(data->table.num_fields,
     415            sizeof(field_t));
     416        if (data->table.fields == NULL)
     417                return "Not enough memory for table fields";
     418
     419        field_t *field = data->table.fields;
     420        for (size_t i = 0; i < data->tasks_count; i++) {
     421                stats_task_t *task = &data->tasks[i];
     422                perc_task_t *perc = &data->tasks_perc[i];
     423                field[TASK_COL_ID].type = FIELD_UINT;
     424                field[TASK_COL_ID].uint = task->task_id;
     425                field[TASK_COL_NUM_THREADS].type = FIELD_UINT;
     426                field[TASK_COL_NUM_THREADS].uint = task->threads;
     427                field[TASK_COL_RESIDENT].type = FIELD_UINT_SUFFIX_BIN;
     428                field[TASK_COL_RESIDENT].uint = task->resmem;
     429                field[TASK_COL_PERCENT_RESIDENT].type = FIELD_PERCENT;
     430                field[TASK_COL_PERCENT_RESIDENT].fixed = perc->resmem;
     431                field[TASK_COL_VIRTUAL].type = FIELD_UINT_SUFFIX_BIN;
     432                field[TASK_COL_VIRTUAL].uint = task->virtmem;
     433                field[TASK_COL_PERCENT_VIRTUAL].type = FIELD_PERCENT;
     434                field[TASK_COL_PERCENT_VIRTUAL].fixed = perc->virtmem;
     435                field[TASK_COL_PERCENT_USER].type = FIELD_PERCENT;
     436                field[TASK_COL_PERCENT_USER].fixed = perc->ucycles;
     437                field[TASK_COL_PERCENT_KERNEL].type = FIELD_PERCENT;
     438                field[TASK_COL_PERCENT_KERNEL].fixed = perc->kcycles;
     439                field[TASK_COL_NAME].type = FIELD_STRING;
     440                field[TASK_COL_NAME].string = task->name;
     441                field += TASK_NUM_COLUMNS;
     442        }
     443
     444        return NULL;
     445}
     446
     447static const char *fill_ipc_table(data_t *data)
     448{
     449        data->table.name = "IPC";
     450        data->table.num_columns = IPC_NUM_COLUMNS;
     451        data->table.columns = ipc_columns;
     452        data->table.num_fields = data->tasks_count * IPC_NUM_COLUMNS;
     453        data->table.fields = calloc(data->table.num_fields,
     454            sizeof(field_t));
     455        if (data->table.fields == NULL)
     456                return "Not enough memory for table fields";
     457
     458        field_t *field = data->table.fields;
     459        for (size_t i = 0; i < data->tasks_count; i++) {
     460                field[IPC_COL_TASKID].type = FIELD_UINT;
     461                field[IPC_COL_TASKID].uint = data->tasks[i].task_id;
     462                field[IPC_COL_CLS_SNT].type = FIELD_UINT_SUFFIX_DEC;
     463                field[IPC_COL_CLS_SNT].uint = data->tasks[i].ipc_info.call_sent;
     464                field[IPC_COL_CLS_RCV].type = FIELD_UINT_SUFFIX_DEC;
     465                field[IPC_COL_CLS_RCV].uint = data->tasks[i].ipc_info.call_received;
     466                field[IPC_COL_ANS_SNT].type = FIELD_UINT_SUFFIX_DEC;
     467                field[IPC_COL_ANS_SNT].uint = data->tasks[i].ipc_info.answer_sent;
     468                field[IPC_COL_ANS_RCV].type = FIELD_UINT_SUFFIX_DEC;
     469                field[IPC_COL_ANS_RCV].uint = data->tasks[i].ipc_info.answer_received;
     470                field[IPC_COL_FORWARD].type = FIELD_UINT_SUFFIX_DEC;
     471                field[IPC_COL_FORWARD].uint = data->tasks[i].ipc_info.forwarded;
     472                field[IPC_COL_NAME].type = FIELD_STRING;
     473                field[IPC_COL_NAME].string = data->tasks[i].name;
     474                field += IPC_NUM_COLUMNS;
     475        }
     476
     477        return NULL;
     478}
     479
     480static const char *fill_exception_table(data_t *data)
     481{
     482        data->table.name = "Exceptions";
     483        data->table.num_columns = EXCEPTION_NUM_COLUMNS;
     484        data->table.columns = exception_columns;
     485        data->table.num_fields = data->exceptions_count *
     486            EXCEPTION_NUM_COLUMNS;
     487        data->table.fields = calloc(data->table.num_fields, sizeof(field_t));
     488        if (data->table.fields == NULL)
     489                return "Not enough memory for table fields";
     490
     491        field_t *field = data->table.fields;
     492        for (size_t i = 0; i < data->exceptions_count; i++) {
     493                if (!excs_all && !data->exceptions[i].hot)
     494                        continue;
     495                field[EXCEPTION_COL_ID].type = FIELD_UINT;
     496                field[EXCEPTION_COL_ID].uint = data->exceptions[i].id;
     497                field[EXCEPTION_COL_COUNT].type = FIELD_UINT_SUFFIX_DEC;
     498                field[EXCEPTION_COL_COUNT].uint = data->exceptions[i].count;
     499                field[EXCEPTION_COL_PERCENT_COUNT].type = FIELD_PERCENT;
     500                field[EXCEPTION_COL_PERCENT_COUNT].fixed = data->exceptions_perc[i].count;
     501                field[EXCEPTION_COL_CYCLES].type = FIELD_UINT_SUFFIX_DEC;
     502                field[EXCEPTION_COL_CYCLES].uint = data->exceptions[i].cycles;
     503                field[EXCEPTION_COL_PERCENT_CYCLES].type = FIELD_PERCENT;
     504                field[EXCEPTION_COL_PERCENT_CYCLES].fixed = data->exceptions_perc[i].cycles;
     505                field[EXCEPTION_COL_DESCRIPTION].type = FIELD_STRING;
     506                field[EXCEPTION_COL_DESCRIPTION].string = data->exceptions[i].desc;
     507                field += EXCEPTION_NUM_COLUMNS;
     508        }
     509
     510        /* in case any cold exceptions were ignored */
     511        data->table.num_fields = field - data->table.fields;
     512
     513        return NULL;
     514}
     515
     516static const char *fill_table(data_t *data)
     517{
     518        if (data->table.fields != NULL) {
     519                free(data->table.fields);
     520                data->table.fields = NULL;
     521        }
     522
     523        switch (op_mode) {
     524        case OP_TASKS:
     525                return fill_task_table(data);
     526        case OP_IPC:
     527                return fill_ipc_table(data);
     528        case OP_EXCS:
     529                return fill_exception_table(data);
     530        }
     531        return NULL;
    316532}
    317533
     
    356572        if (target->ecount_diff != NULL)
    357573                free(target->ecount_diff);
     574
     575        if (target->table.fields != NULL)
     576                free(target->table.fields);
    358577}
    359578
     
    367586        printf("Reading initial data...\n");
    368587       
    369         if ((ret = read_data(&data_prev)) != NULL)
     588        if ((ret = read_data(&data)) != NULL)
    370589                goto out;
    371590       
    372591        /* Compute some rubbish to have initialised values */
    373         compute_percentages(&data_prev, &data_prev);
     592        compute_percentages(&data, &data);
    374593       
    375594        /* And paint screen until death */
    376595        while (true) {
    377596                int c = tgetchar(UPDATE_INTERVAL);
    378                 if (c < 0) {
     597
     598                if (c < 0) { /* timeout */
     599                        data_prev = data;
    379600                        if ((ret = read_data(&data)) != NULL) {
    380                                 free_data(&data);
     601                                free_data(&data_prev);
    381602                                goto out;
    382603                        }
    383604                       
    384605                        compute_percentages(&data_prev, &data);
    385                         sort_data(&data);
    386                         print_data(&data);
    387606                        free_data(&data_prev);
    388                         data_prev = data;
    389                        
    390                         continue;
    391                 }
    392                
     607
     608                        c = -1;
     609                }
     610
     611                if (screen_mode == SCREEN_HELP && c >= 0) {
     612                        if (c == 'h' || c == '?')
     613                                c = -1;
     614                        /* go back to table and handle the key */
     615                        screen_mode = SCREEN_TABLE;
     616                }
     617
     618                if (screen_mode == SCREEN_SORT && c >= 0) {
     619                        for (size_t i = 0; i < data.table.num_columns; i++) {
     620                                if (data.table.columns[i].key == c) {
     621                                        sort_column = i;
     622                                        screen_mode = SCREEN_TABLE;
     623                                }
     624                        }
     625
     626                        c = -1;
     627                }
     628
    393629                switch (c) {
    394                         case 't':
    395                                 print_warning("Showing task statistics");
    396                                 op_mode = OP_TASKS;
     630                case -1: /* do nothing */
     631                        break;
     632                case 't':
     633                        op_mode = OP_TASKS;
     634                        break;
     635                case 'i':
     636                        op_mode = OP_IPC;
     637                        break;
     638                case 'e':
     639                        op_mode = OP_EXCS;
     640                        break;
     641                case 's':
     642                        screen_mode = SCREEN_SORT;
     643                        break;
     644                case 'r':
     645                        sort_reverse = -sort_reverse;
     646                        break;
     647                case 'h':
     648                case '?':
     649                        screen_mode = SCREEN_HELP;
     650                        break;
     651                case 'q':
     652                        goto out;
     653                case 'a':
     654                        if (op_mode == OP_EXCS) {
     655                                excs_all = !excs_all;
     656                                if (excs_all)
     657                                        show_warning("Showing all exceptions");
     658                                else
     659                                        show_warning("Showing only hot exceptions");
    397660                                break;
    398                         case 'i':
    399                                 print_warning("Showing IPC statistics");
    400                                 op_mode = OP_IPC;
    401                                 break;
    402                         case 'e':
    403                                 print_warning("Showing exception statistics");
    404                                 op_mode = OP_EXCS;
    405                                 break;
    406                         case 'h':
    407                                 print_warning("Showing help");
    408                                 op_mode = OP_HELP;
    409                                 break;
    410                         case 'q':
    411                                 goto out;
    412                         case 'a':
    413                                 if (op_mode == OP_EXCS) {
    414                                         excs_all = !excs_all;
    415                                         if (excs_all)
    416                                                 print_warning("Showing all exceptions");
    417                                         else
    418                                                 print_warning("Showing only hot exceptions");
    419                                         break;
    420                                 }
    421                         default:
    422                                 print_warning("Unknown command \"%c\", use \"h\" for help", c);
    423                                 break;
    424                 }
     661                        }
     662                        /* fallthrough */
     663                default:
     664                        show_warning("Unknown command \"%c\", use \"h\" for help", c);
     665                        continue; /* don't redraw */
     666                }
     667
     668                if ((ret = fill_table(&data)) != NULL) {
     669                        goto out;
     670                }
     671                sort_table(&data.table);
     672                print_data(&data);
    425673        }
    426674       
    427675out:
    428676        screen_done();
    429         free_data(&data_prev);
     677        free_data(&data);
    430678       
    431679        if (ret != NULL) {
  • uspace/dist/src/c/demos/top/top.h

    r1ab8539 r5042706  
    5151
    5252typedef enum {
    53         OP_TASKS,
    54         OP_IPC,
    55         OP_EXCS,
    56         OP_HELP
    57 } op_mode_t;
     53        SCREEN_TABLE,
     54        SCREEN_SORT,
     55        SCREEN_HELP,
     56} screen_mode_t;
    5857
    59 typedef enum {
    60         SORT_TASK_CYCLES
    61 } sort_mode_t;
    62 
    63 extern op_mode_t op_mode;
    64 extern sort_mode_t sort_mode;
    65 extern bool excs_all;
     58extern screen_mode_t screen_mode;
    6659
    6760typedef struct {
     
    8780} perc_exc_t;
    8881
     82typedef enum {
     83        FIELD_EMPTY, FIELD_UINT, FIELD_UINT_SUFFIX_BIN, FIELD_UINT_SUFFIX_DEC,
     84        FIELD_PERCENT, FIELD_STRING
     85} field_type_t;
     86
     87typedef 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
     96typedef struct {
     97        const char *name;
     98        char key;
     99        int width;
     100} column_t;
     101
     102typedef 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
    89110typedef struct {
    90111        time_t hours;
     
    107128        stats_task_t *tasks;
    108129        perc_task_t *tasks_perc;
    109         size_t *tasks_map;
    110130       
    111131        size_t threads_count;
     
    122142        uint64_t *ecycles_diff;
    123143        uint64_t *ecount_diff;
     144
     145        table_t table;
    124146} data_t;
    125147
Note: See TracChangeset for help on using the changeset viewer.