Ignore:
File:
1 edited

Legend:

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

    ra63966d r894afff  
    5252#define MINUTE  60
    5353
     54#define KERNEL_NAME  "kernel"
     55#define INIT_PREFIX  "init:"
     56
     57typedef 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
    5467static void list_tasks(void)
    5568{
     
    6578            " [kcycles] [name\n");
    6679
    67         size_t i;
    68         for (i = 0; i < count; i++) {
     80        for (size_t i = 0; i < count; i++) {
    6981                uint64_t resmem;
    7082                uint64_t virtmem;
     
    103115        printf("[taskid] [threadid] [state ] [prio] [cpu ] [ucycles] [kcycles]\n");
    104116
    105         size_t i;
    106         for (i = 0; i < count; i++) {
     117        for (size_t i = 0; i < count; i++) {
    107118                if ((all) || (stats_threads[i].task_id == task_id)) {
    108119                        uint64_t ucycles, kcycles;
     
    130141}
    131142
     143static 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
    132165static void list_cpus(void)
    133166{
     
    142175        printf("[id] [MHz     ] [busy cycles] [idle cycles]\n");
    143176
    144         size_t i;
    145         for (i = 0; i < count; i++) {
     177        for (size_t i = 0; i < count; i++) {
    146178                printf("%-4u ", cpus[i].id);
    147179                if (cpus[i].active) {
     
    174206        printf("%s: Load average: ", NAME);
    175207
    176         size_t i;
    177         for (i = 0; i < count; i++) {
     208        for (size_t i = 0; i < count; i++) {
    178209                if (i > 0)
    179210                        printf(" ");
     
    197228}
    198229
     230static 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
     260static 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
    199367static void usage(const char *name)
    200368{
    201369        printf(
    202             "Usage: %s [-t task_id] [-a] [-c] [-l] [-u]\n"
     370            "Usage: %s [-t task_id] [-i task_id] [-at] [-ai] [-c] [-l] [-u] [-d]\n"
    203371            "\n"
    204372            "Options:\n"
    205             "\t-t task_id\n"
    206             "\t--task=task_id\n"
     373            "\t-t task_id | --task=task_id\n"
    207374            "\t\tList threads of the given task\n"
    208375            "\n"
    209             "\t-a\n"
    210             "\t--all\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"
    211380            "\t\tList all threads\n"
    212381            "\n"
    213             "\t-c\n"
    214             "\t--cpus\n"
     382            "\t-ai | --all-ipccs\n"
     383            "\t\tList all IPC connections\n"
     384            "\n"
     385            "\t-c | --cpus\n"
    215386            "\t\tList CPUs\n"
    216387            "\n"
    217             "\t-l\n"
    218             "\t--load\n"
     388            "\t-l | --load\n"
    219389            "\t\tPrint system load\n"
    220390            "\n"
    221             "\t-u\n"
    222             "\t--uptime\n"
     391            "\t-u | --uptime\n"
    223392            "\t\tPrint system uptime\n"
    224393            "\n"
    225             "\t-h\n"
    226             "\t--help\n"
     394            "\t-d | --design\n"
     395            "\t\tPrint the current system architecture graph\n"
     396            "\n"
     397            "\t-h | --help\n"
    227398            "\t\tPrint this usage information\n"
    228399            "\n"
     
    233404int main(int argc, char *argv[])
    234405{
    235         bool toggle_tasks = true;
    236         bool toggle_threads = false;
     406        output_toggle_t output_toggle = LIST_TASKS;
    237407        bool toggle_all = false;
    238         bool toggle_cpus = false;
    239         bool toggle_load = false;
    240         bool toggle_uptime = false;
    241 
    242408        task_id_t task_id = 0;
    243409
    244         int i;
    245         for (i = 1; i < argc; i++) {
     410        for (int i = 1; i < argc; i++) {
    246411                int off;
    247412
     
    252417                }
    253418
     419                /* All IPC connections */
     420                if ((off = arg_parse_short_long(argv[i], "-ai", "--all-ipccs")) != -1) {
     421                        output_toggle = LIST_IPCCS;
     422                        toggle_all = true;
     423                        continue;
     424                }
     425
    254426                /* All threads */
    255                 if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
    256                         toggle_tasks = false;
    257                         toggle_threads = true;
     427                if ((off = arg_parse_short_long(argv[i], "-at", "--all-threads")) != -1) {
     428                        output_toggle = LIST_THREADS;
    258429                        toggle_all = true;
    259430                        continue;
    260431                }
    261432
    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 */
     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 */
    270450                if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) {
    271451                        // TODO: Support for 64b range
     
    273453                        errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off);
    274454                        if (ret != EOK) {
    275                                 printf("%s: Malformed task_id '%s'\n", NAME, argv[i]);
     455                                printf("%s: Malformed task id '%s'\n", NAME, argv[i]);
    276456                                return -1;
    277457                        }
     
    279459                        task_id = tmp;
    280460
    281                         toggle_tasks = false;
    282                         toggle_threads = true;
     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;
    283468                        continue;
    284469                }
     
    286471                /* Load */
    287472                if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) {
    288                         toggle_tasks = false;
    289                         toggle_load = true;
     473                        output_toggle = PRINT_LOAD;
    290474                        continue;
    291475                }
     
    293477                /* Uptime */
    294478                if ((off = arg_parse_short_long(argv[i], "-u", "--uptime")) != -1) {
    295                         toggle_tasks = false;
    296                         toggle_uptime = true;
    297                         continue;
    298                 }
    299         }
    300 
    301         if (toggle_tasks)
     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:
    302492                list_tasks();
    303 
    304         if (toggle_threads)
     493                break;
     494        case LIST_THREADS:
    305495                list_threads(task_id, toggle_all);
    306 
    307         if (toggle_cpus)
     496                break;
     497        case LIST_IPCCS:
     498                list_ipccs(task_id, toggle_all);
     499                break;
     500        case LIST_CPUS:
    308501                list_cpus();
    309 
    310         if (toggle_load)
     502                break;
     503        case PRINT_LOAD:
    311504                print_load();
    312 
    313         if (toggle_uptime)
     505                break;
     506        case PRINT_UPTIME:
    314507                print_uptime();
     508                break;
     509        case PRINT_ARCH:
     510                print_arch();
     511                break;
     512        }
    315513
    316514        return 0;
Note: See TracChangeset for help on using the changeset viewer.