Ignore:
File:
1 edited

Legend:

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

    r894afff ra63966d  
    5252#define MINUTE  60
    5353
    54 #define KERNEL_NAME  "kernel"
    55 #define INIT_PREFIX  "init:"
    56 
    57 typedef enum {
    58         LIST_TASKS,
    59         LIST_THREADS,
    60         LIST_IPCCS,
    61         LIST_CPUS,
    62         PRINT_LOAD,
    63         PRINT_UPTIME,
    64         PRINT_ARCH
    65 } output_toggle_t;
    66 
    6754static void list_tasks(void)
    6855{
     
    7865            " [kcycles] [name\n");
    7966
    80         for (size_t i = 0; i < count; i++) {
     67        size_t i;
     68        for (i = 0; i < count; i++) {
    8169                uint64_t resmem;
    8270                uint64_t virtmem;
     
    115103        printf("[taskid] [threadid] [state ] [prio] [cpu ] [ucycles] [kcycles]\n");
    116104
    117         for (size_t i = 0; i < count; i++) {
     105        size_t i;
     106        for (i = 0; i < count; i++) {
    118107                if ((all) || (stats_threads[i].task_id == task_id)) {
    119108                        uint64_t ucycles, kcycles;
     
    141130}
    142131
    143 static void list_ipccs(task_id_t task_id, bool all)
    144 {
    145         size_t count;
    146         stats_ipcc_t *stats_ipccs = stats_get_ipccs(&count);
    147 
    148         if (stats_ipccs == NULL) {
    149                 fprintf(stderr, "%s: Unable to get IPC connections\n", NAME);
    150                 return;
    151         }
    152 
    153         printf("[caller] [callee]\n");
    154 
    155         for (size_t i = 0; i < count; i++) {
    156                 if ((all) || (stats_ipccs[i].caller == task_id)) {
    157                         printf("%-8" PRIu64 " %-8" PRIu64 "\n",
    158                             stats_ipccs[i].caller, stats_ipccs[i].callee);
    159                 }
    160         }
    161 
    162         free(stats_ipccs);
    163 }
    164 
    165132static void list_cpus(void)
    166133{
     
    175142        printf("[id] [MHz     ] [busy cycles] [idle cycles]\n");
    176143
    177         for (size_t i = 0; i < count; i++) {
     144        size_t i;
     145        for (i = 0; i < count; i++) {
    178146                printf("%-4u ", cpus[i].id);
    179147                if (cpus[i].active) {
     
    206174        printf("%s: Load average: ", NAME);
    207175
    208         for (size_t i = 0; i < count; i++) {
     176        size_t i;
     177        for (i = 0; i < count; i++) {
    209178                if (i > 0)
    210179                        printf(" ");
     
    228197}
    229198
    230 static char *escape_dot(const char *str)
    231 {
    232         size_t size = 0;
    233         for (size_t i = 0; str[i] != 0; i++) {
    234                 if (str[i] == '"')
    235                         size++;
    236 
    237                 size++;
    238         }
    239 
    240         char *escaped_str = calloc(size + 1, sizeof(char));
    241         if (escaped_str == NULL)
    242                 return NULL;
    243 
    244         size_t pos = 0;
    245         for (size_t i = 0; str[i] != 0; i++) {
    246                 if (str[i] == '"') {
    247                         escaped_str[pos] = '\\';
    248                         pos++;
    249                 }
    250 
    251                 escaped_str[pos] = str[i];
    252                 pos++;
    253         }
    254 
    255         escaped_str[pos] = 0;
    256 
    257         return escaped_str;
    258 }
    259 
    260 static void print_arch(void)
    261 {
    262         size_t count_tasks;
    263         stats_task_t *stats_tasks = stats_get_tasks(&count_tasks);
    264 
    265         if (stats_tasks == NULL) {
    266                 fprintf(stderr, "%s: Unable to get tasks\n", NAME);
    267                 return;
    268         }
    269 
    270         size_t count_ipccs;
    271         stats_ipcc_t *stats_ipccs = stats_get_ipccs(&count_ipccs);
    272 
    273         if (stats_ipccs == NULL) {
    274                 fprintf(stderr, "%s: Unable to get IPC connections\n", NAME);
    275                 return;
    276         }
    277 
    278         /* Global dot language attributes */
    279         printf("digraph HelenOS {\n");
    280         printf("\tlayout=sfdp\n");
    281         printf("\t// layout=neato\n");
    282         printf("\tsplines=true\n");
    283         printf("\t// splines=ortho\n");
    284         printf("\tconcentrate=true\n");
    285         printf("\tcenter=true\n");
    286         printf("\toverlap=false\n");
    287         printf("\toutputorder=edgesfirst\n");
    288         printf("\tfontsize=12\n");
    289         printf("\tnode [shape=component style=filled color=red "
    290             "fillcolor=yellow]\n\t\n");
    291 
    292         bool kernel_found = false;
    293         task_id_t kernel_id = 0;
    294 
    295         /* Tasks as vertices (components) */
    296         for (size_t i = 0; i < count_tasks; i++) {
    297                 /* Kernel task */
    298                 bool kernel = (str_cmp(stats_tasks[i].name, KERNEL_NAME) == 0);
    299 
    300                 /* Init task */
    301                 bool init = str_test_prefix(stats_tasks[i].name, INIT_PREFIX);
    302 
    303                 char *escaped_name = NULL;
    304 
    305                 if (init)
    306                         escaped_name = escape_dot(str_suffix(stats_tasks[i].name,
    307                             str_length(INIT_PREFIX)));
    308                 else
    309                         escaped_name = escape_dot(stats_tasks[i].name);
    310 
    311                 if (escaped_name == NULL)
    312                         continue;
    313 
    314                 if (kernel) {
    315                         if (kernel_found) {
    316                                 fprintf(stderr, "%s: Duplicate kernel tasks\n", NAME);
    317                         } else {
    318                                 kernel_found = true;
    319                                 kernel_id = stats_tasks[i].task_id;
    320                         }
    321 
    322                         printf("\ttask%" PRIu64 " [label=\"%s\" shape=invtrapezium "
    323                             "fillcolor=gold]\n", stats_tasks[i].task_id, escaped_name);
    324                 } else if (init)
    325                         printf("\ttask%" PRIu64 " [label=\"%s\" fillcolor=orange]\n",
    326                             stats_tasks[i].task_id, escaped_name);
    327                 else
    328                         printf("\ttask%" PRIu64 " [label=\"%s\"]\n", stats_tasks[i].task_id,
    329                             escaped_name);
    330 
    331                 free(escaped_name);
    332         }
    333 
    334         printf("\t\n");
    335 
    336         if (kernel_found) {
    337                 /*
    338                  * Add an invisible edge from all user
    339                  * space tasks to the kernel to increase
    340                  * the kernel ranking.
    341                  */
    342 
    343                 for (size_t i = 0; i < count_tasks; i++) {
    344                         /* Skip the kernel itself */
    345                         if (stats_tasks[i].task_id == kernel_id)
    346                                 continue;
    347 
    348                         printf("\ttask%" PRIu64 " -> task%" PRIu64 " [style=\"invis\"]\n",
    349                             stats_tasks[i].task_id, kernel_id);
    350                 }
    351         }
    352 
    353         printf("\t\n");
    354 
    355         /* IPC connections as edges */
    356         for (size_t i = 0; i < count_ipccs; i++) {
    357                 printf("\ttask%" PRIu64 " -> task%" PRIu64 "\n",
    358                     stats_ipccs[i].caller, stats_ipccs[i].callee);
    359         }
    360 
    361         printf("}\n");
    362 
    363         free(stats_tasks);
    364         free(stats_ipccs);
    365 }
    366 
    367199static void usage(const char *name)
    368200{
    369201        printf(
    370             "Usage: %s [-t task_id] [-i task_id] [-at] [-ai] [-c] [-l] [-u] [-d]\n"
     202            "Usage: %s [-t task_id] [-a] [-c] [-l] [-u]\n"
    371203            "\n"
    372204            "Options:\n"
    373             "\t-t task_id | --task=task_id\n"
     205            "\t-t task_id\n"
     206            "\t--task=task_id\n"
    374207            "\t\tList threads of the given task\n"
    375208            "\n"
    376             "\t-i task_id | --ipcc=task_id\n"
    377             "\t\tList IPC connections of the given task\n"
    378             "\n"
    379             "\t-at | --all-threads\n"
     209            "\t-a\n"
     210            "\t--all\n"
    380211            "\t\tList all threads\n"
    381212            "\n"
    382             "\t-ai | --all-ipccs\n"
    383             "\t\tList all IPC connections\n"
    384             "\n"
    385             "\t-c | --cpus\n"
     213            "\t-c\n"
     214            "\t--cpus\n"
    386215            "\t\tList CPUs\n"
    387216            "\n"
    388             "\t-l | --load\n"
     217            "\t-l\n"
     218            "\t--load\n"
    389219            "\t\tPrint system load\n"
    390220            "\n"
    391             "\t-u | --uptime\n"
     221            "\t-u\n"
     222            "\t--uptime\n"
    392223            "\t\tPrint system uptime\n"
    393224            "\n"
    394             "\t-d | --design\n"
    395             "\t\tPrint the current system architecture graph\n"
    396             "\n"
    397             "\t-h | --help\n"
     225            "\t-h\n"
     226            "\t--help\n"
    398227            "\t\tPrint this usage information\n"
    399228            "\n"
     
    404233int main(int argc, char *argv[])
    405234{
    406         output_toggle_t output_toggle = LIST_TASKS;
     235        bool toggle_tasks = true;
     236        bool toggle_threads = false;
    407237        bool toggle_all = false;
     238        bool toggle_cpus = false;
     239        bool toggle_load = false;
     240        bool toggle_uptime = false;
     241
    408242        task_id_t task_id = 0;
    409243
    410         for (int i = 1; i < argc; i++) {
     244        int i;
     245        for (i = 1; i < argc; i++) {
    411246                int off;
    412247
     
    417252                }
    418253
    419                 /* All IPC connections */
    420                 if ((off = arg_parse_short_long(argv[i], "-ai", "--all-ipccs")) != -1) {
    421                         output_toggle = LIST_IPCCS;
     254                /* All threads */
     255                if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
     256                        toggle_tasks = false;
     257                        toggle_threads = true;
    422258                        toggle_all = true;
    423259                        continue;
    424260                }
    425261
    426                 /* All threads */
    427                 if ((off = arg_parse_short_long(argv[i], "-at", "--all-threads")) != -1) {
    428                         output_toggle = LIST_THREADS;
    429                         toggle_all = true;
    430                         continue;
    431                 }
    432 
    433                 /* IPC connections */
    434                 if ((off = arg_parse_short_long(argv[i], "-i", "--ipcc=")) != -1) {
    435                         // TODO: Support for 64b range
    436                         int tmp;
    437                         errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off);
    438                         if (ret != EOK) {
    439                                 printf("%s: Malformed task id '%s'\n", NAME, argv[i]);
    440                                 return -1;
    441                         }
    442 
    443                         task_id = tmp;
    444 
    445                         output_toggle = LIST_IPCCS;
    446                         continue;
    447                 }
    448 
    449                 /* Tasks */
     262                /* CPUs */
     263                if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
     264                        toggle_tasks = false;
     265                        toggle_cpus = true;
     266                        continue;
     267                }
     268
     269                /* Threads */
    450270                if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) {
    451271                        // TODO: Support for 64b range
     
    453273                        errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off);
    454274                        if (ret != EOK) {
    455                                 printf("%s: Malformed task id '%s'\n", NAME, argv[i]);
     275                                printf("%s: Malformed task_id '%s'\n", NAME, argv[i]);
    456276                                return -1;
    457277                        }
     
    459279                        task_id = tmp;
    460280
    461                         output_toggle = LIST_THREADS;
    462                         continue;
    463                 }
    464 
    465                 /* CPUs */
    466                 if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
    467                         output_toggle = LIST_CPUS;
     281                        toggle_tasks = false;
     282                        toggle_threads = true;
    468283                        continue;
    469284                }
     
    471286                /* Load */
    472287                if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) {
    473                         output_toggle = PRINT_LOAD;
     288                        toggle_tasks = false;
     289                        toggle_load = true;
    474290                        continue;
    475291                }
     
    477293                /* Uptime */
    478294                if ((off = arg_parse_short_long(argv[i], "-u", "--uptime")) != -1) {
    479                         output_toggle = PRINT_UPTIME;
    480                         continue;
    481                 }
    482 
    483                 /* Architecture */
    484                 if ((off = arg_parse_short_long(argv[i], "-d", "--design")) != -1) {
    485                         output_toggle = PRINT_ARCH;
    486                         continue;
    487                 }
    488         }
    489 
    490         switch (output_toggle) {
    491         case LIST_TASKS:
     295                        toggle_tasks = false;
     296                        toggle_uptime = true;
     297                        continue;
     298                }
     299        }
     300
     301        if (toggle_tasks)
    492302                list_tasks();
    493                 break;
    494         case LIST_THREADS:
     303
     304        if (toggle_threads)
    495305                list_threads(task_id, toggle_all);
    496                 break;
    497         case LIST_IPCCS:
    498                 list_ipccs(task_id, toggle_all);
    499                 break;
    500         case LIST_CPUS:
     306
     307        if (toggle_cpus)
    501308                list_cpus();
    502                 break;
    503         case PRINT_LOAD:
     309
     310        if (toggle_load)
    504311                print_load();
    505                 break;
    506         case PRINT_UPTIME:
     312
     313        if (toggle_uptime)
    507314                print_uptime();
    508                 break;
    509         case PRINT_ARCH:
    510                 print_arch();
    511                 break;
    512         }
    513315
    514316        return 0;
Note: See TracChangeset for help on using the changeset viewer.