Changeset 5042706 in mainline
- Timestamp:
- 2014-11-14T19:57:51Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 99d8c82, b412168
- Parents:
- 1ab8539
- Location:
- uspace/dist/src/c/demos
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/dist/src/c/demos/tetris/shapes.c
r1ab8539 r5042706 69 69 70 70 const struct shape shapes[] = { 71 /* 0 */ { 7, 7, { TL, TC, MR }, 0x ff042d},72 /* 1 */ { 8, 8, { TC, TR, ML }, 0x ff9304},73 /* 2 */ { 9, 11, { ML, MR, BC }, 0x beff04},74 /* 3 */ { 3, 3, { TL, TC, ML }, 0x 63ff04},75 /* 4 */ { 12, 14, { ML, BL, MR }, 0x ce04ff},76 /* 5 */ { 15, 17, { ML, BR, MR }, 0xff 04cf},77 /* 6 */ { 18, 18, { ML, MR, 2 }, 0x 7604ff}, /* sticks out */78 /* 7 */ { 0, 0, { TC, ML, BL }, 0x ff042d},79 /* 8 */ { 1, 1, { TC, MR, BR }, 0x ff9304},80 /* 9 */ { 10, 2, { TC, MR, BC }, 0x beff04},81 /* 10 */ { 11, 9, { TC, ML, MR }, 0x beff04},82 /* 11 */ { 2, 10, { TC, ML, BC }, 0x beff04},83 /* 12 */ { 13, 4, { TC, BC, BR }, 0x ce04ff},84 /* 13 */ { 14, 12, { TR, ML, MR }, 0x ce04ff},85 /* 14 */ { 4, 13, { TL, TC, BC }, 0x ce04ff},86 /* 15 */ { 16, 5, { TR, TC, BC }, 0xff 04cf},87 /* 16 */ { 17, 15, { TL, MR, ML }, 0xff 04cf},88 /* 17 */ { 5, 16, { TC, BC, BL }, 0xff 04cf},89 /* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0x 7604ff} /* 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 */ 90 90 }; 91 91 -
uspace/dist/src/c/demos/top/screen.c
r1ab8539 r5042706 37 37 38 38 #include <stdio.h> 39 #include <stdlib.h> 39 40 #include <io/console.h> 40 41 #include <io/style.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" … … 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 { … … 64 69 console_flush(console); 65 70 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); 66 77 } 67 78 … … 126 137 void screen_done(void) 127 138 { 139 free(warning_text); 140 warning_text = NULL; 141 128 142 screen_restart(true); 129 143 … … 277 291 } 278 292 279 static inline void print_ tasks_head(void)293 static inline void print_help_head(void) 280 294 { 281 295 screen_style_inverted(); 282 printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]" 283 " [%%user] [%%kern] [name"); 296 printf("Help"); 284 297 screen_newline(); 285 298 screen_style_normal(); 286 299 } 287 300 288 static inline void print_tasks(data_t *data) 289 { 290 sysarg_t cols; 291 sysarg_t rows; 292 screen_get_size(&cols, &rows); 301 static 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(); 293 340 294 341 sysarg_t col; … … 296 343 screen_get_pos(&col, &row); 297 344 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 345 while (row < rows) { 327 346 screen_newline(); … … 330 349 } 331 350 332 static inline void print_ipc_head(void) 333 { 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 334 357 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 } 337 372 screen_newline(); 338 373 screen_style_normal(); 339 374 } 340 375 341 static inline void print_ ipc(data_t *data)376 static inline void print_table(const table_t *table) 342 377 { 343 378 sysarg_t cols; … … 350 385 351 386 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 } 392 441 } 393 442 … … 398 447 } 399 448 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) 449 static inline void print_sort(table_t *table) 409 450 { 410 451 sysarg_t cols; … … 415 456 sysarg_t row; 416 457 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); 441 462 screen_newline(); 442 463 row++; … … 449 470 } 450 471 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 } 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 … … 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); 494 print_warning(); 495 496 switch (screen_mode) { 497 case SCREEN_TABLE: 498 print_table_head(&data->table); 499 print_table(&data->table); 503 500 break; 504 case OP_IPC: 505 print_ipc_head(); 506 print_ipc(data); 501 case SCREEN_SORT: 502 print_sort(&data->table); 507 503 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(); 514 506 print_help(); 515 507 } … … 518 510 } 519 511 520 void print_warning(const char *fmt, ...) 521 { 522 screen_moveto(warn_col, warn_row); 523 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 524 524 va_list args; 525 525 va_start(args, fmt); 526 v printf(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 } … … 555 558 cons_event_t event; 556 559 560 warning_timeleft -= timeleft; 557 561 if (!console_get_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 == CEV_KEY && event.ev.key.type == KEY_PRESS) -
uspace/dist/src/c/demos/top/screen.h
r1ab8539 r5042706 44 44 extern void screen_done(void); 45 45 extern void print_data(data_t *); 46 extern void print_warning(const char *, ...)46 extern void show_warning(const char *, ...) 47 47 PRINTF_ATTRIBUTE(1, 2); 48 48 -
uspace/dist/src/c/demos/top/top.c
r1ab8539 r5042706 55 55 #define MINUTE 60 56 56 57 op_mode_t op_mode = OP_TASKS; 58 sort_mode_t sort_mode = SORT_TASK_CYCLES; 59 bool excs_all = false; 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; 60 133 61 134 static const char *read_data(data_t *target) … … 67 140 target->tasks = NULL; 68 141 target->tasks_perc = NULL; 69 target->tasks_map = NULL;70 142 target->threads = NULL; 71 143 target->exceptions = NULL; … … 76 148 target->ecycles_diff = NULL; 77 149 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; 78 155 79 156 /* Get current time */ 80 157 struct timeval time; 81 if (gettimeofday(&time, NULL) != EOK) 82 return "Cannot get time of day"; 158 gettimeofday(&time, NULL); 83 159 84 160 target->hours = (time.tv_sec % DAY) / HOUR; … … 87 163 88 164 /* 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; 94 172 95 173 /* Get load */ … … 117 195 if (target->tasks_perc == NULL) 118 196 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";124 197 125 198 /* Get threads */ … … 289 362 static int cmp_data(void *a, void *b, void *arg) 290 363 { 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 304 396 return 0; 305 397 } 306 398 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); 399 static 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 408 static 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 447 static 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 480 static 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 516 static 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; 316 532 } 317 533 … … 356 572 if (target->ecount_diff != NULL) 357 573 free(target->ecount_diff); 574 575 if (target->table.fields != NULL) 576 free(target->table.fields); 358 577 } 359 578 … … 367 586 printf("Reading initial data...\n"); 368 587 369 if ((ret = read_data(&data _prev)) != NULL)588 if ((ret = read_data(&data)) != NULL) 370 589 goto out; 371 590 372 591 /* Compute some rubbish to have initialised values */ 373 compute_percentages(&data _prev, &data_prev);592 compute_percentages(&data, &data); 374 593 375 594 /* And paint screen until death */ 376 595 while (true) { 377 596 int c = tgetchar(UPDATE_INTERVAL); 378 if (c < 0) { 597 598 if (c < 0) { /* timeout */ 599 data_prev = data; 379 600 if ((ret = read_data(&data)) != NULL) { 380 free_data(&data );601 free_data(&data_prev); 381 602 goto out; 382 603 } 383 604 384 605 compute_percentages(&data_prev, &data); 385 sort_data(&data);386 print_data(&data);387 606 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 393 629 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"); 397 660 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); 425 673 } 426 674 427 675 out: 428 676 screen_done(); 429 free_data(&data _prev);677 free_data(&data); 430 678 431 679 if (ret != NULL) { -
uspace/dist/src/c/demos/top/top.h
r1ab8539 r5042706 51 51 52 52 typedef 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; 58 57 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; 58 extern screen_mode_t screen_mode; 66 59 67 60 typedef struct { … … 87 80 } perc_exc_t; 88 81 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 89 110 typedef struct { 90 111 time_t hours; … … 107 128 stats_task_t *tasks; 108 129 perc_task_t *tasks_perc; 109 size_t *tasks_map;110 130 111 131 size_t threads_count; … … 122 142 uint64_t *ecycles_diff; 123 143 uint64_t *ecount_diff; 144 145 table_t table; 124 146 } data_t; 125 147
Note:
See TracChangeset
for help on using the changeset viewer.