~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/app/top/screen.c

MergeĀ fromĀ lp:~wtachi/helenos/top.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 */
37
37
 
38
38
#include <stdio.h>
 
39
#include <stdlib.h>
39
40
#include <io/console.h>
40
41
#include <io/style.h>
41
42
#include <vfs/vfs.h>
42
43
#include <stdarg.h>
43
44
#include <stats.h>
44
45
#include <inttypes.h>
 
46
#include <macros.h>
45
47
#include "screen.h"
46
48
#include "top.h"
47
49
 
48
50
#define USEC_COUNT  1000000
49
51
 
50
 
static sysarg_t warn_col = 0;
51
 
static sysarg_t warn_row = 0;
52
52
static suseconds_t timeleft = 0;
53
53
 
54
54
console_ctrl_t *console;
55
55
 
 
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
 
56
61
static void screen_style_normal(void)
57
62
{
58
63
        console_flush(console);
65
70
        console_set_style(console, STYLE_INVERTED);
66
71
}
67
72
 
 
73
static void screen_style_emphasis(void)
 
74
{
 
75
        console_flush(console);
 
76
        console_set_style(console, STYLE_EMPHASIS);
 
77
}
 
78
 
68
79
static void screen_moveto(sysarg_t col, sysarg_t row)
69
80
{
70
81
        console_flush(console);
125
136
 
126
137
void screen_done(void)
127
138
{
 
139
        free(warning_text);
 
140
        warning_text = NULL;
 
141
 
128
142
        screen_restart(true);
129
143
        
130
144
        console_flush(console);
276
290
        screen_newline();
277
291
}
278
292
 
279
 
static inline void print_tasks_head(void)
280
 
{
281
 
        screen_style_inverted();
282
 
        printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
283
 
            " [%%user] [%%kern] [name");
284
 
        screen_newline();
285
 
        screen_style_normal();
286
 
}
287
 
 
288
 
static inline void print_tasks(data_t *data)
289
 
{
290
 
        sysarg_t cols;
291
 
        sysarg_t rows;
292
 
        screen_get_size(&cols, &rows);
293
 
        
294
 
        sysarg_t col;
295
 
        sysarg_t row;
296
 
        screen_get_pos(&col, &row);
297
 
        
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
 
        
326
 
        while (row < rows) {
327
 
                screen_newline();
328
 
                row++;
329
 
        }
330
 
}
331
 
 
332
 
static 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
 
 
341
 
static inline void print_ipc(data_t *data)
342
 
{
343
 
        sysarg_t cols;
344
 
        sysarg_t rows;
345
 
        screen_get_size(&cols, &rows);
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
 
 
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)
409
 
{
410
 
        sysarg_t cols;
411
 
        sysarg_t rows;
412
 
        screen_get_size(&cols, &rows);
413
 
        
414
 
        sysarg_t col;
415
 
        sysarg_t row;
416
 
        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
 
                
441
 
                screen_newline();
442
 
                row++;
443
 
        }
444
 
        
445
 
        while (row < rows) {
446
 
                screen_newline();
447
 
                row++;
448
 
        }
449
 
}
450
 
 
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);
 
293
static inline void print_help_head(void)
 
294
{
 
295
        screen_style_inverted();
 
296
        printf("Help");
 
297
        screen_newline();
 
298
        screen_style_normal();
 
299
}
 
300
 
 
301
static inline void print_help(void)
 
302
{
 
303
        sysarg_t cols;
 
304
        sysarg_t rows;
 
305
        screen_get_size(&cols, &rows);
460
306
        
461
307
        screen_newline();
462
308
        
474
320
        
475
321
        printf("      a .. toggle display of all/hot exceptions");
476
322
        screen_newline();
477
 
        
478
 
        row += 6;
479
 
        
480
 
        while (row < rows) {
481
 
                screen_newline();
482
 
                row++;
483
 
        }
 
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
        
 
341
        sysarg_t col;
 
342
        sysarg_t row;
 
343
        screen_get_pos(&col, &row);
 
344
        
 
345
        while (row < rows) {
 
346
                screen_newline();
 
347
                row++;
 
348
        }
 
349
}
 
350
 
 
351
static 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
 
 
357
        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
        }
 
372
        screen_newline();
 
373
        screen_style_normal();
 
374
}
 
375
 
 
376
static inline void print_table(const table_t *table)
 
377
{
 
378
        sysarg_t cols;
 
379
        sysarg_t rows;
 
380
        screen_get_size(&cols, &rows);
 
381
        
 
382
        sysarg_t col;
 
383
        sysarg_t row;
 
384
        screen_get_pos(&col, &row);
 
385
        
 
386
        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
                }
 
441
        }
 
442
        
 
443
        while (row < rows) {
 
444
                screen_newline();
 
445
                row++;
 
446
        }
 
447
}
 
448
 
 
449
static inline void print_sort(table_t *table)
 
450
{
 
451
        sysarg_t cols;
 
452
        sysarg_t rows;
 
453
        screen_get_size(&cols, &rows);
 
454
        
 
455
        sysarg_t col;
 
456
        sysarg_t row;
 
457
        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);
 
462
                screen_newline();
 
463
                row++;
 
464
        }
 
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();
484
484
}
485
485
 
486
486
void print_data(data_t *data)
491
491
        print_thread_summary(data);
492
492
        print_cpu_info(data);
493
493
        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);
503
 
                break;
504
 
        case OP_IPC:
505
 
                print_ipc_head();
506
 
                print_ipc(data);
507
 
                break;
508
 
        case OP_EXCS:
509
 
                print_excs_head();
510
 
                print_excs(data);
511
 
                break;
512
 
        case OP_HELP:
513
 
                print_tasks_head();
 
494
        print_warning();
 
495
        
 
496
        switch (screen_mode) {
 
497
        case SCREEN_TABLE:
 
498
                print_table_head(&data->table);
 
499
                print_table(&data->table);
 
500
                break;
 
501
        case SCREEN_SORT:
 
502
                print_sort(&data->table);
 
503
                break;
 
504
        case SCREEN_HELP:
 
505
                print_help_head();
514
506
                print_help();
515
507
        }
516
508
        
517
509
        console_flush(console);
518
510
}
519
511
 
520
 
void print_warning(const char *fmt, ...)
 
512
void show_warning(const char *fmt, ...)
521
513
{
522
 
        screen_moveto(warn_col, warn_row);
523
 
        
 
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
 
524
524
        va_list args;
525
525
        va_start(args, fmt);
526
 
        vprintf(fmt, args);
 
526
        vsnprintf(warning_text, warning_text_size, fmt, args);
527
527
        va_end(args);
528
528
        
529
 
        screen_newline();
 
529
        warning_timeleft = 2 * USEC_COUNT;
 
530
 
 
531
        screen_moveto(warning_col, warning_row);
 
532
        print_warning();
530
533
        console_flush(console);
531
534
}
532
535
 
554
557
        while (c == 0) {
555
558
                kbd_event_t event;
556
559
                
 
560
                warning_timeleft -= timeleft;
557
561
                if (!console_get_kbd_event_timeout(console, &event, &timeleft)) {
558
562
                        timeleft = 0;
559
563
                        return -1;
560
564
                }
 
565
                warning_timeleft += timeleft;
561
566
                
562
567
                if (event.type == KEY_PRESS)
563
568
                        c = event.c;