Changeset dec16a2 in mainline


Ignore:
Timestamp:
2010-04-18T16:52:47Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5c45ca8
Parents:
e535eeb
Message:
  • sysinfo items "system.tasks" and "system.threads" now return complete statistics of all tasks and threads (statistics of individual tasks and threads can be still acquited from "system.tasks.#" and "system.threads.#")
  • update user space functions accordingly
  • cleanup top — it is fully functional again
Files:
2 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    re535eeb rdec16a2  
    9494        $(USPACEDIR)/app/ping/ping \
    9595        $(USPACEDIR)/app/stats/stats \
    96         $(USPACEDIR)/app/tasks/tasks
    97 #       $(USPACEDIR)/app/top/top \
     96        $(USPACEDIR)/app/tasks/tasks \
     97        $(USPACEDIR)/app/top/top
    9898#       $(USPACEDIR)/app/dummy_load/dummy_load
    9999
  • kernel/generic/include/sysinfo/abi.h

    re535eeb rdec16a2  
    9999 */
    100100typedef struct {
     101        task_id_t task_id;            /**< Task ID */
    101102        char name[TASK_NAME_BUFLEN];  /**< Task name (in kernel) */
    102103        size_t virtmem;               /**< Size of VAS (bytes) */
     
    111112 */
    112113typedef struct {
    113         task_id_t task_id;
    114         state_t state;
    115         int priority;
    116         uint64_t ucycles;
    117         uint64_t kcycles;
    118         bool on_cpu;
    119         unsigned int cpu;
     114        thread_id_t thread_id;  /**< Thread ID */
     115        task_id_t task_id;      /**< Associated task ID */
     116        state_t state;          /**< Thread state */
     117        int priority;           /**< Thread priority */
     118        uint64_t ucycles;       /**< Number of CPU cycles in user space */
     119        uint64_t kcycles;       /**< Number of CPU cycles in kernel */
     120        bool on_cpu;            /**< Associated with a CPU */
     121        unsigned int cpu;       /**< Associated CPU ID (if on_cpu is true) */
    120122} stats_thread_t;
    121123
  • kernel/generic/src/sysinfo/stats.c

    re535eeb rdec16a2  
    146146}
    147147
    148 /** Gather tasks
    149  *
    150  * AVL task tree walker for gathering task IDs. Interrupts should
    151  * be already disabled while walking the tree.
    152  *
    153  * @param node AVL task tree node.
    154  * @param arg  Pointer to the iterator into the array of task IDs.
    155  *
    156  * @param Always true (continue the walk).
    157  *
    158  */
    159 static bool task_serialize_walker(avltree_node_t *node, void *arg)
    160 {
    161         task_id_t **ids = (task_id_t **) arg;
    162         task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
    163        
    164         /* Interrupts are already disabled */
    165         spinlock_lock(&(task->lock));
    166        
    167         /* Record the ID and increment the iterator */
    168         **ids = task->taskid;
    169         (*ids)++;
    170        
    171         spinlock_unlock(&(task->lock));
    172        
    173         return true;
    174 }
    175 
    176 /** Get task IDs
    177  *
    178  * @param item    Sysinfo item (unused).
    179  * @param size    Size of the returned data.
    180  * @param dry_run Do not get the data, just calculate the size.
    181  *
    182  * @return Data containing task IDs of all tasks.
    183  *         If the return value is not NULL, it should be freed
    184  *         in the context of the sysinfo request.
    185  */
    186 static void *get_stats_tasks(struct sysinfo_item *item, size_t *size,
    187     bool dry_run)
    188 {
    189         /* Messing with task structures, avoid deadlock */
    190         ipl_t ipl = interrupts_disable();
    191         spinlock_lock(&tasks_lock);
    192        
    193         /* First walk the task tree to count the tasks */
    194         size_t count = 0;
    195         avltree_walk(&tasks_tree, avl_count_walker, (void *) &count);
    196        
    197         if (count == 0) {
    198                 /* No tasks found (strange) */
    199                 spinlock_unlock(&tasks_lock);
    200                 interrupts_restore(ipl);
    201                
    202                 *size = 0;
    203                 return NULL;
    204         }
    205        
    206         *size = sizeof(task_id_t) * count;
    207         if (dry_run) {
    208                 spinlock_unlock(&tasks_lock);
    209                 interrupts_restore(ipl);
    210                 return NULL;
    211         }
    212        
    213         task_id_t *task_ids = (task_id_t *) malloc(*size, FRAME_ATOMIC);
    214         if (task_ids == NULL) {
    215                 /* No free space for allocation */
    216                 spinlock_unlock(&tasks_lock);
    217                 interrupts_restore(ipl);
    218                
    219                 *size = 0;
    220                 return NULL;
    221         }
    222        
    223         /* Walk tha task tree again to gather the IDs */
    224         task_id_t *iterator = task_ids;
    225         avltree_walk(&tasks_tree, task_serialize_walker, (void *) &iterator);
    226        
    227         spinlock_unlock(&tasks_lock);
    228         interrupts_restore(ipl);
    229        
    230         return ((void *) task_ids);
    231 }
    232 
    233 /** Gather threads
    234  *
    235  * AVL three tree walker for gathering thread IDs. Interrupts should
    236  * be already disabled while walking the tree.
    237  *
    238  * @param node AVL thread tree node.
    239  * @param arg  Pointer to the iterator into the array of thread IDs.
    240  *
    241  * @param Always true (continue the walk).
    242  *
    243  */
    244 static bool thread_serialize_walker(avltree_node_t *node, void *arg)
    245 {
    246         thread_id_t **ids = (thread_id_t **) arg;
    247         thread_t *thread = avltree_get_instance(node, thread_t, threads_tree_node);
    248        
    249         /* Interrupts are already disabled */
    250         spinlock_lock(&(thread->lock));
    251        
    252         /* Record the ID and increment the iterator */
    253         **ids = thread->tid;
    254         (*ids)++;
    255        
    256         spinlock_unlock(&(thread->lock));
    257        
    258         return true;
    259 }
    260 
    261 /** Get thread IDs
    262  *
    263  * @param item    Sysinfo item (unused).
    264  * @param size    Size of the returned data.
    265  * @param dry_run Do not get the data, just calculate the size.
    266  *
    267  * @return Data containing thread IDs of all threads.
    268  *         If the return value is not NULL, it should be freed
    269  *         in the context of the sysinfo request.
    270  */
    271 static void *get_stats_threads(struct sysinfo_item *item, size_t *size,
    272     bool dry_run)
    273 {
    274         /* Messing with threads structures, avoid deadlock */
    275         ipl_t ipl = interrupts_disable();
    276         spinlock_lock(&threads_lock);
    277        
    278         /* First walk the thread tree to count the threads */
    279         size_t count = 0;
    280         avltree_walk(&threads_tree, avl_count_walker, (void *) &count);
    281        
    282         if (count == 0) {
    283                 /* No threads found (strange) */
    284                 spinlock_unlock(&threads_lock);
    285                 interrupts_restore(ipl);
    286                
    287                 *size = 0;
    288                 return NULL;
    289         }
    290        
    291         *size = sizeof(thread_id_t) * count;
    292         if (dry_run) {
    293                 spinlock_unlock(&threads_lock);
    294                 interrupts_restore(ipl);
    295                 return NULL;
    296         }
    297        
    298         thread_id_t *thread_ids = (thread_id_t *) malloc(*size, FRAME_ATOMIC);
    299         if (thread_ids == NULL) {
    300                 /* No free space for allocation */
    301                 spinlock_unlock(&threads_lock);
    302                 interrupts_restore(ipl);
    303                
    304                 *size = 0;
    305                 return NULL;
    306         }
    307        
    308         /* Walk tha thread tree again to gather the IDs */
    309         thread_id_t *iterator = thread_ids;
    310         avltree_walk(&threads_tree, thread_serialize_walker, (void *) &iterator);
    311        
    312         spinlock_unlock(&threads_lock);
    313         interrupts_restore(ipl);
    314        
    315         return ((void *) thread_ids);
    316 }
    317 
    318148/** Get the size of a virtual address space
    319149 *
     
    351181}
    352182
     183/* Produce task statistics
     184 *
     185 * Summarize task information into task statistics.
     186 * Task lock should be held and interrupts disabled
     187 * before executing this function.
     188 *
     189 * @param task       Task.
     190 * @param stats_task Task statistics.
     191 *
     192 */
     193static void produce_stats_task(task_t *task, stats_task_t *stats_task)
     194{
     195        stats_task->task_id = task->taskid;
     196        str_cpy(stats_task->name, TASK_NAME_BUFLEN, task->name);
     197        stats_task->virtmem = get_task_virtmem(task->as);
     198        stats_task->threads = atomic_get(&task->refcount);
     199        task_get_accounting(task, &(stats_task->ucycles),
     200            &(stats_task->kcycles));
     201        stats_task->ipc_info = task->ipc_info;
     202}
     203
     204/** Gather statistics of all tasks
     205 *
     206 * AVL task tree walker for gathering task statistics. Interrupts should
     207 * be already disabled while walking the tree.
     208 *
     209 * @param node AVL task tree node.
     210 * @param arg  Pointer to the iterator into the array of stats_task_t.
     211 *
     212 * @param Always true (continue the walk).
     213 *
     214 */
     215static bool task_serialize_walker(avltree_node_t *node, void *arg)
     216{
     217        stats_task_t **iterator = (stats_task_t **) arg;
     218        task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
     219       
     220        /* Interrupts are already disabled */
     221        spinlock_lock(&(task->lock));
     222       
     223        /* Record the statistics and increment the iterator */
     224        produce_stats_task(task, *iterator);
     225        (*iterator)++;
     226       
     227        spinlock_unlock(&(task->lock));
     228       
     229        return true;
     230}
     231
    353232/** Get task statistics
     233 *
     234 * @param item    Sysinfo item (unused).
     235 * @param size    Size of the returned data.
     236 * @param dry_run Do not get the data, just calculate the size.
     237 *
     238 * @return Data containing several stats_task_t structures.
     239 *         If the return value is not NULL, it should be freed
     240 *         in the context of the sysinfo request.
     241 */
     242static void *get_stats_tasks(struct sysinfo_item *item, size_t *size,
     243    bool dry_run)
     244{
     245        /* Messing with task structures, avoid deadlock */
     246        ipl_t ipl = interrupts_disable();
     247        spinlock_lock(&tasks_lock);
     248       
     249        /* First walk the task tree to count the tasks */
     250        size_t count = 0;
     251        avltree_walk(&tasks_tree, avl_count_walker, (void *) &count);
     252       
     253        if (count == 0) {
     254                /* No tasks found (strange) */
     255                spinlock_unlock(&tasks_lock);
     256                interrupts_restore(ipl);
     257               
     258                *size = 0;
     259                return NULL;
     260        }
     261       
     262        *size = sizeof(stats_task_t) * count;
     263        if (dry_run) {
     264                spinlock_unlock(&tasks_lock);
     265                interrupts_restore(ipl);
     266                return NULL;
     267        }
     268       
     269        stats_task_t *stats_tasks = (stats_task_t *) malloc(*size, FRAME_ATOMIC);
     270        if (stats_tasks == NULL) {
     271                /* No free space for allocation */
     272                spinlock_unlock(&tasks_lock);
     273                interrupts_restore(ipl);
     274               
     275                *size = 0;
     276                return NULL;
     277        }
     278       
     279        /* Walk tha task tree again to gather the statistics */
     280        stats_task_t *iterator = stats_tasks;
     281        avltree_walk(&tasks_tree, task_serialize_walker, (void *) &iterator);
     282       
     283        spinlock_unlock(&tasks_lock);
     284        interrupts_restore(ipl);
     285       
     286        return ((void *) stats_tasks);
     287}
     288
     289/* Produce thread statistics
     290 *
     291 * Summarize thread information into thread statistics.
     292 * Thread lock should be held and interrupts disabled
     293 * before executing this function.
     294 *
     295 * @param thread       Thread.
     296 * @param stats_thread Thread statistics.
     297 *
     298 */
     299static void produce_stats_thread(thread_t *thread, stats_thread_t *stats_thread)
     300{
     301        stats_thread->thread_id = thread->tid;
     302        stats_thread->task_id = thread->task->taskid;
     303        stats_thread->state = thread->state;
     304        stats_thread->priority = thread->priority;
     305        stats_thread->ucycles = thread->ucycles;
     306        stats_thread->kcycles = thread->kcycles;
     307       
     308        if (thread->cpu != NULL) {
     309                stats_thread->on_cpu = true;
     310                stats_thread->cpu = thread->cpu->id;
     311        } else
     312                stats_thread->on_cpu = false;
     313}
     314
     315/** Gather statistics of all threads
     316 *
     317 * AVL three tree walker for gathering thread statistics. Interrupts should
     318 * be already disabled while walking the tree.
     319 *
     320 * @param node AVL thread tree node.
     321 * @param arg  Pointer to the iterator into the array of thread statistics.
     322 *
     323 * @param Always true (continue the walk).
     324 *
     325 */
     326static bool thread_serialize_walker(avltree_node_t *node, void *arg)
     327{
     328        stats_thread_t **iterator = (stats_thread_t **) arg;
     329        thread_t *thread = avltree_get_instance(node, thread_t, threads_tree_node);
     330       
     331        /* Interrupts are already disabled */
     332        spinlock_lock(&(thread->lock));
     333       
     334        /* Record the statistics and increment the iterator */
     335        produce_stats_thread(thread, *iterator);
     336        (*iterator)++;
     337       
     338        spinlock_unlock(&(thread->lock));
     339       
     340        return true;
     341}
     342
     343/** Get thread statistics
     344 *
     345 * @param item    Sysinfo item (unused).
     346 * @param size    Size of the returned data.
     347 * @param dry_run Do not get the data, just calculate the size.
     348 *
     349 * @return Data containing several stats_task_t structures.
     350 *         If the return value is not NULL, it should be freed
     351 *         in the context of the sysinfo request.
     352 */
     353static void *get_stats_threads(struct sysinfo_item *item, size_t *size,
     354    bool dry_run)
     355{
     356        /* Messing with threads structures, avoid deadlock */
     357        ipl_t ipl = interrupts_disable();
     358        spinlock_lock(&threads_lock);
     359       
     360        /* First walk the thread tree to count the threads */
     361        size_t count = 0;
     362        avltree_walk(&threads_tree, avl_count_walker, (void *) &count);
     363       
     364        if (count == 0) {
     365                /* No threads found (strange) */
     366                spinlock_unlock(&threads_lock);
     367                interrupts_restore(ipl);
     368               
     369                *size = 0;
     370                return NULL;
     371        }
     372       
     373        *size = sizeof(stats_thread_t) * count;
     374        if (dry_run) {
     375                spinlock_unlock(&threads_lock);
     376                interrupts_restore(ipl);
     377                return NULL;
     378        }
     379       
     380        stats_thread_t *stats_threads = (stats_thread_t *) malloc(*size, FRAME_ATOMIC);
     381        if (stats_threads == NULL) {
     382                /* No free space for allocation */
     383                spinlock_unlock(&threads_lock);
     384                interrupts_restore(ipl);
     385               
     386                *size = 0;
     387                return NULL;
     388        }
     389       
     390        /* Walk tha thread tree again to gather the statistics */
     391        stats_thread_t *iterator = stats_threads;
     392        avltree_walk(&threads_tree, thread_serialize_walker, (void *) &iterator);
     393       
     394        spinlock_unlock(&threads_lock);
     395        interrupts_restore(ipl);
     396       
     397        return ((void *) stats_threads);
     398}
     399
     400/** Get a single task statistics
    354401 *
    355402 * Get statistics of a given task. The task ID is passed
     
    416463                spinlock_unlock(&tasks_lock);
    417464               
    418                 /* Copy task's statistics */
    419                 str_cpy(stats_task->name, TASK_NAME_BUFLEN, task->name);
    420                 stats_task->virtmem = get_task_virtmem(task->as);
    421                 stats_task->threads = atomic_get(&task->refcount);
    422                 task_get_accounting(task, &(stats_task->ucycles),
    423                     &(stats_task->kcycles));
    424                 stats_task->ipc_info = task->ipc_info;
     465                produce_stats_task(task, stats_task);
    425466               
    426467                spinlock_unlock(&task->lock);
     
    492533                ret.data.data = (void *) stats_thread;
    493534                ret.data.size = sizeof(stats_thread_t);
    494        
     535               
    495536                /* Hand-over-hand locking */
    496537                spinlock_lock(&thread->lock);
    497538                spinlock_unlock(&threads_lock);
    498539               
    499                 /* Copy thread's statistics */
    500                 stats_thread->task_id = thread->task->taskid;
    501                 stats_thread->state = thread->state;
    502                 stats_thread->priority = thread->priority;
    503                 stats_thread->ucycles = thread->ucycles;
    504                 stats_thread->kcycles = thread->kcycles;
    505                
    506                 if (thread->cpu != NULL) {
    507                         stats_thread->on_cpu = true;
    508                         stats_thread->cpu = thread->cpu->id;
    509                 } else
    510                         stats_thread->on_cpu = false;
     540                produce_stats_thread(thread, stats_thread);
    511541               
    512542                spinlock_unlock(&thread->lock);
  • uspace/app/tasks/tasks.c

    re535eeb rdec16a2  
    5959{
    6060        size_t count;
    61         task_id_t *ids =
    62             (task_id_t *) stats_get_tasks(&count);
    63        
    64         if (ids == NULL) {
     61        stats_task_t *stats_tasks = stats_get_tasks(&count);
     62       
     63        if (stats_tasks == NULL) {
    6564                fprintf(stderr, "%s: Unable to get tasks\n", NAME);
    6665                return;
     
    7170        size_t i;
    7271        for (i = 0; i < count; i++) {
    73                 stats_task_t *stats_task = stats_get_task(ids[i]);
    74                 if (stats_task != NULL) {
    75                         uint64_t virtmem, ucycles, kcycles;
    76                         char vmsuffix, usuffix, ksuffix;
    77                        
    78                         order_suffix(stats_task->virtmem, &virtmem, &vmsuffix);
    79                         order_suffix(stats_task->ucycles, &ucycles, &usuffix);
    80                         order_suffix(stats_task->kcycles, &kcycles, &ksuffix);
    81                        
    82                         printf("%8" PRIu64 "%8u %8" PRIu64"%c %12"
    83                             PRIu64 "%c %12" PRIu64 "%c %s\n", ids[i], stats_task->threads,
    84                             virtmem, vmsuffix, ucycles, usuffix, kcycles, ksuffix,
    85                             stats_task->name);
    86                        
    87                         free(stats_task);
    88                 } else
    89                         printf("%8" PRIu64 "\n", ids[i]);
    90         }
    91        
    92         free(ids);
     72                uint64_t virtmem, ucycles, kcycles;
     73                char vmsuffix, usuffix, ksuffix;
     74               
     75                order_suffix(stats_tasks[i].virtmem, &virtmem, &vmsuffix);
     76                order_suffix(stats_tasks[i].ucycles, &ucycles, &usuffix);
     77                order_suffix(stats_tasks[i].kcycles, &kcycles, &ksuffix);
     78               
     79                printf("%8" PRIu64 "%8u %8" PRIu64"%c %12"
     80                    PRIu64 "%c %12" PRIu64 "%c %s\n", stats_tasks[i].task_id,
     81                    stats_tasks[i].threads, virtmem, vmsuffix, ucycles, usuffix,
     82                    kcycles, ksuffix, stats_tasks[i].name);
     83        }
     84       
     85        free(stats_tasks);
    9386}
    9487
     
    9689{
    9790        size_t count;
    98         thread_id_t *ids =
    99             (thread_id_t *) stats_get_threads(&count);
    100        
    101         if (ids == NULL) {
     91        stats_thread_t *stats_threads = stats_get_threads(&count);
     92       
     93        if (stats_threads == NULL) {
    10294                fprintf(stderr, "%s: Unable to get threads\n", NAME);
    10395                return;
     
    10799        size_t i;
    108100        for (i = 0; i < count; i++) {
    109                 stats_thread_t *stats_thread = stats_get_thread(ids[i]);
    110                 if (stats_thread != NULL) {
    111                         if ((all) || (stats_thread->task_id == task_id)) {
    112                                 uint64_t ucycles, kcycles;
    113                                 char usuffix, ksuffix;
    114                                
    115                                 order_suffix(stats_thread->ucycles, &ucycles, &usuffix);
    116                                 order_suffix(stats_thread->kcycles, &kcycles, &ksuffix);
    117                                
    118                                 if (stats_thread->on_cpu) {
    119                                         printf("%8" PRIu64 " %-8s %4u %6d %12"
    120                                             PRIu64"%c %12" PRIu64"%c\n", ids[i],
    121                                             thread_get_state(stats_thread->state),
    122                                             stats_thread->cpu, stats_thread->priority,
    123                                             ucycles, usuffix, kcycles, ksuffix);
    124                                 } else {
    125                                         printf("%8" PRIu64 " %-8s ---- %6d %12"
    126                                             PRIu64"%c %12" PRIu64"%c\n", ids[i],
    127                                             thread_get_state(stats_thread->state),
    128                                             stats_thread->priority,
    129                                             ucycles, usuffix, kcycles, ksuffix);
    130                                 }
     101                if ((all) || (stats_threads[i].task_id == task_id)) {
     102                        uint64_t ucycles, kcycles;
     103                        char usuffix, ksuffix;
     104                       
     105                        order_suffix(stats_threads[i].ucycles, &ucycles, &usuffix);
     106                        order_suffix(stats_threads[i].kcycles, &kcycles, &ksuffix);
     107                       
     108                        if (stats_threads[i].on_cpu) {
     109                                printf("%8" PRIu64 " %-8s %4u %6d %12"
     110                                    PRIu64"%c %12" PRIu64"%c\n", stats_threads[i].thread_id,
     111                                    thread_get_state(stats_threads[i].state),
     112                                    stats_threads[i].cpu, stats_threads[i].priority,
     113                                    ucycles, usuffix, kcycles, ksuffix);
     114                        } else {
     115                                printf("%8" PRIu64 " %-8s ---- %6d %12"
     116                                    PRIu64"%c %12" PRIu64"%c\n", stats_threads[i].thread_id,
     117                                    thread_get_state(stats_threads[i].state),
     118                                    stats_threads[i].priority,
     119                                    ucycles, usuffix, kcycles, ksuffix);
    131120                        }
    132                        
    133                         free(stats_thread);
    134                 } else if (all)
    135                         printf("%8" PRIu64 "\n", ids[i]);
    136         }
    137        
    138         free(ids);
     121                }
     122        }
     123       
     124        free(stats_threads);
    139125}
    140126
  • uspace/app/top/Makefile

    re535eeb rdec16a2  
    2929
    3030USPACE_PREFIX = ../..
    31 # BINARY = top
     31BINARY = top
    3232
    3333SOURCES = \
    3434        top.c \
    3535        screen.c \
    36         input.c \
    37         ps.c
     36        input.c
    3837
    3938include $(USPACE_PREFIX)/Makefile.common
  • uspace/app/top/screen.c

    re535eeb rdec16a2  
    11/*
    22 * Copyright (c) 2010 Stanislav Kozina
     3 * Copyright (c) 2010 Martin Decky
    34 * All rights reserved.
    45 *
     
    3839#include <io/console.h>
    3940#include <vfs/vfs.h>
    40 #include <load.h>
    41 #include <kernel/ps/taskinfo.h>
    42 #include <ps.h>
     41#include <stdarg.h>
     42#include <stats.h>
     43#include <inttypes.h>
    4344#include "screen.h"
    4445#include "top.h"
    45 #include "func.h"
    46 
    47 int rows;
    48 int colls;
    49 int up_rows;
    50 
    51 #define WHITE 0xf0f0f0
    52 #define BLACK 0x000000
    53 
    54 static void print_float(ps_float f, int precision)
    55 {
    56         printf("%2u.", f.upper / f.lower);
    57         int i;
    58         unsigned int rest = (f.upper % f.lower) * 10;
    59         for (i = 0; i < precision; ++i) {
    60                 printf("%d", rest / f.lower);
    61                 rest = (rest % f.lower) * 10;
    62         }
    63 }
    64 
    65 static void resume_normal(void)
     46
     47#define WHITE  0xf0f0f0
     48#define BLACK  0x000000
     49
     50static int rows;
     51static int colls;
     52static int up_rows;
     53
     54static void print_float(fixed_float ffloat, unsigned int precision)
     55{
     56        printf("%2" PRIu64 ".", ffloat.upper / ffloat.lower);
     57       
     58        unsigned int i;
     59        uint64_t rest = (ffloat.upper % ffloat.lower) * 10;
     60        for (i = 0; i < precision; i++) {
     61                printf("%" PRIu64, rest / ffloat.lower);
     62                rest = (rest % ffloat.lower) * 10;
     63        }
     64}
     65
     66static void screen_resume_normal(void)
    6667{
    6768        fflush(stdout);
     
    6970}
    7071
     72static void screen_moveto(int r, int c)
     73{
     74        fflush(stdout);
     75        console_goto(fphone(stdout), c, r);
     76}
     77
     78static void screen_clear(void)
     79{
     80        console_clear(fphone(stdout));
     81        screen_moveto(0, 0);
     82        up_rows = 0;
     83        fflush(stdout);
     84}
     85
    7186void screen_init(void)
    7287{
     88        console_cursor_visibility(fphone(stdout), 0);
     89        screen_resume_normal();
     90        screen_clear();
     91       
    7392        console_get_size(fphone(stdout), &colls, &rows);
    74         up_rows = 0;
    75         console_cursor_visibility(fphone(stdout), 0);
    76         resume_normal();
    77         clear_screen();
    78 }
    79 
    80 void clear_screen(void)
    81 {
    82         console_clear(fphone(stdout));
    83         moveto(0, 0);
    84         up_rows = 0;
    85         fflush(stdout);
    86 }
    87 
    88 void moveto(int r, int c)
    89 {
    90         fflush(stdout);
    91         console_goto(fphone(stdout), c, r);
     93}
     94
     95void screen_done(void)
     96{
     97        screen_resume_normal();
     98        screen_clear();
     99        console_cursor_visibility(fphone(stdout), 1);
    92100}
    93101
    94102static inline void print_time(data_t *data)
    95103{
    96         printf("%02d:%02d:%02d ", data->hours, data->minutes, data->seconds);
     104        printf("%02lu:%02lu:%02lu ", data->hours, data->minutes, data->seconds);
    97105}
    98106
    99107static inline void print_uptime(data_t *data)
    100108{
    101         printf("up %4d days, %02d:%02d:%02d, ", data->uptime_d, data->uptime_h,
    102                 data->uptime_m, data->uptime_s);
     109        printf("up %u days, %02u:%02u:%02u, ", data->udays, data->uhours,
     110            data->uminutes, data->useconds);
    103111}
    104112
    105113static inline void print_load(data_t *data)
    106114{
    107         puts("load avarage: ");
    108         print_load_fragment(data->load[0], 2);
    109         puts(" ");
    110         print_load_fragment(data->load[1], 2);
    111         puts(" ");
    112         print_load_fragment(data->load[2], 2);
    113 }
    114 
    115 static inline void print_taskstat(data_t *data)
    116 {
    117         puts("Tasks: ");
    118         printf("%4u total", data->task_count);
    119 }
    120 
    121 static inline void print_threadstat(data_t *data)
    122 {
     115        printf("load avarage: ");
     116       
     117        size_t i;
     118        for (i = 0; i < data->load_count; i++) {
     119                stats_print_load_fragment(data->load[i], 2);
     120                printf(" ");
     121        }
     122}
     123
     124static inline void print_task_summary(data_t *data)
     125{
     126        printf("tasks: %u total", data->tasks_count);
     127}
     128
     129static inline void print_thread_summary(data_t *data)
     130{
     131        size_t total = 0;
     132        size_t running = 0;
     133        size_t ready = 0;
    123134        size_t sleeping = 0;
    124         size_t running = 0;
     135        size_t lingering = 0;
     136        size_t other = 0;
    125137        size_t invalid = 0;
    126         size_t other = 0;
    127         size_t total = 0;
    128         size_t i;
    129         for (i = 0; i < data->thread_count; ++i) {
    130                 ++total;
    131                 switch (data->thread_infos[i].state) {
    132                         case Invalid:
    133                         case Lingering:
    134                                 ++invalid;
    135                                 break;
    136                         case Running:
    137                         case Ready:
    138                                 ++running;
    139                                 break;
    140                         case Sleeping:
    141                                 ++sleeping;
    142                                 break;
    143                         case Entering:
    144                         case Exiting:
    145                                 ++other;
    146                                 break;
     138       
     139       
     140        size_t i;
     141        for (i = 0; i < data->threads_count; i++) {
     142                total++;
     143               
     144                switch (data->threads[i].state) {
     145                case Running:
     146                        running++;
     147                        break;
     148                case Ready:
     149                        ready++;
     150                        break;
     151                case Sleeping:
     152                        sleeping++;
     153                        break;
     154                case Lingering:
     155                        lingering++;
     156                        break;
     157                case Entering:
     158                case Exiting:
     159                        other++;
     160                        break;
     161                default:
     162                        invalid++;
    147163                }
    148164        }
    149         printf("Threads: %5u total, %5u running, %5u sleeping, %5u invalid, %5u other",
    150                 total, running, sleeping, invalid, other);
    151 }
    152 
    153 static inline void print_cpuinfo(data_t *data)
    154 {
    155         unsigned int i;
    156         uspace_cpu_info_t *cpus = data->cpus;
    157         for (i = 0; i < data->cpu_count; ++i) {
    158                 printf("Cpu%u (%4u Mhz): Busy ticks: %6llu, Idle Ticks: %6llu",
    159                         i, (unsigned int)cpus[i].frequency_mhz, cpus[i].busy_ticks,
    160                         cpus[i].idle_ticks);
     165       
     166        printf("threads: %u total, %u running, %u ready, %u sleeping, %u lingering, "
     167            "%u other, %u invalid",
     168            total, running, ready, sleeping, lingering, other, invalid);
     169}
     170
     171static inline void print_cpu_info(data_t *data)
     172{
     173        size_t i;
     174        for (i = 0; i < data->cpus_count; i++) {
     175                printf("cpu%u (%4" PRIu16 " MHz): busy ticks: "
     176                    "%" PRIu64 ", idle ticks: %" PRIu64,
     177                    data->cpus[i].id, data->cpus[i].frequency_mhz,
     178                    data->cpus[i].busy_ticks, data->cpus[i].idle_ticks);
    161179                printf(", idle: ");
    162                 print_float(data->cpu_perc[i].idle, 2);
    163                 puts("%, busy: ");
    164                 print_float(data->cpu_perc[i].busy, 2);
    165                 puts("%\n");
    166                 ++up_rows;
    167         }
    168 }
    169 
    170 static inline void print_meminfo(data_t *data)
    171 {
    172         uint64_t newsize;
    173         char suffix;
    174         order(data->mem_info.total, &newsize, &suffix);
    175         printf("Mem: %8llu %c total", newsize, suffix);
    176         order(data->mem_info.used, &newsize, &suffix);
    177         printf(", %8llu %c used", newsize, suffix);
    178         order(data->mem_info.free, &newsize, &suffix);
    179         printf(", %8llu %c free", newsize, suffix);
     180                print_float(data->cpus_perc[i].idle, 2);
     181                printf("%%, busy: ");
     182                print_float(data->cpus_perc[i].busy, 2);
     183               
     184                printf("%%\n");
     185                up_rows++;
     186        }
     187}
     188
     189static inline void print_physmem_info(data_t *data)
     190{
     191        uint64_t total;
     192        uint64_t unavail;
     193        uint64_t used;
     194        uint64_t free;
     195        char total_suffix;
     196        char unavail_suffix;
     197        char used_suffix;
     198        char free_suffix;
     199       
     200        order_suffix(data->physmem->total, &total, &total_suffix);
     201        order_suffix(data->physmem->unavail, &unavail, &unavail_suffix);
     202        order_suffix(data->physmem->used, &used, &used_suffix);
     203        order_suffix(data->physmem->free, &free, &free_suffix);
     204       
     205        printf("memory: %" PRIu64 "%c total, %" PRIu64 "%c unavail, %"
     206            PRIu64 "%c used, %" PRIu64 "%c free", total, total_suffix,
     207            unavail, unavail_suffix, used, used_suffix, free, free_suffix);
    180208}
    181209
    182210static inline void print_tasks(data_t *data, int row)
    183211{
    184         int i;
    185         for (i = 0; i < (int)data->task_count; ++i) {
    186                 if (row + i > rows)
    187                         return;
    188                 task_info_t *taskinfo = &data->taskinfos[i];
    189                 uint64_t mem;
    190                 char suffix;
    191                 order(taskinfo->virt_mem, &mem, &suffix);
    192                 printf("%8llu %8u %8llu%c ", taskinfo->taskid,
    193                         taskinfo->thread_count, mem, suffix);
    194                 task_perc_t *taskperc = &data->task_perc[i];
    195                 puts("   ");
    196                 print_float(taskperc->mem, 2);
    197                 puts("%   ");
    198                 print_float(taskperc->ucycles, 2);
    199                 puts("%   ");
    200                 print_float(taskperc->kcycles, 2);
    201                 puts("% ");
    202                 printf("%s\n", taskinfo->name);
     212        size_t i;
     213        for (i = 0; i < data->tasks_count; i++, row++) {
     214                if (row > rows)
     215                        break;
     216               
     217                uint64_t virtmem;
     218                char virtmem_suffix;
     219                order_suffix(data->tasks[i].virtmem, &virtmem, &virtmem_suffix);
     220               
     221                printf("%8" PRIu64 " %8u %8" PRIu64 "%c ", data->tasks[i].task_id,
     222                    data->tasks[i].threads, virtmem, virtmem_suffix);
     223                printf("   ");
     224                print_float(data->tasks_perc[i].virtmem, 2);
     225                printf("%%   ");
     226                print_float(data->tasks_perc[i].ucycles, 2);
     227                printf("%%   ");
     228                print_float(data->tasks_perc[i].kcycles, 2);
     229                printf("%% %s\n", data->tasks[i].name);
    203230        }
    204231}
     
    208235        fflush(stdout);
    209236        console_set_rgb_color(fphone(stdout), WHITE, BLACK);
     237       
    210238        printf("      ID  Threads      Mem      %%Mem %%uCycles %%kCycles  Name");
     239       
    211240        int i;
    212241        for (i = 61; i < colls; ++i)
    213                 puts(" ");
     242                printf(" ");
     243       
    214244        fflush(stdout);
    215245        console_set_rgb_color(fphone(stdout), BLACK, WHITE);
     
    220250        fflush(stdout);
    221251        console_set_rgb_color(fphone(stdout), WHITE, BLACK);
     252       
    222253        printf("      ID Calls sent Calls recv Answs sent Answs recv  IRQn recv       Forw Name");
     254       
    223255        int i;
    224256        for (i = 80; i < colls; ++i)
    225                 puts(" ");
     257                printf(" ");
     258       
    226259        fflush(stdout);
    227260        console_set_rgb_color(fphone(stdout), BLACK, WHITE);
     
    230263static inline void print_ipc(data_t *data, int row)
    231264{
    232         int i;
    233         for (i = 0; i < (int)data->task_count; ++i) {
    234                 if (row + i > rows)
    235                         return;
    236                 task_info_t *taskinfo = &data->taskinfos[i];
    237                 task_ipc_info_t *ipcinfo = &taskinfo->ipc_info;
    238                 printf("%8llu ", taskinfo->taskid);
    239                 printf("%10llu %10llu %10llu %10llu %10llu %10llu ",
    240                                 ipcinfo->call_sent, ipcinfo->call_recieved,
    241                                 ipcinfo->answer_sent, ipcinfo->answer_recieved,
    242                                 ipcinfo->irq_notif_recieved, ipcinfo->forwarded);
    243                 printf("%s\n", taskinfo->name);
     265        size_t i;
     266        for (i = 0; i < data->tasks_count; i++, row++) {
     267                if (row > rows)
     268                        break;
     269               
     270                printf("%8" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64
     271                     " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %s\n",
     272                     data->tasks[i].task_id, data->tasks[i].ipc_info.call_sent,
     273                     data->tasks[i].ipc_info.call_recieved,
     274                     data->tasks[i].ipc_info.answer_sent,
     275                     data->tasks[i].ipc_info.answer_recieved,
     276                     data->tasks[i].ipc_info.irq_notif_recieved,
     277                     data->tasks[i].ipc_info.forwarded, data->tasks[i].name);
    244278        }
    245279}
     
    247281void print_data(data_t *data)
    248282{
    249         clear_screen();
    250         fflush(stdout);
     283        screen_clear();
     284        fflush(stdout);
     285       
    251286        printf("top - ");
    252287        print_time(data);
    253288        print_uptime(data);
    254289        print_load(data);
    255         puts("\n");
    256         ++up_rows;
    257         print_taskstat(data);
    258         puts("\n");
    259         ++up_rows;
    260         print_threadstat(data);
    261         puts("\n");
    262         ++up_rows;
    263         print_cpuinfo(data);
    264         print_meminfo(data);
    265         puts("\n");
    266         ++up_rows;
    267         puts("\n");
    268         ++up_rows;
     290       
     291        printf("\n");
     292        up_rows++;
     293       
     294        print_task_summary(data);
     295       
     296        printf("\n");
     297        up_rows++;
     298       
     299        print_thread_summary(data);
     300       
     301        printf("\n");
     302        up_rows++;
     303       
     304        print_cpu_info(data);
     305        print_physmem_info(data);
     306       
     307        printf("\n");
     308        up_rows++;
     309       
     310        /* Empty row for warnings */
     311        printf("\n");
     312       
    269313        if (operation_type == OP_IPC) {
    270314                print_ipc_head();
    271                 puts("\n");
     315                printf("\n");
    272316                print_ipc(data, up_rows);
    273317        } else {
    274318                print_task_head();
    275                 puts("\n");
     319                printf("\n");
    276320                print_tasks(data, up_rows);
    277321        }
     322       
     323        fflush(stdout);
     324}
     325
     326void print_warning(const char *fmt, ...)
     327{
     328        screen_moveto(up_rows, 0);
     329       
     330        va_list args;
     331        va_start(args, fmt);
     332        vprintf(fmt, args);
     333        va_end(args);
     334       
    278335        fflush(stdout);
    279336}
  • uspace/app/top/screen.h

    re535eeb rdec16a2  
    11/*
    2  * Copyright (c) 2008 Stanislav Kozina
     2 * Copyright (c) 2010 Stanislav Kozina
     3 * Copyright (c) 2010 Martin Decky
    34 * All rights reserved.
    45 *
     
    3637#include "top.h"
    3738
    38 extern int rows;
    39 extern int colls;
    40 
    4139extern void screen_init(void);
    42 extern void clear_screen(void);
    43 extern void moveto(int r, int c);
    44 extern void print_data(data_t *data);
    45 
    46 extern int up_rows;
    47 #define PRINT_WARNING(message, ...) \
    48 do { \
    49         moveto(up_rows - 1, 0); \
    50         printf(message, ##__VA_ARGS__); \
    51         fflush(stdout); \
    52 } while (0)
     40extern void screen_done(void);
     41extern void print_data(data_t *);
     42extern void print_warning(const char *, ...);
    5343
    5444#endif
  • uspace/app/top/top.c

    re535eeb rdec16a2  
    11/*
    22 * Copyright (c) 2010 Stanislav Kozina
     3 * Copyright (c) 2010 Martin Decky
    34 * All rights reserved.
    45 *
     
    3839#include <stdlib.h>
    3940#include <unistd.h>
    40 #include <uptime.h>
    4141#include <task.h>
    4242#include <thread.h>
    4343#include <sys/time.h>
    44 #include <load.h>
    45 #include <ps.h>
    4644#include <arch/barrier.h>
     45#include <errno.h>
    4746#include "screen.h"
    4847#include "input.h"
    4948#include "top.h"
    50 #include "ps.h"
    51 
    52 #define UPDATE_INTERVAL 1
    53 
    54 #define DAY 86400
    55 #define HOUR 3600
    56 #define MINUTE 60
     49
     50#define NAME  "top"
     51
     52#define UPDATE_INTERVAL  1
     53
     54#define DAY     86400
     55#define HOUR    3600
     56#define MINUTE  60
    5757
    5858int operation_type;
    5959
    60 static void read_data(data_t *target)
     60static const char *read_data(data_t *target)
    6161{
    62         /* Read current time */
     62        /* Initialize data */
     63        target->load = NULL;
     64        target->cpus = NULL;
     65        target->cpus_perc = NULL;
     66        target->tasks = NULL;
     67        target->tasks_perc = NULL;
     68        target->threads = NULL;
     69        target->physmem = NULL;
     70       
     71        /* Get current time */
    6372        struct timeval time;
    64         if (gettimeofday(&time, NULL) != 0) {
    65                 printf("Cannot get time of day!\n");
    66                 exit(1);
    67         }
     73        if (gettimeofday(&time, NULL) != EOK)
     74                return "Cannot get time of day";
     75       
    6876        target->hours = (time.tv_sec % DAY) / HOUR;
    6977        target->minutes = (time.tv_sec % HOUR) / MINUTE;
    7078        target->seconds = time.tv_sec % MINUTE;
    71 
    72         /* Read uptime */
    73         uint64_t uptime;
    74         get_uptime(&uptime);
    75         target->uptime_d = uptime / DAY;
    76         target->uptime_h = (uptime % DAY) / HOUR;
    77         target->uptime_m = (uptime % HOUR) / MINUTE;
    78         target->uptime_s = uptime % MINUTE;
    79 
    80         /* Read load */
    81         get_load(target->load);
    82 
    83         /* Read task ids */
    84         target->task_count = get_tasks(&target->taskinfos);
    85 
    86         /* Read all threads */
    87         target->thread_count = get_threads(&target->thread_infos);
    88 
    89         /* Read cpu infos */
    90         target->cpu_count = get_cpu_infos(&target->cpus);
    91 
    92         /* Read mem info */
    93         get_mem_info(&target->mem_info);
     79       
     80        /* Get uptime */
     81        sysarg_t uptime = stats_get_uptime();
     82        target->udays = uptime / DAY;
     83        target->uhours = (uptime % DAY) / HOUR;
     84        target->uminutes = (uptime % HOUR) / MINUTE;
     85        target->useconds = uptime % MINUTE;
     86       
     87        /* Get load */
     88        target->load = stats_get_load(&(target->load_count));
     89        if (target->load == NULL)
     90                return "Cannot get system load";
     91       
     92        /* Get CPUs */
     93        target->cpus = stats_get_cpus(&(target->cpus_count));
     94        if (target->cpus == NULL)
     95                return "Cannot get CPUs";
     96       
     97        target->cpus_perc =
     98            (perc_cpu_t *) calloc(target->cpus_count, sizeof(perc_cpu_t));
     99        if (target->cpus_perc == NULL)
     100                return "Not enough memory for CPU utilization";
     101       
     102        /* Get tasks */
     103        target->tasks = stats_get_tasks(&(target->tasks_count));
     104        if (target->tasks == NULL)
     105                return "Cannot get tasks";
     106       
     107        target->tasks_perc =
     108            (perc_task_t *) calloc(target->tasks_count, sizeof(perc_task_t));
     109        if (target->tasks_perc == NULL)
     110                return "Not enough memory for task utilization";
     111       
     112        /* Get threads */
     113        target->threads = stats_get_threads(&(target->threads_count));
     114        if (target->threads == NULL)
     115                return "Cannot get threads";
     116       
     117        /* Get physical memory */
     118        target->physmem = stats_get_physmem();
     119        if (target->physmem == NULL)
     120                return "Cannot get physical memory";
     121       
     122        return NULL;
    94123}
    95124
    96125/** Computes percentage differencies from old_data to new_data
    97126 *
    98  * @param old_data      Pointer to old data strucutre.
    99  * @param new_data      Pointer to actual data where percetages are stored.
    100  *
    101  */
    102 static void compute_percentages(data_t *old_data, data_t *new_data)
     127 * @param old_data Pointer to old data strucutre.
     128 * @param new_data Pointer to actual data where percetages are stored.
     129 *
     130 */
     131static const char *compute_percentages(data_t *old_data, data_t *new_data)
    103132{
    104         /* Foreach cpu, compute total ticks and divide it between user and
    105          * system */
    106         unsigned int i;
    107         new_data->cpu_perc = malloc(new_data->cpu_count * sizeof(cpu_perc_t));
    108         for (i = 0; i < new_data->cpu_count; ++i) {
    109                 uint64_t idle = new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks;
    110                 uint64_t busy = new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks;
     133        /* Allocate memory */
     134       
     135        uint64_t *ucycles_diff = calloc(new_data->tasks_count, sizeof(uint64_t));
     136        if (ucycles_diff == NULL)
     137                return "Not enough memory for user utilization";
     138       
     139        uint64_t *kcycles_diff = calloc(new_data->tasks_count, sizeof(uint64_t));
     140        if (kcycles_diff == NULL) {
     141                free(ucycles_diff);
     142                return "Not enough memory for kernel utilization";
     143        }
     144       
     145        /* For each CPU: Compute total ticks and divide it between
     146           user and kernel */
     147       
     148        size_t i;
     149        for (i = 0; i < new_data->cpus_count; i++) {
     150                uint64_t idle =
     151                    new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks;
     152                uint64_t busy =
     153                    new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks;
    111154                uint64_t sum = idle + busy;
    112                 FRACTION_TO_FLOAT(new_data->cpu_perc[i].idle, idle * 100, sum);
    113                 FRACTION_TO_FLOAT(new_data->cpu_perc[i].busy, busy * 100, sum);
    114         }
    115 
     155               
     156                FRACTION_TO_FLOAT(new_data->cpus_perc[i].idle, idle * 100, sum);
     157                FRACTION_TO_FLOAT(new_data->cpus_perc[i].busy, busy * 100, sum);
     158        }
     159       
    116160        /* For all tasks compute sum and differencies of all cycles */
    117         uint64_t mem_total = 1; /*< Must NOT be null! */
    118         uint64_t ucycles_total = 1; /*< Must NOT be null! */
    119         uint64_t kcycles_total = 1; /*< Must NOT be null! */
    120         uint64_t *ucycles_diff = malloc(new_data->task_count * sizeof(uint64_t));
    121         uint64_t *kcycles_diff = malloc(new_data->task_count * sizeof(uint64_t));
    122         unsigned int j = 0;
    123         for (i = 0; i < new_data->task_count; ++i) {
    124                 /* Jump over all death tasks */
    125                 while (old_data->taskinfos[j].taskid < new_data->taskinfos[i].taskid)
    126                         ++j;
    127                 if (old_data->taskinfos[j].taskid > new_data->taskinfos[i].taskid) {
     161       
     162        uint64_t virtmem_total = 1;  /* Must NOT be zero */
     163        uint64_t ucycles_total = 1;  /* Must NOT be zero */
     164        uint64_t kcycles_total = 1;  /* Must NOT be zero */
     165       
     166        for (i = 0; i < new_data->tasks_count; i++) {
     167                /* Match task with the previous instance */
     168               
     169                bool found = false;
     170                size_t j;
     171                for (j = 0; j < old_data->tasks_count; j++) {
     172                        if (new_data->tasks[i].task_id == old_data->tasks[j].task_id) {
     173                                found = true;
     174                                break;
     175                        }
     176                }
     177               
     178                if (!found) {
    128179                        /* This is newly borned task, ignore it */
    129180                        ucycles_diff[i] = 0;
     
    131182                        continue;
    132183                }
    133                 /* Now we now we have task with same id */
    134                 ucycles_diff[i] = new_data->taskinfos[i].ucycles - old_data->taskinfos[j].ucycles;
    135                 kcycles_diff[i] = new_data->taskinfos[i].kcycles - old_data->taskinfos[j].kcycles;
    136 
    137                 mem_total += new_data->taskinfos[i].virt_mem;
     184               
     185                ucycles_diff[i] =
     186                    new_data->tasks[i].ucycles - old_data->tasks[j].ucycles;
     187                kcycles_diff[i] =
     188                    new_data->tasks[i].kcycles - old_data->tasks[j].kcycles;
     189               
     190                virtmem_total += new_data->tasks[i].virtmem;
    138191                ucycles_total += ucycles_diff[i];
    139192                kcycles_total += kcycles_diff[i];
    140193        }
    141 
    142         /* And now compute percental change */
    143         new_data->task_perc = malloc(new_data->task_count * sizeof(task_perc_t));
    144         for (i = 0; i < new_data->task_count; ++i) {
    145                 FRACTION_TO_FLOAT(new_data->task_perc[i].mem, new_data->taskinfos[i].virt_mem * 100, mem_total);
    146                 FRACTION_TO_FLOAT(new_data->task_perc[i].ucycles, ucycles_diff[i] * 100, ucycles_total);
    147                 FRACTION_TO_FLOAT(new_data->task_perc[i].kcycles, kcycles_diff[i] * 100, kcycles_total);
    148         }
    149 
    150         /* Wait until coprocessor finishes its work */
    151         write_barrier();
    152 
    153         /* And free temporary structures */
     194       
     195        /* For each task: Compute percential change */
     196       
     197        for (i = 0; i < new_data->tasks_count; i++) {
     198                FRACTION_TO_FLOAT(new_data->tasks_perc[i].virtmem,
     199                    new_data->tasks[i].virtmem * 100, virtmem_total);
     200                FRACTION_TO_FLOAT(new_data->tasks_perc[i].ucycles,
     201                    ucycles_diff[i] * 100, ucycles_total);
     202                FRACTION_TO_FLOAT(new_data->tasks_perc[i].kcycles,
     203                    kcycles_diff[i] * 100, kcycles_total);
     204        }
     205       
     206        /* Cleanup */
     207       
    154208        free(ucycles_diff);
    155209        free(kcycles_diff);
     210       
     211        return NULL;
    156212}
    157213
    158214static void free_data(data_t *target)
    159215{
    160         free(target->taskinfos);
    161         free(target->thread_infos);
    162         free(target->cpus);
    163         free(target->cpu_perc);
    164         free(target->task_perc);
     216        if (target->load != NULL)
     217                free(target->load);
     218       
     219        if (target->cpus != NULL)
     220                free(target->cpus);
     221       
     222        if (target->cpus_perc != NULL)
     223                free(target->cpus_perc);
     224       
     225        if (target->tasks != NULL)
     226                free(target->tasks);
     227       
     228        if (target->tasks_perc != NULL)
     229                free(target->tasks_perc);
     230       
     231        if (target->threads != NULL)
     232                free(target->threads);
     233       
     234        if (target->physmem != NULL)
     235                free(target->physmem);
    165236}
    166 
    167 static inline void swap(data_t **first, data_t **second)
    168 {
    169         data_t *temp;
    170         temp = *first;
    171         *first = *second;
    172         *second = temp;
    173 }
    174 
    175 static data_t data[2];
    176237
    177238int main(int argc, char *argv[])
    178239{
    179         data_t *data1 = &data[0];
    180         data_t *data2 = &data[1];
     240        data_t data;
     241        data_t data_prev;
     242        const char *ret = NULL;
     243       
    181244        screen_init();
    182 
    183         /* Read initial stats */
    184245        printf("Reading initial data...\n");
    185         read_data(data1);
     246       
     247        if ((ret = read_data(&data_prev)) != NULL)
     248                goto out;
     249       
    186250        /* Compute some rubbish to have initialised values */
    187         compute_percentages(data1, data1);
    188 
    189         /* And paint screen until death... */
     251        if ((ret = compute_percentages(&data_prev, &data_prev)) != NULL)
     252                goto out;
     253       
     254        /* And paint screen until death */
    190255        operation_type = OP_TASKS;
    191256        while (true) {
    192257                char c = tgetchar(UPDATE_INTERVAL);
    193258                if (c < 0) {
    194                         read_data(data2);
    195                         compute_percentages(data1, data2);
    196                         free_data(data1);
    197                         print_data(data2);
    198                         swap(&data1, &data2);
     259                        if ((ret = read_data(&data)) != NULL) {
     260                                free_data(&data);
     261                                goto out;
     262                        }
     263                       
     264                        if ((ret = compute_percentages(&data_prev, &data)) != NULL) {
     265                                free_data(&data);
     266                                goto out;
     267                        }
     268                       
     269                        print_data(&data);
     270                        free_data(&data_prev);
     271                        data_prev = data;
     272                       
    199273                        continue;
    200274                }
     275               
    201276                switch (c) {
    202277                        case 'q':
    203                                 clear_screen();
    204                                 return 0;
     278                                goto out;
    205279                        case 'i':
    206                                 PRINT_WARNING("Showing IPC statistics", c);
     280                                print_warning("Showing IPC statistics");
    207281                                operation_type = OP_IPC;
    208282                                break;
    209283                        case 't':
    210                                 PRINT_WARNING("Showing task stats", c);
     284                                print_warning("Showing task statistics");
    211285                                operation_type = OP_TASKS;
    212286                                break;
    213287                        default:
    214                                 PRINT_WARNING("Unknown command: %c", c);
     288                                print_warning("Unknown command: %c", c);
    215289                                break;
    216290                }
    217 
    218         }
    219 
    220         free_data(data1);
    221         free_data(data2);
     291        }
     292       
     293out:
     294        screen_done();
     295        free_data(&data_prev);
     296       
     297        if (ret != NULL) {
     298                fprintf(stderr, "%s: %s\n", NAME, ret);
     299                return 1;
     300        }
     301       
    222302        return 0;
    223303}
  • uspace/app/top/top.h

    re535eeb rdec16a2  
    11/*
    2  * Copyright (c) 2008 Stanislav Kozina
     2 * Copyright (c) 2010 Stanislav Kozina
     3 * Copyright (c) 2010 Martin Decky
    34 * All rights reserved.
    45 *
     
    3536
    3637#include <task.h>
    37 #include <kernel/ps/cpuinfo.h>
    38 #include <kernel/ps/taskinfo.h>
     38#include <stats.h>
     39#include <time.h>
    3940
    4041#define FRACTION_TO_FLOAT(float, a, b) { \
     
    4344}
    4445
    45 #define OP_TASKS 1
    46 #define OP_IPC 2
     46#define OP_TASKS  1
     47#define OP_IPC    2
     48
    4749extern int operation_type;
    4850
     
    5052        uint64_t upper;
    5153        uint64_t lower;
    52 } ps_float;
     54} fixed_float;
    5355
    5456typedef struct {
    55         ps_float idle;
    56         ps_float busy;
    57 } cpu_perc_t;
     57        fixed_float idle;
     58        fixed_float busy;
     59} perc_cpu_t;
    5860
    5961typedef struct {
    60         ps_float ucycles;
    61         ps_float kcycles;
    62         ps_float mem;
    63 } task_perc_t;
     62        fixed_float ucycles;
     63        fixed_float kcycles;
     64        fixed_float virtmem;
     65} perc_task_t;
    6466
    6567typedef struct {
    66         unsigned int hours;
    67         unsigned int minutes;
    68         unsigned int seconds;
    69 
    70         unsigned int uptime_d;
    71         unsigned int uptime_h;
    72         unsigned int uptime_m;
    73         unsigned int uptime_s;
    74 
    75         unsigned long load[3];
    76 
    77         size_t task_count;
    78         task_info_t *taskinfos;
    79         task_perc_t *task_perc;
    80 
    81         size_t thread_count;
    82         thread_info_t *thread_infos;
    83 
    84         unsigned int cpu_count;
    85         uspace_cpu_info_t *cpus;
    86         cpu_perc_t *cpu_perc;
    87 
    88         uspace_mem_info_t mem_info;
     68        time_t hours;
     69        time_t minutes;
     70        time_t seconds;
     71       
     72        sysarg_t udays;
     73        sysarg_t uhours;
     74        sysarg_t uminutes;
     75        sysarg_t useconds;
     76       
     77        size_t load_count;
     78        load_t *load;
     79       
     80        size_t cpus_count;
     81        stats_cpu_t *cpus;
     82        perc_cpu_t *cpus_perc;
     83       
     84        size_t tasks_count;
     85        stats_task_t *tasks;
     86        perc_task_t *tasks_perc;
     87       
     88        size_t threads_count;
     89        stats_thread_t *threads;
     90       
     91        stats_physmem_t *physmem;
    8992} data_t;
    9093
  • uspace/lib/c/generic/stats.c

    re535eeb rdec16a2  
    9696}
    9797
    98 /** Get task IDs
    99  *
    100  * @param count Number of IDs returned.
    101  *
    102  * @return Array of IDs (task_id_t).
    103  *         If non-NULL then it should be eventually freed
    104  *         by free().
    105  *
    106  */
    107 task_id_t *stats_get_tasks(size_t *count)
    108 {
    109         size_t size = 0;
    110         task_id_t *ids =
    111             (task_id_t *) sysinfo_get_data("system.tasks", &size);
    112        
    113         assert((size % sizeof(task_id_t)) == 0);
    114        
    115         *count = size / sizeof(task_id_t);
    116         return ids;
     98/** Get task statistics
     99 *
     100 * @param count Number of records returned.
     101 *
     102 * @return Array of stats_task_t structures.
     103 *         If non-NULL then it should be eventually freed
     104 *         by free().
     105 *
     106 */
     107stats_task_t *stats_get_tasks(size_t *count)
     108{
     109        size_t size = 0;
     110        stats_task_t *stats_tasks =
     111            (stats_task_t *) sysinfo_get_data("system.tasks", &size);
     112       
     113        assert((size % sizeof(stats_task_t)) == 0);
     114       
     115        *count = size / sizeof(stats_task_t);
     116        return stats_tasks;
    117117}
    118118
     
    140140}
    141141
    142 /** Get thread IDs
    143  *
    144  * @param count Number of IDs returned.
    145  *
    146  * @return Array of IDs (thread_id_t).
    147  *         If non-NULL then it should be eventually freed
    148  *         by free().
    149  *
    150  */
    151 thread_id_t *stats_get_threads(size_t *count)
    152 {
    153         size_t size = 0;
    154         thread_id_t *ids =
    155             (thread_id_t *) sysinfo_get_data("system.threads", &size);
    156        
    157         assert((size % sizeof(thread_id_t)) == 0);
    158        
    159         *count = size / sizeof(thread_id_t);
    160         return ids;
     142/** Get thread statistics.
     143 *
     144 * @param count Number of records returned.
     145 *
     146 * @return Array of stats_thread_t structures.
     147 *         If non-NULL then it should be eventually freed
     148 *         by free().
     149 *
     150 */
     151stats_thread_t *stats_get_threads(size_t *count)
     152{
     153        size_t size = 0;
     154        stats_thread_t *stats_threads =
     155            (stats_thread_t *) sysinfo_get_data("system.threads", &size);
     156       
     157        assert((size % sizeof(stats_thread_t)) == 0);
     158       
     159        *count = size / sizeof(stats_thread_t);
     160        return stats_threads;
    161161}
    162162
  • uspace/lib/c/include/stats.h

    re535eeb rdec16a2  
    4747extern sysarg_t stats_get_uptime(void);
    4848
    49 extern task_id_t *stats_get_tasks(size_t *);
     49extern stats_task_t *stats_get_tasks(size_t *);
    5050extern stats_task_t *stats_get_task(task_id_t);
    5151
    52 extern thread_id_t *stats_get_threads(size_t *);
     52extern stats_thread_t *stats_get_threads(size_t *);
    5353extern stats_thread_t *stats_get_thread(thread_id_t);
    5454
Note: See TracChangeset for help on using the changeset viewer.