Changeset e1b6742 in mainline


Ignore:
Timestamp:
2010-04-18T12:17:11Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e535eeb
Parents:
bbda5ab
Message:

export threads to user space
the "tasks" command can now print all threads or threads belonging to a task

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/proc/thread.h

    rbbda5ab re1b6742  
    4848#include <proc/uarg.h>
    4949#include <udebug/udebug.h>
     50#include <sysinfo/abi.h>
    5051
    5152#define THREAD_STACK_SIZE       STACK_SIZE
     
    6970#define THREAD_FLAG_NOATTACH    (1 << 3)
    7071
    71 /** Thread states. */
    72 typedef enum {
    73         /** It is an error, if thread is found in this state. */
    74         Invalid,
    75         /** State of a thread that is currently executing on some CPU. */
    76         Running,
    77         /** Thread in this state is waiting for an event. */
    78         Sleeping,
    79         /** State of threads in a run queue. */
    80         Ready,
    81         /** Threads are in this state before they are first readied. */
    82         Entering,
    83         /** After a thread calls thread_exit(), it is put into Exiting state. */
    84         Exiting,
    85         /** Threads that were not detached but exited are Lingering. */
    86         Lingering
    87 } state_t;
    88 
    8972/** Thread structure. There is one per thread. */
    9073typedef struct thread {
     
    253236extern void thread_print_list(void);
    254237extern void thread_destroy(thread_t *);
     238extern thread_t *thread_find_by_id(thread_id_t);
    255239extern void thread_update_accounting(bool);
    256240extern bool thread_exists(thread_t *);
  • kernel/generic/include/sysinfo/abi.h

    rbbda5ab re1b6742  
    4242/** Maximum task name size */
    4343#define TASK_NAME_BUFLEN  20
     44
     45/** Thread states */
     46typedef enum {
     47        /** It is an error, if thread is found in this state. */
     48        Invalid,
     49        /** State of a thread that is currently executing on some CPU. */
     50        Running,
     51        /** Thread in this state is waiting for an event. */
     52        Sleeping,
     53        /** State of threads in a run queue. */
     54        Ready,
     55        /** Threads are in this state before they are first readied. */
     56        Entering,
     57        /** After a thread calls thread_exit(), it is put into Exiting state. */
     58        Exiting,
     59        /** Threads that were not detached but exited are Lingering. */
     60        Lingering
     61} state_t;
    4462
    4563/** Statistics about a single CPU
     
    89107} stats_task_t;
    90108
     109/** Statistics about a single thread
     110 *
     111 */
     112typedef 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;
     120} stats_thread_t;
     121
    91122/** Load fixed-point value */
    92123typedef uint32_t load_t;
  • kernel/generic/include/sysinfo/sysinfo.h

    rbbda5ab re1b6742  
    105105
    106106/** Generated subtree function */
    107 typedef sysinfo_return_t (*sysinfo_fn_subtree_t)(const char *);
     107typedef sysinfo_return_t (*sysinfo_fn_subtree_t)(const char *, bool);
    108108
    109109/** Sysinfo subtree (union)
  • kernel/generic/src/proc/task.c

    rbbda5ab re1b6742  
    312312 * @param id Task ID.
    313313 *
    314  * @return Task structure address or NULL if there is no such task
    315  *         ID.
     314 * @return Task structure address or NULL if there is no such task ID.
    316315 *
    317316 */
    318317task_t *task_find_by_id(task_id_t id)
    319318{
    320         avltree_node_t *node;
    321         node = avltree_search(&tasks_tree, (avltree_key_t) id);
     319        avltree_node_t *node =
     320            avltree_search(&tasks_tree, (avltree_key_t) id);
    322321       
    323322        if (node)
  • kernel/generic/src/proc/thread.c

    rbbda5ab re1b6742  
    8484        "Exiting",
    8585        "Lingering"
    86 };
     86};
     87
     88typedef struct {
     89        thread_id_t thread_id;
     90        thread_t *thread;
     91} thread_iterator_t;
    8792
    8893/** Lock protecting the threads_tree AVL tree.
     
    726731        THREAD->last_cycle = time;
    727732}
     733
     734static bool thread_search_walker(avltree_node_t *node, void *arg)
     735{
     736        thread_t *thread =
     737            (thread_t *) avltree_get_instance(node, thread_t, threads_tree_node);
     738        thread_iterator_t *iterator = (thread_iterator_t *) arg;
     739       
     740        if (thread->tid == iterator->thread_id) {
     741                iterator->thread = thread;
     742                return false;
     743        }
     744       
     745        return true;
     746}
     747
     748/** Find thread structure corresponding to thread ID.
     749 *
     750 * The threads_lock must be already held by the caller of this function and
     751 * interrupts must be disabled.
     752 *
     753 * @param id Thread ID.
     754 *
     755 * @return Thread structure address or NULL if there is no such thread ID.
     756 *
     757 */
     758thread_t *thread_find_by_id(thread_id_t thread_id)
     759{
     760        thread_iterator_t iterator;
     761       
     762        iterator.thread_id = thread_id;
     763        iterator.thread = NULL;
     764       
     765        avltree_walk(&threads_tree, thread_search_walker, (void *) &iterator);
     766       
     767        return iterator.thread;
     768}
     769
    728770
    729771/** Process syscall to create new thread.
  • kernel/generic/src/sysinfo/stats.c

    rbbda5ab re1b6742  
    4040#include <time/clock.h>
    4141#include <mm/frame.h>
     42#include <proc/task.h>
    4243#include <proc/thread.h>
    4344#include <str.h>
     
    127128}
    128129
    129 /** Count number of tasks
    130  *
    131  * AVL task tree walker for counting tasks.
    132  *
    133  * @param node AVL task tree node (unused).
    134  * @param arg  Pointer to the counter.
     130/** Count number of nodes in an AVL tree
     131 *
     132 * AVL tree walker for counting nodes.
     133 *
     134 * @param node AVL tree node (unused).
     135 * @param arg  Pointer to the counter (size_t).
    135136 *
    136137 * @param Always true (continue the walk).
    137138 *
    138139 */
    139 static bool task_count_walker(avltree_node_t *node, void *arg)
     140static bool avl_count_walker(avltree_node_t *node, void *arg)
    140141{
    141142        size_t *count = (size_t *) arg;
     
    192193        /* First walk the task tree to count the tasks */
    193194        size_t count = 0;
    194         avltree_walk(&tasks_tree, task_count_walker, (void *) &count);
     195        avltree_walk(&tasks_tree, avl_count_walker, (void *) &count);
    195196       
    196197        if (count == 0) {
     
    228229       
    229230        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 */
     244static 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 */
     271static 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);
    230316}
    231317
     
    271357 * but it is still reasonable for the given purpose).
    272358 *
    273  * @param name Task ID (string-encoded number).
     359 * @param name    Task ID (string-encoded number).
     360 * @param dry_run Do not get the data, just calculate the size.
    274361 *
    275362 * @return Sysinfo return holder. The type of the returned
     
    281368 *
    282369 */
    283 static sysinfo_return_t get_stats_task(const char *name)
     370static sysinfo_return_t get_stats_task(const char *name, bool dry_run)
    284371{
    285372        /* Initially no return value */
     
    292379                return ret;
    293380       
    294         /* Allocate stats_task_t structure */
    295         stats_task_t *stats_task =
    296             (stats_task_t *) malloc(sizeof(stats_task_t), FRAME_ATOMIC);
    297         if (stats_task == NULL)
    298                 return ret;
    299        
    300381        /* Messing with task structures, avoid deadlock */
    301382        ipl_t ipl = interrupts_disable();
     
    307388                spinlock_unlock(&tasks_lock);
    308389                interrupts_restore(ipl);
    309                 free(stats_task);
    310390                return ret;
    311391        }
    312392       
    313         /* Hand-over-hand locking */
    314         spinlock_lock(&task->lock);
    315         spinlock_unlock(&tasks_lock);
    316        
    317         /* Copy task's statistics */
    318         str_cpy(stats_task->name, TASK_NAME_BUFLEN, task->name);
    319         stats_task->virtmem = get_task_virtmem(task->as);
    320         stats_task->threads = atomic_get(&task->refcount);
    321         task_get_accounting(task, &(stats_task->ucycles),
    322             &(stats_task->kcycles));
    323         stats_task->ipc_info = task->ipc_info;
    324        
    325         spinlock_unlock(&task->lock);
     393        if (dry_run) {
     394                ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     395                ret.data.data = NULL;
     396                ret.data.size = sizeof(stats_task_t);
     397               
     398                spinlock_unlock(&tasks_lock);
     399        } else {
     400                /* Allocate stats_task_t structure */
     401                stats_task_t *stats_task =
     402                    (stats_task_t *) malloc(sizeof(stats_task_t), FRAME_ATOMIC);
     403                if (stats_task == NULL) {
     404                        spinlock_unlock(&tasks_lock);
     405                        interrupts_restore(ipl);
     406                        return ret;
     407                }
     408               
     409                /* Correct return value */
     410                ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     411                ret.data.data = (void *) stats_task;
     412                ret.data.size = sizeof(stats_task_t);
     413       
     414                /* Hand-over-hand locking */
     415                spinlock_lock(&task->lock);
     416                spinlock_unlock(&tasks_lock);
     417               
     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;
     425               
     426                spinlock_unlock(&task->lock);
     427        }
     428       
    326429        interrupts_restore(ipl);
    327430       
    328         /* Correct return value */
    329         ret.tag = SYSINFO_VAL_FUNCTION_DATA;
    330         ret.data.data = (void *) stats_task;
    331         ret.data.size = sizeof(stats_task_t);
     431        return ret;
     432}
     433
     434/** Get thread statistics
     435 *
     436 * Get statistics of a given thread. The thread ID is passed
     437 * as a string (current limitation of the sysinfo interface,
     438 * but it is still reasonable for the given purpose).
     439 *
     440 * @param name    Thread ID (string-encoded number).
     441 * @param dry_run Do not get the data, just calculate the size.
     442 *
     443 * @return Sysinfo return holder. The type of the returned
     444 *         data is either SYSINFO_VAL_UNDEFINED (unknown
     445 *         thread ID or memory allocation error) or
     446 *         SYSINFO_VAL_FUNCTION_DATA (in that case the
     447 *         generated data should be freed within the
     448 *         sysinfo request context).
     449 *
     450 */
     451static sysinfo_return_t get_stats_thread(const char *name, bool dry_run)
     452{
     453        /* Initially no return value */
     454        sysinfo_return_t ret;
     455        ret.tag = SYSINFO_VAL_UNDEFINED;
     456       
     457        /* Parse the thread ID */
     458        thread_id_t thread_id;
     459        if (str_uint64(name, NULL, 0, true, &thread_id) != EOK)
     460                return ret;
     461       
     462        /* Messing with threads structures, avoid deadlock */
     463        ipl_t ipl = interrupts_disable();
     464        spinlock_lock(&threads_lock);
     465       
     466        thread_t *thread = thread_find_by_id(thread_id);
     467        if (thread == NULL) {
     468                /* No thread with this ID */
     469                spinlock_unlock(&threads_lock);
     470                interrupts_restore(ipl);
     471                return ret;
     472        }
     473       
     474        if (dry_run) {
     475                ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     476                ret.data.data = NULL;
     477                ret.data.size = sizeof(stats_thread_t);
     478               
     479                spinlock_unlock(&threads_lock);
     480        } else {
     481                /* Allocate stats_thread_t structure */
     482                stats_thread_t *stats_thread =
     483                    (stats_thread_t *) malloc(sizeof(stats_thread_t), FRAME_ATOMIC);
     484                if (stats_thread == NULL) {
     485                        spinlock_unlock(&threads_lock);
     486                        interrupts_restore(ipl);
     487                        return ret;
     488                }
     489               
     490                /* Correct return value */
     491                ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     492                ret.data.data = (void *) stats_thread;
     493                ret.data.size = sizeof(stats_thread_t);
     494       
     495                /* Hand-over-hand locking */
     496                spinlock_lock(&thread->lock);
     497                spinlock_unlock(&threads_lock);
     498               
     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;
     511               
     512                spinlock_unlock(&thread->lock);
     513        }
     514       
     515        interrupts_restore(ipl);
    332516       
    333517        return ret;
     
    477661        sysinfo_set_item_fn_data("system.load", NULL, get_stats_load);
    478662        sysinfo_set_item_fn_data("system.tasks", NULL, get_stats_tasks);
     663        sysinfo_set_item_fn_data("system.threads", NULL, get_stats_threads);
    479664        sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task);
     665        sysinfo_set_subtree_fn("system.threads", NULL, get_stats_thread);
    480666}
    481667
  • kernel/generic/src/sysinfo/sysinfo.c

    rbbda5ab re1b6742  
    112112 *                original pointer is used to store the value
    113113 *                generated by a generated subtree function.
     114 * @param dry_run Do not actually get any generated
     115 *                binary data, just calculate the size.
    114116 *
    115117 * @return Found item or NULL if no item in the fixed tree
     
    118120 */
    119121static sysinfo_item_t *sysinfo_find_item(const char *name,
    120     sysinfo_item_t *subtree, sysinfo_return_t **ret)
     122    sysinfo_item_t *subtree, sysinfo_return_t **ret, bool dry_run)
    121123{
    122124        ASSERT(subtree != NULL);
     
    144146                                /* Recursively find in subtree */
    145147                                return sysinfo_find_item(name + i + 1,
    146                                     cur->subtree.table, ret);
     148                                    cur->subtree.table, ret, dry_run);
    147149                        case SYSINFO_SUBTREE_FUNCTION:
    148150                                /* Get generated data */
    149                                 **ret = cur->subtree.get_data(name + i + 1);
     151                                **ret = cur->subtree.get_data(name + i + 1, dry_run);
    150152                                return NULL;
    151153                        default:
     
    593595        sysinfo_return_t ret;
    594596        sysinfo_return_t *ret_ptr = &ret;
    595         sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr);
     597        sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
     598            dry_run);
    596599       
    597600        if (item != NULL) {
  • uspace/app/tasks/tasks.c

    rbbda5ab re1b6742  
    11/*
    22 * Copyright (c) 2010 Stanislav Kozina
     3 * Copyright (c) 2010 Martin Decky
    34 * All rights reserved.
    45 *
     
    4344#include <malloc.h>
    4445#include <inttypes.h>
     46#include <bool.h>
    4547#include <arg_parse.h>
    4648#include "func.h"
     
    5355#define PRINT_LOAD1(x)  ((x) >> 11)
    5456#define PRINT_LOAD2(x)  (((x) & 0x7ff) / 2)
    55 
    56 /** Thread states */
    57 //static const char *thread_states[] = {
    58 //      "Invalid",
    59 //      "Running",
    60 //      "Sleeping",
    61 //      "Ready",
    62 //      "Entering",
    63 //      "Exiting",
    64 //      "Lingering"
    65 //};
    6657
    6758static void list_tasks(void)
     
    9081                       
    9182                        printf("%8" PRIu64 "%8u %8" PRIu64"%c %12"
    92                             PRIu64"%c %12" PRIu64"%c %s\n", ids[i], stats_task->threads,
     83                            PRIu64 "%c %12" PRIu64 "%c %s\n", ids[i], stats_task->threads,
    9384                            virtmem, vmsuffix, ucycles, usuffix, kcycles, ksuffix,
    9485                            stats_task->name);
     
    10293}
    10394
    104 static void list_threads(task_id_t task_id)
    105 {
    106         /* TODO:
    107         size_t thread_count = THREAD_COUNT;
    108         thread_info_t *threads = malloc(thread_count * sizeof(thread_info_t));
    109         size_t result = get_task_threads(threads, sizeof(thread_info_t) * thread_count);
    110 
    111         while (result > thread_count) {
    112                 thread_count *= 2;
    113                 threads = realloc(threads, thread_count * sizeof(thread_info_t));
    114                 result = get_task_threads(threads, sizeof(thread_info_t) * thread_count);
    115         }
    116 
    117         if (result == 0) {
    118                 printf("No task with given pid!\n");
    119                 exit(1);
    120         }
    121 
    122         size_t i;
     95static void list_threads(task_id_t task_id, bool all)
     96{
     97        size_t count;
     98        thread_id_t *ids =
     99            (thread_id_t *) stats_get_threads(&count);
     100       
     101        if (ids == NULL) {
     102                fprintf(stderr, "%s: Unable to get threads\n", NAME);
     103                return;
     104        }
     105       
    123106        printf("    ID    State  CPU   Prio    [k]uCycles    [k]kcycles   Cycle fault\n");
    124         for (i = 0; i < result; ++i) {
    125                 if (threads[i].taskid != taskid) {
    126                         continue;
    127                 }
    128                 uint64_t ucycles, kcycles;
    129                 char usuffix, ksuffix;
    130                 order(threads[i].ucycles, &ucycles, &usuffix);
    131                 order(threads[i].kcycles, &kcycles, &ksuffix);
    132                 printf("%6llu %-8s %4u %6d %12llu%c %12llu%c\n", threads[i].tid,
    133                         thread_states[threads[i].state], threads[i].cpu,
    134                         threads[i].priority, ucycles, usuffix,
    135                         kcycles, ksuffix);
    136         }
    137 
    138         free(threads); */
     107        size_t i;
     108        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(stats_thread->ucycles, &ucycles, &usuffix);
     116                                order(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                                }
     131                        }
     132                       
     133                        free(stats_thread);
     134                } else if (all)
     135                        printf("%8" PRIu64 "\n", ids[i]);
     136        }
     137       
     138        free(ids);
    139139}
    140140
     
    190190{
    191191        printf(
    192             "Usage: tasks [-t task_id] [-l] [-c]\n" \
     192            "Usage: tasks [-t task_id] [-a] [-l] [-c]\n" \
    193193            "\n" \
    194194            "Options:\n" \
     
    197197            "\t\tList threads of the given task\n" \
    198198            "\n" \
     199            "\t-a\n" \
     200            "\t--all\n" \
     201            "\t\tList all threads\n" \
     202            "\n" \
    199203            "\t-l\n" \
    200204            "\t--load\n" \
     
    217221        bool toggle_tasks = true;
    218222        bool toggle_threads = false;
     223        bool toggle_all = false;
    219224        bool toggle_load = false;
    220225        bool toggle_cpus = false;
    221226       
    222         task_id_t task_id;
     227        task_id_t task_id = 0;
    223228       
    224229        int i;
     
    230235                        usage();
    231236                        return 0;
     237                }
     238               
     239                /* All threads */
     240                if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
     241                        toggle_tasks = false;
     242                        toggle_threads = true;
     243                        toggle_all = true;
     244                        continue;
    232245                }
    233246               
     
    268281       
    269282        if (toggle_threads)
    270                 list_threads(task_id);
     283                list_threads(task_id, toggle_all);
    271284       
    272285        if (toggle_load)
  • uspace/lib/c/generic/stats.c

    rbbda5ab re1b6742  
    4343#define SYSINFO_STATS_MAX_PATH  64
    4444
     45/** Thread states
     46 *
     47 */
     48static const char *thread_states[] = {
     49        "Invalid",
     50        "Running",
     51        "Sleeping",
     52        "Ready",
     53        "Entering",
     54        "Exiting",
     55        "Lingering"
     56};
     57
    4558/** Get CPUs statistics
    4659 *
     
    125138       
    126139        return stats_task;
     140}
     141
     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 */
     151thread_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;
     161}
     162
     163/** Get single thread statistics
     164 *
     165 * @param thread_id Thread ID we are interested in.
     166 *
     167 * @return Pointer to the stats_thread_t structure.
     168 *         If non-NULL then it should be eventually freed
     169 *         by free().
     170 *
     171 */
     172stats_thread_t *stats_get_thread(thread_id_t thread_id)
     173{
     174        char name[SYSINFO_STATS_MAX_PATH];
     175        snprintf(name, SYSINFO_STATS_MAX_PATH, "system.threads.%" PRIu64, thread_id);
     176       
     177        size_t size = 0;
     178        stats_thread_t *stats_thread =
     179            (stats_thread_t *) sysinfo_get_data(name, &size);
     180       
     181        assert((size == sizeof(stats_thread_t)) || (size == 0));
     182       
     183        return stats_thread;
    127184}
    128185
     
    188245}
    189246
     247const char *thread_get_state(state_t state)
     248{
     249        if (state <= Lingering)
     250                return thread_states[state];
     251       
     252        return thread_states[Invalid];
     253}
     254
    190255/** @}
    191256 */
  • uspace/lib/c/include/stats.h

    rbbda5ab re1b6742  
    3737
    3838#include <task.h>
     39#include <thread.h>
     40#include <stdint.h>
     41#include <bool.h>
    3942#include <kernel/sysinfo/abi.h>
    4043
    4144extern stats_cpu_t *stats_get_cpus(size_t *);
    4245extern stats_physmem_t *stats_get_physmem(void);
    43 extern task_id_t *stats_get_tasks(size_t *);
    44 extern stats_task_t *stats_get_task(task_id_t);
    4546extern load_t *stats_get_load(size_t *);
    4647extern sysarg_t stats_get_uptime(void);
    4748
     49extern task_id_t *stats_get_tasks(size_t *);
     50extern stats_task_t *stats_get_task(task_id_t);
     51
     52extern thread_id_t *stats_get_threads(size_t *);
     53extern stats_thread_t *stats_get_thread(thread_id_t);
     54
    4855extern void stats_print_load_fragment(load_t, unsigned int);
     56extern const char *thread_get_state(state_t);
    4957
    5058#endif
Note: See TracChangeset for help on using the changeset viewer.