Changeset 8eec3c8 in mainline for kernel


Ignore:
Timestamp:
2010-06-10T14:24:50Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c0f13d2
Parents:
1113c9e
Message:

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

Location:
kernel/generic
Files:
4 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
Note: See TracChangeset for help on using the changeset viewer.