Changes in uspace/app/stats/stats.c [a63966d:894afff] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/stats/stats.c
ra63966d r894afff 52 52 #define MINUTE 60 53 53 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 54 67 static void list_tasks(void) 55 68 { … … 65 78 " [kcycles] [name\n"); 66 79 67 size_t i; 68 for (i = 0; i < count; i++) { 80 for (size_t i = 0; i < count; i++) { 69 81 uint64_t resmem; 70 82 uint64_t virtmem; … … 103 115 printf("[taskid] [threadid] [state ] [prio] [cpu ] [ucycles] [kcycles]\n"); 104 116 105 size_t i; 106 for (i = 0; i < count; i++) { 117 for (size_t i = 0; i < count; i++) { 107 118 if ((all) || (stats_threads[i].task_id == task_id)) { 108 119 uint64_t ucycles, kcycles; … … 130 141 } 131 142 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 132 165 static void list_cpus(void) 133 166 { … … 142 175 printf("[id] [MHz ] [busy cycles] [idle cycles]\n"); 143 176 144 size_t i; 145 for (i = 0; i < count; i++) { 177 for (size_t i = 0; i < count; i++) { 146 178 printf("%-4u ", cpus[i].id); 147 179 if (cpus[i].active) { … … 174 206 printf("%s: Load average: ", NAME); 175 207 176 size_t i; 177 for (i = 0; i < count; i++) { 208 for (size_t i = 0; i < count; i++) { 178 209 if (i > 0) 179 210 printf(" "); … … 197 228 } 198 229 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 199 367 static void usage(const char *name) 200 368 { 201 369 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" 203 371 "\n" 204 372 "Options:\n" 205 "\t-t task_id\n" 206 "\t--task=task_id\n" 373 "\t-t task_id | --task=task_id\n" 207 374 "\t\tList threads of the given task\n" 208 375 "\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" 211 380 "\t\tList all threads\n" 212 381 "\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" 215 386 "\t\tList CPUs\n" 216 387 "\n" 217 "\t-l\n" 218 "\t--load\n" 388 "\t-l | --load\n" 219 389 "\t\tPrint system load\n" 220 390 "\n" 221 "\t-u\n" 222 "\t--uptime\n" 391 "\t-u | --uptime\n" 223 392 "\t\tPrint system uptime\n" 224 393 "\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" 227 398 "\t\tPrint this usage information\n" 228 399 "\n" … … 233 404 int main(int argc, char *argv[]) 234 405 { 235 bool toggle_tasks = true; 236 bool toggle_threads = false; 406 output_toggle_t output_toggle = LIST_TASKS; 237 407 bool toggle_all = false; 238 bool toggle_cpus = false;239 bool toggle_load = false;240 bool toggle_uptime = false;241 242 408 task_id_t task_id = 0; 243 409 244 int i; 245 for (i = 1; i < argc; i++) { 410 for (int i = 1; i < argc; i++) { 246 411 int off; 247 412 … … 252 417 } 253 418 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 254 426 /* 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; 258 429 toggle_all = true; 259 430 continue; 260 431 } 261 432 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 */ 270 450 if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) { 271 451 // TODO: Support for 64b range … … 273 453 errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off); 274 454 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]); 276 456 return -1; 277 457 } … … 279 459 task_id = tmp; 280 460 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; 283 468 continue; 284 469 } … … 286 471 /* Load */ 287 472 if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) { 288 toggle_tasks = false; 289 toggle_load = true; 473 output_toggle = PRINT_LOAD; 290 474 continue; 291 475 } … … 293 477 /* Uptime */ 294 478 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: 302 492 list_tasks(); 303 304 if (toggle_threads)493 break; 494 case LIST_THREADS: 305 495 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: 308 501 list_cpus(); 309 310 if (toggle_load)502 break; 503 case PRINT_LOAD: 311 504 print_load(); 312 313 if (toggle_uptime)505 break; 506 case PRINT_UPTIME: 314 507 print_uptime(); 508 break; 509 case PRINT_ARCH: 510 print_arch(); 511 break; 512 } 315 513 316 514 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.