Changeset a6302ae in mainline
- Timestamp:
- 2019-12-11T10:49:48Z (5 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fe7bcf1
- Parents:
- ad211c8
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
abi/include/abi/sysinfo.h
rad211c8 ra6302ae 125 125 } stats_thread_t; 126 126 127 /** Statistics about a single IPC connection 128 * 129 */ 130 typedef struct { 131 task_id_t caller; /**< Source task ID */ 132 task_id_t callee; /**< Target task ID */ 133 } stats_ipcc_t; 134 127 135 /** Statistics about a single exception 128 136 * -
kernel/generic/src/sysinfo/stats.c
rad211c8 ra6302ae 69 69 #define LOAD_INTERVAL 5 70 70 71 /** IPC connections statistics state */ 72 typedef struct { 73 bool counting; 74 size_t count; 75 size_t i; 76 stats_ipcc_t *data; 77 } ipccs_state_t; 78 71 79 /** Fixed-point representation of 72 80 * … … 371 379 372 380 return ((void *) stats_threads); 381 } 382 383 /** Produce IPC connection statistics 384 * 385 * Summarize IPC connection information into IPC connection statistics. 386 * 387 * @param cap Phone capability. 388 * @param arg State variable. 389 * 390 */ 391 static bool produce_stats_ipcc_cb(cap_t *cap, void *arg) 392 { 393 phone_t *phone = cap->kobject->phone; 394 ipccs_state_t *state = (ipccs_state_t *) arg; 395 396 if (state->counting) { 397 /* 398 * Simply update the number of entries 399 * in case we are in the counting mode. 400 */ 401 402 state->count++; 403 return true; 404 } 405 406 /* We are in the gathering mode */ 407 408 if ((state->data == NULL) || (state->i >= state->count)) { 409 /* 410 * Do nothing if we have no buffer 411 * to store the data to (meaning we are 412 * in a dry run) or the buffer is already 413 * full. 414 */ 415 416 return true; 417 } 418 419 mutex_lock(&phone->lock); 420 421 if (phone->state == IPC_PHONE_CONNECTED) { 422 state->data[state->i].caller = phone->caller->taskid; 423 state->data[state->i].callee = phone->callee->task->taskid; 424 state->i++; 425 } 426 427 mutex_unlock(&phone->lock); 428 429 return true; 430 } 431 432 /** Get IPC connections statistics 433 * 434 * @param item Sysinfo item (unused). 435 * @param size Size of the returned data. 436 * @param dry_run Do not get the data, just calculate the size. 437 * @param data Unused. 438 * 439 * @return Data containing several stats_ipccs_t structures. 440 * If the return value is not NULL, it should be freed 441 * in the context of the sysinfo request. 442 * 443 */ 444 static void *get_stats_ipccs(struct sysinfo_item *item, size_t *size, 445 bool dry_run, void *data) 446 { 447 /* Messing with tasks structures, avoid deadlock */ 448 irq_spinlock_lock(&tasks_lock, true); 449 450 ipccs_state_t state = { 451 .counting = true, 452 .count = 0, 453 .i = 0, 454 .data = NULL 455 }; 456 457 /* Compute the number of IPC connections */ 458 task_t *task = task_first(); 459 while (task != NULL) { 460 task_hold(task); 461 irq_spinlock_unlock(&tasks_lock, true); 462 463 caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE, 464 produce_stats_ipcc_cb, &state); 465 466 irq_spinlock_lock(&tasks_lock, true); 467 468 task = task_next(task); 469 } 470 471 state.counting = false; 472 *size = sizeof(stats_ipcc_t) * state.count; 473 474 if (!dry_run) 475 state.data = (stats_ipcc_t *) malloc(*size); 476 477 /* Gather the statistics for each task */ 478 task = task_first(); 479 while (task != NULL) { 480 /* We already hold a reference to the task */ 481 irq_spinlock_unlock(&tasks_lock, true); 482 483 caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE, 484 produce_stats_ipcc_cb, &state); 485 486 irq_spinlock_lock(&tasks_lock, true); 487 task_release(task); 488 489 task = task_next(task); 490 } 491 492 irq_spinlock_unlock(&tasks_lock, true); 493 494 return ((void *) state.data); 373 495 } 374 496 … … 754 876 sysinfo_set_item_gen_data("system.tasks", NULL, get_stats_tasks, NULL); 755 877 sysinfo_set_item_gen_data("system.threads", NULL, get_stats_threads, NULL); 878 sysinfo_set_item_gen_data("system.ipccs", NULL, get_stats_ipccs, NULL); 756 879 sysinfo_set_item_gen_data("system.exceptions", NULL, get_stats_exceptions, NULL); 757 880 sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task, NULL); -
uspace/app/stats/stats.c
rad211c8 ra6302ae 52 52 #define MINUTE 60 53 53 54 typedef enum { 55 LIST_TASKS, 56 LIST_THREADS, 57 LIST_IPCCS, 58 LIST_CPUS, 59 LIST_LOAD, 60 LIST_UPTIME 61 } list_toggle_t; 62 54 63 static void list_tasks(void) 55 64 { … … 65 74 " [kcycles] [name\n"); 66 75 67 size_t i; 68 for (i = 0; i < count; i++) { 76 for (size_t i = 0; i < count; i++) { 69 77 uint64_t resmem; 70 78 uint64_t virtmem; … … 103 111 printf("[taskid] [threadid] [state ] [prio] [cpu ] [ucycles] [kcycles]\n"); 104 112 105 size_t i; 106 for (i = 0; i < count; i++) { 113 for (size_t i = 0; i < count; i++) { 107 114 if ((all) || (stats_threads[i].task_id == task_id)) { 108 115 uint64_t ucycles, kcycles; … … 130 137 } 131 138 139 static void list_ipccs(task_id_t task_id, bool all) 140 { 141 size_t count; 142 stats_ipcc_t *stats_ipccs = stats_get_ipccs(&count); 143 144 if (stats_ipccs == NULL) { 145 fprintf(stderr, "%s: Unable to get IPC connections\n", NAME); 146 return; 147 } 148 149 printf("[caller] [callee]\n"); 150 151 for (size_t i = 0; i < count; i++) { 152 if ((all) || (stats_ipccs[i].caller == task_id)) { 153 printf("%-8" PRIu64 " %-8" PRIu64 "\n", 154 stats_ipccs[i].caller, stats_ipccs[i].callee); 155 } 156 } 157 158 free(stats_ipccs); 159 } 160 132 161 static void list_cpus(void) 133 162 { … … 142 171 printf("[id] [MHz ] [busy cycles] [idle cycles]\n"); 143 172 144 size_t i; 145 for (i = 0; i < count; i++) { 173 for (size_t i = 0; i < count; i++) { 146 174 printf("%-4u ", cpus[i].id); 147 175 if (cpus[i].active) { … … 174 202 printf("%s: Load average: ", NAME); 175 203 176 size_t i; 177 for (i = 0; i < count; i++) { 204 for (size_t i = 0; i < count; i++) { 178 205 if (i > 0) 179 206 printf(" "); … … 200 227 { 201 228 printf( 202 "Usage: %s [-t task_id] [- a] [-c] [-l] [-u]\n"229 "Usage: %s [-t task_id] [-i task_id] [-at] [-ai] [-c] [-l] [-u]\n" 203 230 "\n" 204 231 "Options:\n" … … 207 234 "\t\tList threads of the given task\n" 208 235 "\n" 209 "\t-a\n" 210 "\t--all\n" 236 "\t-i task_id\n" 237 "\t--ipcc=task_id\n" 238 "\t\tList IPC connections of the given task\n" 239 "\n" 240 "\t-at\n" 241 "\t--all-threads\n" 211 242 "\t\tList all threads\n" 243 "\n" 244 "\t-ai\n" 245 "\t--all-ipccs\n" 246 "\t\tList all IPC connections\n" 212 247 "\n" 213 248 "\t-c\n" … … 233 268 int main(int argc, char *argv[]) 234 269 { 235 bool toggle_tasks = true; 236 bool toggle_threads = false; 270 list_toggle_t list_toggle = LIST_TASKS; 237 271 bool toggle_all = false; 238 bool toggle_cpus = false;239 bool toggle_load = false;240 bool toggle_uptime = false;241 242 272 task_id_t task_id = 0; 243 273 244 int i; 245 for (i = 1; i < argc; i++) { 274 for (int i = 1; i < argc; i++) { 246 275 int off; 247 276 … … 252 281 } 253 282 283 /* All IPC connections */ 284 if ((off = arg_parse_short_long(argv[i], "-ai", "--all-ipccs")) != -1) { 285 list_toggle = LIST_IPCCS; 286 toggle_all = true; 287 continue; 288 } 289 254 290 /* All threads */ 255 if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) { 256 toggle_tasks = false; 257 toggle_threads = true; 291 if ((off = arg_parse_short_long(argv[i], "-at", "--all-threads")) != -1) { 292 list_toggle = LIST_THREADS; 258 293 toggle_all = true; 259 294 continue; 260 295 } 261 296 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 */ 297 /* IPC connections */ 298 if ((off = arg_parse_short_long(argv[i], "-i", "--ipcc=")) != -1) { 299 // TODO: Support for 64b range 300 int tmp; 301 errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off); 302 if (ret != EOK) { 303 printf("%s: Malformed task id '%s'\n", NAME, argv[i]); 304 return -1; 305 } 306 307 task_id = tmp; 308 309 list_toggle = LIST_IPCCS; 310 continue; 311 } 312 313 /* Tasks */ 270 314 if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) { 271 315 // TODO: Support for 64b range … … 273 317 errno_t ret = arg_parse_int(argc, argv, &i, &tmp, off); 274 318 if (ret != EOK) { 275 printf("%s: Malformed task _id '%s'\n", NAME, argv[i]);319 printf("%s: Malformed task id '%s'\n", NAME, argv[i]); 276 320 return -1; 277 321 } … … 279 323 task_id = tmp; 280 324 281 toggle_tasks = false; 282 toggle_threads = true; 325 list_toggle = LIST_THREADS; 326 continue; 327 } 328 329 /* CPUs */ 330 if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) { 331 list_toggle = LIST_CPUS; 283 332 continue; 284 333 } … … 286 335 /* Load */ 287 336 if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) { 288 toggle_tasks = false; 289 toggle_load = true; 337 list_toggle = LIST_LOAD; 290 338 continue; 291 339 } … … 293 341 /* Uptime */ 294 342 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)343 list_toggle = LIST_UPTIME; 344 continue; 345 } 346 } 347 348 switch (list_toggle) { 349 case LIST_TASKS: 302 350 list_tasks(); 303 304 if (toggle_threads)351 break; 352 case LIST_THREADS: 305 353 list_threads(task_id, toggle_all); 306 307 if (toggle_cpus) 354 break; 355 case LIST_IPCCS: 356 list_ipccs(task_id, toggle_all); 357 break; 358 case LIST_CPUS: 308 359 list_cpus(); 309 310 if (toggle_load)360 break; 361 case LIST_LOAD: 311 362 print_load(); 312 313 if (toggle_uptime)363 break; 364 case LIST_UPTIME: 314 365 print_uptime(); 366 break; 367 } 315 368 316 369 return 0; -
uspace/lib/c/generic/stats.c
rad211c8 ra6302ae 184 184 } 185 185 186 /** Get IPC connections statistics. 187 * 188 * @param count Number of records returned. 189 * 190 * @return Array of stats_ipcc_t structures. 191 * If non-NULL then it should be eventually freed 192 * by free(). 193 * 194 */ 195 stats_ipcc_t *stats_get_ipccs(size_t *count) 196 { 197 size_t size = 0; 198 stats_ipcc_t *stats_ipccs = 199 (stats_ipcc_t *) sysinfo_get_data("system.ipccs", &size); 200 201 if ((size % sizeof(stats_ipcc_t)) != 0) { 202 if (stats_ipccs != NULL) 203 free(stats_ipccs); 204 *count = 0; 205 return NULL; 206 } 207 208 *count = size / sizeof(stats_ipcc_t); 209 return stats_ipccs; 210 } 211 186 212 /** Get exception statistics. 187 213 * -
uspace/lib/c/include/stats.h
rad211c8 ra6302ae 52 52 53 53 extern stats_thread_t *stats_get_threads(size_t *); 54 extern stats_ipcc_t *stats_get_ipccs(size_t *); 54 55 55 56 extern stats_exc_t *stats_get_exceptions(size_t *);
Note:
See TracChangeset
for help on using the changeset viewer.