Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 8eec3c8 in mainline


Ignore:
Timestamp:
2010-06-10T14:24:50Z (11 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
c0f13d2
Parents:
1113c9e
Message:

merge basic exception accounting (this is the last piece missing from the original "measure" branch by Stanislav Kozina)

Files:
9 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/interrupt.h

    r1113c9e r8eec3c8  
    4646typedef void (* iroutine)(int, istate_t *);
    4747
     48typedef struct {
     49        const char *name;
     50        iroutine f;
     51        uint64_t cycles;
     52        uint64_t count;
     53} exc_table_t;
     54
     55IRQ_SPINLOCK_EXTERN(exctbl_lock);
     56extern exc_table_t exc_table[];
     57
    4858extern void fault_if_from_uspace(istate_t *, const char *, ...);
    4959extern iroutine exc_register(int, const char *, iroutine);
  • kernel/generic/include/sysinfo/abi.h

    r1113c9e r8eec3c8  
    4040#define LOAD_STEPS  3
    4141
    42 /** Maximum task name size */
     42/** Maximum name sizes */
    4343#define TASK_NAME_BUFLEN  20
     44#define EXC_NAME_BUFLEN   20
    4445
    4546/** Thread states */
     
    123124} stats_thread_t;
    124125
     126/** Statistics about a single exception
     127 *
     128 */
     129typedef 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
    125136/** Load fixed-point value */
    126137typedef uint32_t load_t;
  • kernel/generic/src/interrupt/interrupt.c

    r1113c9e r8eec3c8  
    5353#include <symtab.h>
    5454#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
     58exc_table_t exc_table[IVT_ITEMS];
     59IRQ_SPINLOCK_INITIALIZE(exctbl_lock);
    6260
    6361/** Register exception handler
     
    7270        ASSERT(n < IVT_ITEMS);
    7371       
    74         spinlock_lock(&exctbl_lock);
     72        irq_spinlock_lock(&exctbl_lock, true);
    7573       
    7674        iroutine old = exc_table[n].f;
    7775        exc_table[n].f = handler;
    7876        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);
    8181       
    8282        return old;
     
    9292{
    9393        ASSERT(n < IVT_ITEMS);
     94       
     95        uint64_t begin_cycle = get_cycle();
    9496       
    9597        /* Account user cycles */
    9698        if (THREAD) {
    9799                irq_spinlock_lock(&THREAD->lock, false);
    98                 thread_update_accounting(true);
     100                THREAD->ucycles += begin_cycle - THREAD->last_cycle;
    99101                irq_spinlock_unlock(&THREAD->lock, false);
    100102        }
     
    116118                thread_exit();
    117119       
     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 */
    118126        if (THREAD) {
    119127                irq_spinlock_lock(&THREAD->lock, false);
    120                 thread_update_accounting(false);
     128                THREAD->last_cycle = end_cycle;
    121129                irq_spinlock_unlock(&THREAD->lock, false);
    122130        }
     
    185193        unsigned int i;
    186194       
    187         spinlock_lock(&exctbl_lock);
     195        irq_spinlock_lock(&exctbl_lock, true);
    188196       
    189197#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");
    192200#endif
    193201       
    194202#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");
    197205#endif
    198206       
    199207        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);
    201220               
    202221#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);
    205225#endif
    206226               
    207227#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);
    210231#endif
    211232               
    212233                if (((i + 1) % 20) == 0) {
    213234                        printf(" -- Press any key to continue -- ");
    214                         spinlock_unlock(&exctbl_lock);
     235                        irq_spinlock_unlock(&exctbl_lock, true);
    215236                        indev_pop_character(stdin);
    216                         spinlock_lock(&exctbl_lock);
     237                        irq_spinlock_lock(&exctbl_lock, true);
    217238                        printf("\n");
    218239                }
    219240        }
    220241       
    221         spinlock_unlock(&exctbl_lock);
     242        irq_spinlock_unlock(&exctbl_lock, true);
    222243#endif
    223244       
  • kernel/generic/src/sysinfo/stats.c

    r1113c9e r8eec3c8  
    4444#include <proc/task.h>
    4545#include <proc/thread.h>
     46#include <interrupt.h>
    4647#include <str.h>
    4748#include <errno.h>
     
    535536}
    536537
     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 */
     548static 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 */
     597static 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
    537649/** Get physical memory statistics
    538650 *
     
    651763        sysinfo_set_item_fn_data("system.tasks", NULL, get_stats_tasks);
    652764        sysinfo_set_item_fn_data("system.threads", NULL, get_stats_threads);
     765        sysinfo_set_item_fn_data("system.exceptions", NULL, get_stats_exceptions);
    653766        sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task);
    654767        sysinfo_set_subtree_fn("system.threads", NULL, get_stats_thread);
     768        sysinfo_set_subtree_fn("system.exceptions", NULL, get_stats_exception);
    655769}
    656770
  • uspace/app/top/screen.c

    r1113c9e r8eec3c8  
    325325}
    326326
     327static 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
     335static 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
    327364void print_data(data_t *data)
    328365{
     
    338375        screen_newline();
    339376       
    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:
    341383                print_ipc_head();
    342384                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;
    346390        }
    347391       
  • uspace/app/top/top.c

    r1113c9e r8eec3c8  
    115115                return "Cannot get threads";
    116116       
     117        target->exceptions = stats_get_exceptions(&(target->exceptions_count));
     118        if (target->exceptions == NULL)
     119                return "Cannot get exceptions";
     120       
    117121        /* Get physical memory */
    118122        target->physmem = stats_get_physmem();
     
    231235        if (target->threads != NULL)
    232236                free(target->threads);
     237       
     238        if (target->exceptions != NULL)
     239                free(target->exceptions);
    233240       
    234241        if (target->physmem != NULL)
     
    285292                                operation_type = OP_TASKS;
    286293                                break;
     294                        case 'e':
     295                                print_warning("Showing exception statistics");
     296                                operation_type = OP_EXC;
     297                                break;
    287298                        default:
    288299                                print_warning("Unknown command: %c", c);
  • uspace/app/top/top.h

    r1113c9e r8eec3c8  
    4646#define OP_TASKS  1
    4747#define OP_IPC    2
     48#define OP_EXC    3
    4849
    4950extern int operation_type;
     
    8990        stats_thread_t *threads;
    9091       
     92        size_t exceptions_count;
     93        stats_exc_t *exceptions;
     94       
    9195        stats_physmem_t *physmem;
    9296} data_t;
  • uspace/lib/c/generic/stats.c

    r1113c9e r8eec3c8  
    184184}
    185185
     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 */
     195stats_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 */
     216stats_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
    186230/** Get system load
    187231 *
  • uspace/lib/c/include/stats.h

    r1113c9e r8eec3c8  
    5353extern stats_thread_t *stats_get_thread(thread_id_t);
    5454
     55extern stats_exc_t *stats_get_exceptions(size_t *);
     56extern stats_exc_t *stats_get_exception(unsigned int);
     57
    5558extern void stats_print_load_fragment(load_t, unsigned int);
    5659extern const char *thread_get_state(state_t);
Note: See TracChangeset for help on using the changeset viewer.