Changeset 8eec3c8 in mainline
- Timestamp:
- 2010-06-10T14:24:50Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c0f13d2
- Parents:
- 1113c9e
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/interrupt.h
r1113c9e r8eec3c8 46 46 typedef void (* iroutine)(int, istate_t *); 47 47 48 typedef struct { 49 const char *name; 50 iroutine f; 51 uint64_t cycles; 52 uint64_t count; 53 } exc_table_t; 54 55 IRQ_SPINLOCK_EXTERN(exctbl_lock); 56 extern exc_table_t exc_table[]; 57 48 58 extern void fault_if_from_uspace(istate_t *, const char *, ...); 49 59 extern iroutine exc_register(int, const char *, iroutine); -
kernel/generic/include/sysinfo/abi.h
r1113c9e r8eec3c8 40 40 #define LOAD_STEPS 3 41 41 42 /** Maximum task name size*/42 /** Maximum name sizes */ 43 43 #define TASK_NAME_BUFLEN 20 44 #define EXC_NAME_BUFLEN 20 44 45 45 46 /** Thread states */ … … 123 124 } stats_thread_t; 124 125 126 /** Statistics about a single exception 127 * 128 */ 129 typedef struct { 130 unsigned int id; /**< Exception ID */ 131 char desc[EXC_NAME_BUFLEN]; /**< Description */ 132 uint64_t cycles; /**< Number of CPU cycles in the handler */ 133 uint64_t count; /**< Number of handled exceptions */ 134 } stats_exc_t; 135 125 136 /** Load fixed-point value */ 126 137 typedef uint32_t load_t; -
kernel/generic/src/interrupt/interrupt.c
r1113c9e r8eec3c8 53 53 #include <symtab.h> 54 54 #include <proc/thread.h> 55 56 static struct { 57 const char *name; 58 iroutine f; 59 } exc_table[IVT_ITEMS]; 60 61 SPINLOCK_INITIALIZE(exctbl_lock); 55 #include <arch/cycle.h> 56 #include <str.h> 57 58 exc_table_t exc_table[IVT_ITEMS]; 59 IRQ_SPINLOCK_INITIALIZE(exctbl_lock); 62 60 63 61 /** Register exception handler … … 72 70 ASSERT(n < IVT_ITEMS); 73 71 74 spinlock_lock(&exctbl_lock);72 irq_spinlock_lock(&exctbl_lock, true); 75 73 76 74 iroutine old = exc_table[n].f; 77 75 exc_table[n].f = handler; 78 76 exc_table[n].name = name; 79 80 spinlock_unlock(&exctbl_lock); 77 exc_table[n].cycles = 0; 78 exc_table[n].count = 0; 79 80 irq_spinlock_unlock(&exctbl_lock, true); 81 81 82 82 return old; … … 92 92 { 93 93 ASSERT(n < IVT_ITEMS); 94 95 uint64_t begin_cycle = get_cycle(); 94 96 95 97 /* Account user cycles */ 96 98 if (THREAD) { 97 99 irq_spinlock_lock(&THREAD->lock, false); 98 thread_update_accounting(true);100 THREAD->ucycles += begin_cycle - THREAD->last_cycle; 99 101 irq_spinlock_unlock(&THREAD->lock, false); 100 102 } … … 116 118 thread_exit(); 117 119 120 /* Account exception handling */ 121 uint64_t end_cycle = get_cycle(); 122 exc_table[n].cycles += end_cycle - begin_cycle; 123 exc_table[n].count++; 124 125 /* Do not charge THREAD for exception cycles */ 118 126 if (THREAD) { 119 127 irq_spinlock_lock(&THREAD->lock, false); 120 thread_update_accounting(false);128 THREAD->last_cycle = end_cycle; 121 129 irq_spinlock_unlock(&THREAD->lock, false); 122 130 } … … 185 193 unsigned int i; 186 194 187 spinlock_lock(&exctbl_lock);195 irq_spinlock_lock(&exctbl_lock, true); 188 196 189 197 #ifdef __32_BITS__ 190 printf("Exc Description Handler Symbol\n");191 printf("--- -------------------- ---------- -------- \n");198 printf("Exc Description Count Cycles Handler Symbol\n"); 199 printf("--- -------------------- ---------- ---------- ---------- --------\n"); 192 200 #endif 193 201 194 202 #ifdef __64_BITS__ 195 printf("Exc Description Handler Symbol\n");196 printf("--- -------------------- ---------- -------- --------\n");203 printf("Exc Description Count Cycles Handler Symbol\n"); 204 printf("--- -------------------- ---------- ---------- ------------------ --------\n"); 197 205 #endif 198 206 199 207 for (i = 0; i < IVT_ITEMS; i++) { 200 const char *symbol = symtab_fmt_name_lookup((unative_t) exc_table[i].f); 208 uint64_t count; 209 char count_suffix; 210 211 order_suffix(exc_table[i].count, &count, &count_suffix); 212 213 uint64_t cycles; 214 char cycles_suffix; 215 216 order_suffix(exc_table[i].cycles, &cycles, &cycles_suffix); 217 218 const char *symbol = 219 symtab_fmt_name_lookup((unative_t) exc_table[i].f); 201 220 202 221 #ifdef __32_BITS__ 203 printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name, 204 exc_table[i].f, symbol); 222 printf("%-3u %-20s %9" PRIu64 "%c %9" PRIu64 "%c %10p %s\n", 223 i + IVT_FIRST, exc_table[i].name, count, count_suffix, 224 cycles, cycles_suffix, exc_table[i].f, symbol); 205 225 #endif 206 226 207 227 #ifdef __64_BITS__ 208 printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name, 209 exc_table[i].f, symbol); 228 printf("%-3u %-20s %9" PRIu64 "%c %9" PRIu64 "%c %18p %s\n", 229 i + IVT_FIRST, exc_table[i].name, count, count_suffix, 230 cycles, cycles_suffix, exc_table[i].f, symbol); 210 231 #endif 211 232 212 233 if (((i + 1) % 20) == 0) { 213 234 printf(" -- Press any key to continue -- "); 214 spinlock_unlock(&exctbl_lock);235 irq_spinlock_unlock(&exctbl_lock, true); 215 236 indev_pop_character(stdin); 216 spinlock_lock(&exctbl_lock);237 irq_spinlock_lock(&exctbl_lock, true); 217 238 printf("\n"); 218 239 } 219 240 } 220 241 221 spinlock_unlock(&exctbl_lock);242 irq_spinlock_unlock(&exctbl_lock, true); 222 243 #endif 223 244 -
kernel/generic/src/sysinfo/stats.c
r1113c9e r8eec3c8 44 44 #include <proc/task.h> 45 45 #include <proc/thread.h> 46 #include <interrupt.h> 46 47 #include <str.h> 47 48 #include <errno.h> … … 535 536 } 536 537 538 /** Get exceptions statistics 539 * 540 * @param item Sysinfo item (unused). 541 * @param size Size of the returned data. 542 * @param dry_run Do not get the data, just calculate the size. 543 * 544 * @return Data containing several stats_exc_t structures. 545 * If the return value is not NULL, it should be freed 546 * in the context of the sysinfo request. 547 */ 548 static void *get_stats_exceptions(struct sysinfo_item *item, size_t *size, 549 bool dry_run) 550 { 551 *size = sizeof(stats_exc_t) * IVT_ITEMS; 552 553 if ((dry_run) || (IVT_ITEMS == 0)) 554 return NULL; 555 556 stats_exc_t *stats_exceptions = 557 (stats_exc_t *) malloc(*size, FRAME_ATOMIC); 558 if (stats_exceptions == NULL) { 559 /* No free space for allocation */ 560 *size = 0; 561 return NULL; 562 } 563 564 /* Messing with exception table, avoid deadlock */ 565 irq_spinlock_lock(&exctbl_lock, true); 566 567 unsigned int i; 568 for (i = 0; i < IVT_ITEMS; i++) { 569 stats_exceptions[i].id = i + IVT_FIRST; 570 str_cpy(stats_exceptions[i].desc, EXC_NAME_BUFLEN, exc_table[i].name); 571 stats_exceptions[i].cycles = exc_table[i].cycles; 572 stats_exceptions[i].count = exc_table[i].count; 573 } 574 575 irq_spinlock_unlock(&exctbl_lock, true); 576 577 return ((void *) stats_exceptions); 578 } 579 580 /** Get exception statistics 581 * 582 * Get statistics of a given exception. The exception number 583 * is passed as a string (current limitation of the sysinfo 584 * interface, but it is still reasonable for the given purpose). 585 * 586 * @param name Exception number (string-encoded number). 587 * @param dry_run Do not get the data, just calculate the size. 588 * 589 * @return Sysinfo return holder. The type of the returned 590 * data is either SYSINFO_VAL_UNDEFINED (unknown 591 * exception number or memory allocation error) or 592 * SYSINFO_VAL_FUNCTION_DATA (in that case the 593 * generated data should be freed within the 594 * sysinfo request context). 595 * 596 */ 597 static sysinfo_return_t get_stats_exception(const char *name, bool dry_run) 598 { 599 /* Initially no return value */ 600 sysinfo_return_t ret; 601 ret.tag = SYSINFO_VAL_UNDEFINED; 602 603 /* Parse the exception number */ 604 uint64_t excn; 605 if (str_uint64(name, NULL, 0, true, &excn) != EOK) 606 return ret; 607 608 #if IVT_FIRST > 0 609 if (excn < IVT_FIRST) 610 return ret; 611 #endif 612 613 if (excn >= IVT_ITEMS + IVT_FIRST) 614 return ret; 615 616 if (dry_run) { 617 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 618 ret.data.data = NULL; 619 ret.data.size = sizeof(stats_thread_t); 620 } else { 621 /* Update excn index for accessing exc_table */ 622 excn -= IVT_FIRST; 623 624 /* Allocate stats_exc_t structure */ 625 stats_exc_t *stats_exception = 626 (stats_exc_t *) malloc(sizeof(stats_exc_t), FRAME_ATOMIC); 627 if (stats_exception == NULL) 628 return ret; 629 630 /* Messing with exception table, avoid deadlock */ 631 irq_spinlock_lock(&exctbl_lock, true); 632 633 /* Correct return value */ 634 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 635 ret.data.data = (void *) stats_exception; 636 ret.data.size = sizeof(stats_exc_t); 637 638 stats_exception->id = excn; 639 str_cpy(stats_exception->desc, EXC_NAME_BUFLEN, exc_table[excn].name); 640 stats_exception->cycles = exc_table[excn].cycles; 641 stats_exception->count = exc_table[excn].count; 642 643 irq_spinlock_unlock(&exctbl_lock, true); 644 } 645 646 return ret; 647 } 648 537 649 /** Get physical memory statistics 538 650 * … … 651 763 sysinfo_set_item_fn_data("system.tasks", NULL, get_stats_tasks); 652 764 sysinfo_set_item_fn_data("system.threads", NULL, get_stats_threads); 765 sysinfo_set_item_fn_data("system.exceptions", NULL, get_stats_exceptions); 653 766 sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task); 654 767 sysinfo_set_subtree_fn("system.threads", NULL, get_stats_thread); 768 sysinfo_set_subtree_fn("system.exceptions", NULL, get_stats_exception); 655 769 } 656 770 -
uspace/app/top/screen.c
r1113c9e r8eec3c8 325 325 } 326 326 327 static inline void print_exc_head(void) 328 { 329 screen_style_inverted(); 330 printf(" ID Desc Count Cycles"); 331 screen_newline(); 332 screen_style_normal(); 333 } 334 335 static inline void print_exc(data_t *data) 336 { 337 ipcarg_t cols; 338 ipcarg_t rows; 339 screen_get_size(&cols, &rows); 340 341 ipcarg_t col; 342 ipcarg_t row; 343 screen_get_pos(&col, &row); 344 345 size_t i; 346 for (i = 0; (i < data->exceptions_count) && (row < rows); i++, row++) { 347 uint64_t cycles; 348 char suffix; 349 350 order_suffix(data->exceptions[i].cycles, &cycles, &suffix); 351 printf("%8u %20s %8" PRIu64 " %8" PRIu64 "%c", 352 data->exceptions[i].id, data->exceptions[i].desc, 353 data->exceptions[i].count, cycles, suffix); 354 355 screen_newline(); 356 } 357 358 while (row < rows) { 359 screen_newline(); 360 row++; 361 } 362 } 363 327 364 void print_data(data_t *data) 328 365 { … … 338 375 screen_newline(); 339 376 340 if (operation_type == OP_IPC) { 377 switch (operation_type) { 378 case OP_TASKS: 379 print_task_head(); 380 print_tasks(data); 381 break; 382 case OP_IPC: 341 383 print_ipc_head(); 342 384 print_ipc(data); 343 } else { 344 print_task_head(); 345 print_tasks(data); 385 break; 386 case OP_EXC: 387 print_exc_head(); 388 print_exc(data); 389 break; 346 390 } 347 391 -
uspace/app/top/top.c
r1113c9e r8eec3c8 115 115 return "Cannot get threads"; 116 116 117 target->exceptions = stats_get_exceptions(&(target->exceptions_count)); 118 if (target->exceptions == NULL) 119 return "Cannot get exceptions"; 120 117 121 /* Get physical memory */ 118 122 target->physmem = stats_get_physmem(); … … 231 235 if (target->threads != NULL) 232 236 free(target->threads); 237 238 if (target->exceptions != NULL) 239 free(target->exceptions); 233 240 234 241 if (target->physmem != NULL) … … 285 292 operation_type = OP_TASKS; 286 293 break; 294 case 'e': 295 print_warning("Showing exception statistics"); 296 operation_type = OP_EXC; 297 break; 287 298 default: 288 299 print_warning("Unknown command: %c", c); -
uspace/app/top/top.h
r1113c9e r8eec3c8 46 46 #define OP_TASKS 1 47 47 #define OP_IPC 2 48 #define OP_EXC 3 48 49 49 50 extern int operation_type; … … 89 90 stats_thread_t *threads; 90 91 92 size_t exceptions_count; 93 stats_exc_t *exceptions; 94 91 95 stats_physmem_t *physmem; 92 96 } data_t; -
uspace/lib/c/generic/stats.c
r1113c9e r8eec3c8 184 184 } 185 185 186 /** Get exception statistics. 187 * 188 * @param count Number of records returned. 189 * 190 * @return Array of stats_exc_t structures. 191 * If non-NULL then it should be eventually freed 192 * by free(). 193 * 194 */ 195 stats_exc_t *stats_get_exceptions(size_t *count) 196 { 197 size_t size = 0; 198 stats_exc_t *stats_exceptions = 199 (stats_exc_t *) sysinfo_get_data("system.exceptions", &size); 200 201 assert((size % sizeof(stats_exc_t)) == 0); 202 203 *count = size / sizeof(stats_exc_t); 204 return stats_exceptions; 205 } 206 207 /** Get single exception statistics 208 * 209 * @param excn Exception number we are interested in. 210 * 211 * @return Pointer to the stats_exc_t structure. 212 * If non-NULL then it should be eventually freed 213 * by free(). 214 * 215 */ 216 stats_exc_t *stats_get_exception(unsigned int excn) 217 { 218 char name[SYSINFO_STATS_MAX_PATH]; 219 snprintf(name, SYSINFO_STATS_MAX_PATH, "system.exceptionss.%u", excn); 220 221 size_t size = 0; 222 stats_exc_t *stats_exception = 223 (stats_exc_t *) sysinfo_get_data(name, &size); 224 225 assert((size == sizeof(stats_exc_t)) || (size == 0)); 226 227 return stats_exception; 228 } 229 186 230 /** Get system load 187 231 * -
uspace/lib/c/include/stats.h
r1113c9e r8eec3c8 53 53 extern stats_thread_t *stats_get_thread(thread_id_t); 54 54 55 extern stats_exc_t *stats_get_exceptions(size_t *); 56 extern stats_exc_t *stats_get_exception(unsigned int); 57 55 58 extern void stats_print_load_fragment(load_t, unsigned int); 56 59 extern const char *thread_get_state(state_t);
Note:
See TracChangeset
for help on using the changeset viewer.