Changeset f4f866c in mainline for kernel/generic


Ignore:
Timestamp:
2010-04-23T21:42:26Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6c39a907
Parents:
38aaacc2 (diff), 80badbe (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Location:
kernel/generic
Files:
2 added
32 edited
1 moved

Legend:

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

    r38aaacc2 rf4f866c  
    6868                                             are disabled. */
    6969
     70        bool idle;
     71        uint64_t idle_ticks;
     72        uint64_t busy_ticks;
     73
    7074        /**
    7175         * Processor ID assigned by kernel.
     
    7377        unsigned int id;
    7478       
    75         int active;
     79        bool active;
    7680        int tlb_active;
    7781
  • kernel/generic/include/func.h

    r38aaacc2 rf4f866c  
    4343extern void halt(void) __attribute__((noreturn));
    4444extern unative_t atoi(const char *text);
    45 extern void order(const uint64_t val, uint64_t *rv, char *suffix);
    4645
    4746#endif
  • kernel/generic/include/ipc/sysipc.h

    r38aaacc2 rf4f866c  
    5757unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
    5858    ipc_data_t *data, int mode);
    59 unative_t sys_ipc_hangup(int phoneid);
     59unative_t sys_ipc_hangup(unative_t phoneid);
    6060unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
    6161    irq_code_t *ucode);
  • kernel/generic/include/mm/frame.h

    r38aaacc2 rf4f866c  
    169169extern bool zone_merge(size_t, size_t);
    170170extern void zone_merge_all(void);
    171 extern uint64_t zone_total_size(void);
     171extern uint64_t zones_total_size(void);
     172extern void zones_stats(uint64_t *, uint64_t *, uint64_t *, uint64_t *);
    172173
    173174/*
    174175 * Console functions
    175176 */
    176 extern void zone_print_list(void);
     177extern void zones_print_list(void);
    177178extern void zone_print_one(size_t);
    178179
  • kernel/generic/include/print.h

    r38aaacc2 rf4f866c  
    3939#include <stdarg.h>
    4040
    41 #define EOF (-1)
     41#define EOF  (-1)
    4242
    4343extern int puts(const char *s);
  • kernel/generic/include/printf/printf_core.h

    r38aaacc2 rf4f866c  
    5151} printf_spec_t;
    5252
    53 int printf_core(const char *fmt, printf_spec_t *ps, va_list ap);
     53extern int printf_core(const char *fmt, printf_spec_t *ps, va_list ap);
    5454
    5555#endif
  • kernel/generic/include/proc/task.h

    r38aaacc2 rf4f866c  
    5656#include <ipc/kbox.h>
    5757#include <mm/as.h>
    58 
    59 #define TASK_NAME_BUFLEN        20
     58#include <sysinfo/abi.h>
    6059
    6160struct thread;
     
    8180        task_id_t taskid;
    8281        /** Task security context. */
    83         context_id_t context;   
     82        context_id_t context;
    8483
    8584        /** Number of references (i.e. threads). */
     
    8988
    9089        /** Task capabilities. */
    91         cap_t capabilities;     
     90        cap_t capabilities;
    9291
    9392        /* IPC stuff */
    9493        answerbox_t answerbox;  /**< Communication endpoint */
    9594        phone_t phones[IPC_MAX_PHONES];
     95        stats_ipc_t ipc_info;   /**< IPC statistics */
    9696        /**
    9797         * Active asynchronous messages. It is used for limiting uspace to
     
    119119        mutex_t futexes_lock;
    120120        /** B+tree of futexes referenced by this task. */
    121         btree_t futexes;       
     121        btree_t futexes;
    122122       
    123123        /** Accumulated accounting. */
    124         uint64_t cycles;
     124        uint64_t ucycles;
     125        uint64_t kcycles;
    125126} task_t;
    126127
     
    134135extern task_t *task_find_by_id(task_id_t id);
    135136extern int task_kill(task_id_t id);
    136 extern uint64_t task_get_accounting(task_t *t);
     137extern void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles);
    137138extern void task_print_list(void);
    138139
  • kernel/generic/include/proc/thread.h

    r38aaacc2 rf4f866c  
    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 {
     
    189172       
    190173        /** Thread accounting. */
    191         uint64_t cycles;
     174        uint64_t ucycles;
     175        uint64_t kcycles;
    192176        /** Last sampled cycle. */
    193177        uint64_t last_cycle;
     
    252236extern void thread_print_list(void);
    253237extern void thread_destroy(thread_t *);
    254 extern void thread_update_accounting(void);
     238extern thread_t *thread_find_by_id(thread_id_t);
     239extern void thread_update_accounting(bool);
    255240extern bool thread_exists(thread_t *);
    256241
  • kernel/generic/include/str.h

    r38aaacc2 rf4f866c  
    8989extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
    9090
     91extern char *str_dup(const char *src);
     92extern char *str_ndup(const char *src, size_t n);
     93
    9194extern char *str_chr(const char *str, wchar_t ch);
    9295
     
    9497extern bool wstr_remove(wchar_t *str, size_t pos);
    9598
     99extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *);
     100
     101extern void order_suffix(const uint64_t val, uint64_t *rv, char *suffix);
     102
    96103#endif
    97104
  • kernel/generic/include/syscall/syscall.h

    r38aaacc2 rf4f866c  
    7171        SYS_IPC_REGISTER_IRQ,
    7272        SYS_IPC_UNREGISTER_IRQ,
    73 
     73       
    7474        SYS_EVENT_SUBSCRIBE,
    7575       
     
    8282        SYS_PREEMPT_CONTROL,
    8383       
    84         SYS_SYSINFO_VALID,
    85         SYS_SYSINFO_VALUE,
     84        SYS_SYSINFO_GET_TAG,
     85        SYS_SYSINFO_GET_VALUE,
     86        SYS_SYSINFO_GET_DATA_SIZE,
     87        SYS_SYSINFO_GET_DATA,
    8688       
    8789        SYS_DEBUG_ENABLE_CONSOLE,
    8890        SYS_DEBUG_DISABLE_CONSOLE,
     91       
    8992        SYS_IPC_CONNECT_KBOX,
    9093        SYSCALL_END
  • kernel/generic/include/sysinfo/stats.h

    r38aaacc2 rf4f866c  
    11/*
    2  * Copyright (c) 2005 Jakub Vana
     2 * Copyright (c) 2010 Martin Decky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 #include <print.h>
    30 #include <debug.h>
     29/** @addtogroup generic
     30 * @{
     31 */
     32/** @file
     33 */
    3134
    32 #include <test.h>
    33 #include <sysinfo/sysinfo.h>
     35#ifndef KERN_STATS_H_
     36#define KERN_STATS_H_
    3437
    35 const char *test_sysinfo1(void)
    36 {
    37         if (!test_quiet)
    38                 sysinfo_dump(NULL, 0);
    39         return NULL;
    40 }
     38extern void kload(void *arg);
     39extern void stats_init(void);
     40
     41#endif
     42
     43/** @}
     44 */
  • kernel/generic/include/sysinfo/sysinfo.h

    r38aaacc2 rf4f866c  
    3939#include <str.h>
    4040
     41/** Framebuffer info exported flags */
    4142extern bool fb_exported;
    4243
    43 typedef union sysinfo_item_val {
    44         unative_t val;
    45         void *fn;
     44/** Item value type
     45 *
     46 */
     47typedef enum {
     48        SYSINFO_VAL_UNDEFINED = 0,     /**< Undefined value */
     49        SYSINFO_VAL_VAL = 1,           /**< Constant numeric value */
     50        SYSINFO_VAL_DATA = 2,          /**< Constant binary data */
     51        SYSINFO_VAL_FUNCTION_VAL = 3,  /**< Generated numeric value */
     52        SYSINFO_VAL_FUNCTION_DATA = 4  /**< Generated binary data */
     53} sysinfo_item_val_type_t;
     54
     55/** Subtree type
     56 *
     57 */
     58typedef enum {
     59        SYSINFO_SUBTREE_NONE = 0,     /**< No subtree (leaf item) */
     60        SYSINFO_SUBTREE_TABLE = 1,    /**< Fixed subtree */
     61        SYSINFO_SUBTREE_FUNCTION = 2  /**< Generated subtree */
     62} sysinfo_subtree_type_t;
     63
     64struct sysinfo_item;
     65
     66/** Gerated numeric value function */
     67typedef unative_t (*sysinfo_fn_val_t)(struct sysinfo_item *);
     68
     69/** Generated binary data function */
     70typedef void *(*sysinfo_fn_data_t)(struct sysinfo_item *, size_t *, bool);
     71
     72/** Sysinfo item binary data
     73 *
     74 */
     75typedef struct {
     76        void *data;   /**< Data */
     77        size_t size;  /**< Size (bytes) */
     78} sysinfo_data_t;
     79
     80/** Sysinfo item value (union)
     81 *
     82 */
     83typedef union {
     84        unative_t val;              /**< Constant numberic value */
     85        sysinfo_fn_val_t fn_val;    /**< Generated numeric value function */
     86        sysinfo_fn_data_t fn_data;  /**< Generated binary data function */
     87        sysinfo_data_t data;        /**< Constant binary data */
    4688} sysinfo_item_val_t;
    4789
     90/** Sysinfo return holder
     91 *
     92 * This structure is generated from the constant
     93 * items or by the generating functions. Note that
     94 * the validity of the data is limited by the scope
     95 * of single sysinfo invocation guarded by sysinfo_lock.
     96 *
     97 */
     98typedef struct {
     99        sysinfo_item_val_type_t tag;  /**< Return value type */
     100        union {
     101                unative_t val;            /**< Numberic value */
     102                sysinfo_data_t data;      /**< Binary data */
     103        };
     104} sysinfo_return_t;
     105
     106/** Generated subtree function */
     107typedef sysinfo_return_t (*sysinfo_fn_subtree_t)(const char *, bool);
     108
     109/** Sysinfo subtree (union)
     110 *
     111 */
     112typedef union {
     113        struct sysinfo_item *table;     /**< Fixed subtree (list of subitems) */
     114        sysinfo_fn_subtree_t get_data;  /**< Generated subtree function */
     115} sysinfo_subtree_t;
     116
     117/** Sysinfo item
     118 *
     119 */
    48120typedef struct sysinfo_item {
    49         char *name;
    50         union {
    51                 unative_t val;
    52                 void *fn;
    53         } val;
    54 
    55         union {
    56                 struct sysinfo_item *table;
    57                 void *fn;
    58         } subinfo;
    59 
    60         struct sysinfo_item *next;
    61         int val_type;
    62         int subinfo_type;
     121        char *name;                           /**< Item name */
     122       
     123        sysinfo_item_val_type_t val_type;     /**< Item value type */
     124        sysinfo_item_val_t val;               /**< Item value */
     125       
     126        sysinfo_subtree_type_t subtree_type;  /**< Subtree type */
     127        sysinfo_subtree_t subtree;            /**< Subtree */
     128       
     129        struct sysinfo_item *next;            /**< Sibling item */
    63130} sysinfo_item_t;
    64131
    65 #define SYSINFO_VAL_VAL        0
    66 #define SYSINFO_VAL_FUNCTION   1
    67 #define SYSINFO_VAL_UNDEFINED  U_SPECIAL
     132extern void sysinfo_set_item_val(const char *, sysinfo_item_t **, unative_t);
     133extern void sysinfo_set_item_data(const char *, sysinfo_item_t **, void *,
     134    size_t);
     135extern void sysinfo_set_item_fn_val(const char *, sysinfo_item_t **,
     136    sysinfo_fn_val_t);
     137extern void sysinfo_set_item_fn_data(const char *, sysinfo_item_t **,
     138    sysinfo_fn_data_t);
     139extern void sysinfo_set_item_undefined(const char *, sysinfo_item_t **);
    68140
    69 #define SYSINFO_SUBINFO_NONE      0
    70 #define SYSINFO_SUBINFO_TABLE     1
    71 #define SYSINFO_SUBINFO_FUNCTION  2
     141extern void sysinfo_set_subtree_fn(const char *, sysinfo_item_t **,
     142    sysinfo_fn_subtree_t);
    72143
    73 typedef unative_t (*sysinfo_val_fn_t)(sysinfo_item_t *root);
    74 typedef unative_t (*sysinfo_subinfo_fn_t)(const char *subname);
     144extern void sysinfo_init(void);
     145extern void sysinfo_dump(sysinfo_item_t *);
    75146
    76 typedef struct sysinfo_rettype {
    77         unative_t val;
    78         unative_t valid;
    79 } sysinfo_rettype_t;
    80 
    81 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val);
    82 void sysinfo_dump(sysinfo_item_t **root, int depth);
    83 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn);
    84 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root);
    85 
    86 sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root);
    87 
    88 unative_t sys_sysinfo_valid(unative_t ptr, unative_t len);
    89 unative_t sys_sysinfo_value(unative_t ptr, unative_t len);
     147extern unative_t sys_sysinfo_get_tag(void *, size_t);
     148extern unative_t sys_sysinfo_get_value(void *, size_t, void *);
     149extern unative_t sys_sysinfo_get_data_size(void *, size_t, void *);
     150extern unative_t sys_sysinfo_get_data(void *, size_t, void *, size_t);
    90151
    91152#endif
  • kernel/generic/include/time/clock.h

    r38aaacc2 rf4f866c  
    3838#include <typedefs.h>
    3939
    40 #define HZ              100
     40#define HZ  100
    4141
    4242/** Uptime structure */
  • kernel/generic/src/console/cmd.c

    r38aaacc2 rf4f866c  
    6666#include <ipc/irq.h>
    6767#include <ipc/event.h>
     68#include <sysinfo/sysinfo.h>
    6869#include <symtab.h>
    6970#include <errno.h>
     
    387388};
    388389
     390static int cmd_sysinfo(cmd_arg_t *argv);
     391static cmd_info_t sysinfo_info = {
     392        .name = "sysinfo",
     393        .description = "Dump sysinfo.",
     394        .func = cmd_sysinfo,
     395        .argc = 0
     396};
     397
    389398/* Data and methods for 'zones' command */
    390399static int cmd_zones(cmd_arg_t *argv);
     
    475484        &set4_info,
    476485        &slabs_info,
     486        &sysinfo_info,
    477487        &symaddr_info,
    478488        &sched_info,
     
    868878}
    869879
     880/** Command for dumping sysinfo
     881 *
     882 * @param argv Ignores
     883 *
     884 * @return Always 1
     885 */
     886int cmd_sysinfo(cmd_arg_t * argv)
     887{
     888        sysinfo_dump(NULL);
     889        return 1;
     890}
     891
    870892
    871893/** Command for listings Thread information
     
    913935int cmd_zones(cmd_arg_t * argv)
    914936{
    915         zone_print_list();
     937        zones_print_list();
    916938        return 1;
    917939}
     
    10271049        ipl_t ipl = interrupts_disable();
    10281050        spinlock_lock(&TASK->lock);
    1029         uint64_t t0 = task_get_accounting(TASK);
     1051        uint64_t ucycles0, kcycles0;
     1052        task_get_accounting(TASK, &ucycles0, &kcycles0);
    10301053        spinlock_unlock(&TASK->lock);
    10311054        interrupts_restore(ipl);
     
    10361059       
    10371060        /* Update and read thread accounting */
     1061        uint64_t ucycles1, kcycles1;
    10381062        ipl = interrupts_disable();
    10391063        spinlock_lock(&TASK->lock);
    1040         uint64_t dt = task_get_accounting(TASK) - t0;
     1064        task_get_accounting(TASK, &ucycles1, &kcycles1);
    10411065        spinlock_unlock(&TASK->lock);
    10421066        interrupts_restore(ipl);
    10431067       
    1044         uint64_t cycles;
    1045         char suffix;
    1046         order(dt, &cycles, &suffix);
    1047                
    1048         printf("Time: %" PRIu64 "%c cycles\n", cycles, suffix);
     1068        uint64_t ucycles, kcycles;
     1069        char usuffix, ksuffix;
     1070        order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
     1071        order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
     1072               
     1073        printf("Time: %" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles\n",
     1074                        ucycles, usuffix, kcycles, ksuffix);
    10491075       
    10501076        if (ret == NULL) {
     
    10611087        uint32_t i;
    10621088        bool ret = true;
    1063         uint64_t cycles;
    1064         char suffix;
     1089        uint64_t ucycles, kcycles;
     1090        char usuffix, ksuffix;
    10651091       
    10661092        if (cnt < 1)
     
    10801106                ipl_t ipl = interrupts_disable();
    10811107                spinlock_lock(&TASK->lock);
    1082                 uint64_t t0 = task_get_accounting(TASK);
     1108                uint64_t ucycles0, kcycles0;
     1109                task_get_accounting(TASK, &ucycles0, &kcycles0);
    10831110                spinlock_unlock(&TASK->lock);
    10841111                interrupts_restore(ipl);
     
    10911118                ipl = interrupts_disable();
    10921119                spinlock_lock(&TASK->lock);
    1093                 uint64_t dt = task_get_accounting(TASK) - t0;
     1120                uint64_t ucycles1, kcycles1;
     1121                task_get_accounting(TASK, &ucycles1, &kcycles1);
    10941122                spinlock_unlock(&TASK->lock);
    10951123                interrupts_restore(ipl);
    1096                
     1124
    10971125                if (ret != NULL) {
    10981126                        printf("%s\n", ret);
     
    11011129                }
    11021130               
    1103                 data[i] = dt;
    1104                 order(dt, &cycles, &suffix);
    1105                 printf("OK (%" PRIu64 "%c cycles)\n", cycles, suffix);
     1131                data[i] = ucycles1 - ucycles0 + kcycles1 - kcycles0;
     1132                order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix);
     1133                order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix);
     1134                printf("OK (%" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles)\n",
     1135                                ucycles, usuffix, kcycles, ksuffix);
    11061136        }
    11071137       
     
    11151145                }
    11161146               
    1117                 order(sum / (uint64_t) cnt, &cycles, &suffix);
    1118                 printf("Average\t\t%" PRIu64 "%c\n", cycles, suffix);
     1147                order_suffix(sum / (uint64_t) cnt, &ucycles, &usuffix);
     1148                printf("Average\t\t%" PRIu64 "%c\n", ucycles, usuffix);
    11191149        }
    11201150       
  • kernel/generic/src/cpu/cpu.c

    r38aaacc2 rf4f866c  
    4848#include <adt/list.h>
    4949#include <print.h>
     50#include <sysinfo/sysinfo.h>
    5051
    5152cpu_t *cpus;
  • kernel/generic/src/interrupt/interrupt.c

    r38aaacc2 rf4f866c  
    5151#include <print.h>
    5252#include <symtab.h>
     53#include <proc/thread.h>
    5354
    5455static struct {
     
    9192        ASSERT(n < IVT_ITEMS);
    9293
     94        /* Account user cycles */
     95        if (THREAD)
     96                thread_update_accounting(true);
     97
    9398#ifdef CONFIG_UDEBUG
    9499        if (THREAD) THREAD->udebug.uspace_state = istate;
     
    104109        if (THREAD && THREAD->interrupted && istate_from_uspace(istate))
    105110                thread_exit();
     111
     112        if (THREAD)
     113                thread_update_accounting(false);
    106114}
    107115
  • kernel/generic/src/ipc/ipc.c

    r38aaacc2 rf4f866c  
    219219        bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));
    220220
     221        /* Count sent answer */
     222        spinlock_lock(&TASK->lock);
     223        TASK->ipc_info.answer_sent++;
     224        spinlock_unlock(&TASK->lock);
     225
    221226        call->flags |= IPC_CALL_ANSWERED;
    222227
     
    276281static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
    277282{
     283        /* Count sent ipc call */
     284        spinlock_lock(&TASK->lock);
     285        TASK->ipc_info.call_sent++;
     286        spinlock_unlock(&TASK->lock);
     287
    278288        if (!(call->flags & IPC_CALL_FORWARDED)) {
    279289                atomic_inc(&phone->active_calls);
     
    376386int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode)
    377387{
     388        /* Count forwarded calls */
     389        spinlock_lock(&TASK->lock);
     390        TASK->ipc_info.forwarded++;
     391        spinlock_unlock(&TASK->lock);
     392
    378393        spinlock_lock(&oldbox->lock);
    379394        list_remove(&call->link);
     
    416431        spinlock_lock(&box->lock);
    417432        if (!list_empty(&box->irq_notifs)) {
     433
     434                /* Count recieved IRQ notification */
     435                spinlock_lock(&TASK->lock);
     436                TASK->ipc_info.irq_notif_recieved++;
     437                spinlock_unlock(&TASK->lock);
     438
    418439                ipl = interrupts_disable();
    419440                spinlock_lock(&box->irq_lock);
     
    425446                interrupts_restore(ipl);
    426447        } else if (!list_empty(&box->answers)) {
     448                /* Count recieved answer */
     449                spinlock_lock(&TASK->lock);
     450                TASK->ipc_info.answer_recieved++;
     451                spinlock_unlock(&TASK->lock);
     452
    427453                /* Handle asynchronous answers */
    428454                request = list_get_instance(box->answers.next, call_t, link);
     
    430456                atomic_dec(&request->data.phone->active_calls);
    431457        } else if (!list_empty(&box->calls)) {
     458                /* Count recieved call */
     459                spinlock_lock(&TASK->lock);
     460                TASK->ipc_info.call_recieved++;
     461                spinlock_unlock(&TASK->lock);
     462
    432463                /* Handle requests */
    433464                request = list_get_instance(box->calls.next, call_t, link);
  • kernel/generic/src/ipc/sysipc.c

    r38aaacc2 rf4f866c  
    5858#define DATA_XFER_LIMIT         (64 * 1024)
    5959
    60 #define GET_CHECK_PHONE(phone, phoneid, err) \
    61 { \
    62         if (phoneid > IPC_MAX_PHONES) { \
    63                 err \
    64         } \
    65         phone = &TASK->phones[phoneid]; \
     60/** Get phone from the current task by ID.
     61 *
     62 * @param phoneid       Phone ID.
     63 * @param phone         Place to store pointer to phone.
     64 * @return              EOK on success, EINVAL if ID is invalid.
     65 */
     66static int phone_get(unative_t phoneid, phone_t **phone)
     67{
     68        if (phoneid >= IPC_MAX_PHONES)
     69                return EINVAL;
     70
     71        *phone = &TASK->phones[phoneid];
     72        return EOK;
    6673}
    6774
     
    374381        case IPC_M_CONNECTION_CLONE: {
    375382                phone_t *cloned_phone;
    376                 GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
    377                     return ENOENT;);
     383
     384                if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
     385                        return ENOENT;
    378386                phones_lock(cloned_phone, phone);
     387
    379388                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
    380389                    phone->state != IPC_PHONE_CONNECTED) {
     
    534543        int res;
    535544        int rc;
    536        
    537         GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     545
     546        if (phone_get(phoneid, &phone) != EOK)
     547                return ENOENT;
    538548
    539549        call = ipc_call_alloc(0);
     
    591601        int rc;
    592602
    593         GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     603        if (phone_get(phoneid, &phone) != EOK)
     604                return ENOENT;
    594605
    595606        call = ipc_call_alloc(0);
     
    666677                return IPC_CALLRET_TEMPORARY;
    667678
    668         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
     679        if (phone_get(phoneid, &phone) != EOK)
     680                return IPC_CALLRET_FATAL;
    669681
    670682        call = ipc_call_alloc(0);
     
    705717                return IPC_CALLRET_TEMPORARY;
    706718
    707         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
     719        if (phone_get(phoneid, &phone) != EOK)
     720                return IPC_CALLRET_FATAL;
    708721
    709722        call = ipc_call_alloc(0);
     
    755768        call->flags |= IPC_CALL_FORWARDED;
    756769
    757         GET_CHECK_PHONE(phone, phoneid, {
     770        if (phone_get(phoneid, &phone) != EOK) {
    758771                IPC_SET_RETVAL(call->data, EFORWARD);
    759772                ipc_answer(&TASK->answerbox, call);
    760773                return ENOENT;
    761         });
     774        }
    762775
    763776        if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
     
    956969 * @return              Return 0 on success or an error code.
    957970 */
    958 unative_t sys_ipc_hangup(int phoneid)
     971unative_t sys_ipc_hangup(unative_t phoneid)
    959972{
    960973        phone_t *phone;
    961974
    962         GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     975        if (phone_get(phoneid, &phone) != EOK)
     976                return ENOENT;
    963977
    964978        if (ipc_phone_hangup(phone))
  • kernel/generic/src/lib/func.c

    r38aaacc2 rf4f866c  
    123123}
    124124
    125 
    126 void order(const uint64_t val, uint64_t *rv, char *suffix)
    127 {
    128         if (val > 10000000000000000000ULL) {
    129                 *rv = val / 1000000000000000000ULL;
    130                 *suffix = 'Z';
    131         } else if (val > 1000000000000000000ULL) {
    132                 *rv = val / 1000000000000000ULL;
    133                 *suffix = 'E';
    134         } else if (val > 1000000000000000ULL) {
    135                 *rv = val / 1000000000000ULL;
    136                 *suffix = 'T';
    137         } else if (val > 1000000000000ULL) {
    138                 *rv = val / 1000000000ULL;
    139                 *suffix = 'G';
    140         } else if (val > 1000000000ULL) {
    141                 *rv = val / 1000000ULL;
    142                 *suffix = 'M';
    143         } else if (val > 1000000ULL) {
    144                 *rv = val / 1000ULL;
    145                 *suffix = 'k';
    146         } else {
    147                 *rv = val;
    148                 *suffix = ' ';
    149         }
    150 }
    151 
    152125/** @}
    153126 */
  • kernel/generic/src/lib/str.c

    r38aaacc2 rf4f866c  
    110110#include <align.h>
    111111#include <debug.h>
     112#include <macros.h>
    112113
    113114/** Byte mask consisting of lowest @n bits (out of 8) */
     
    537538 * null-terminated and containing only complete characters.
    538539 *
    539  * @param dest   Destination buffer.
     540 * @param dest  Destination buffer.
    540541 * @param count Size of the destination buffer (must be > 0).
    541542 * @param src   Source string.
     543 *
    542544 */
    543545void str_cpy(char *dest, size_t size, const char *src)
    544546{
    545         wchar_t ch;
    546         size_t src_off;
    547         size_t dest_off;
    548 
    549547        /* There must be space for a null terminator in the buffer. */
    550548        ASSERT(size > 0);
    551549       
    552         src_off = 0;
    553         dest_off = 0;
    554 
     550        size_t src_off = 0;
     551        size_t dest_off = 0;
     552       
     553        wchar_t ch;
    555554        while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
    556555                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    557556                        break;
    558557        }
    559 
     558       
    560559        dest[dest_off] = '\0';
    561560}
     
    571570 * have to be null-terminated.
    572571 *
    573  * @param dest   Destination buffer.
     572 * @param dest  Destination buffer.
    574573 * @param count Size of the destination buffer (must be > 0).
    575574 * @param src   Source string.
    576  * @param n     Maximum number of bytes to read from @a src.
     575 * @param n     Maximum number of bytes to read from @a src.
     576 *
    577577 */
    578578void str_ncpy(char *dest, size_t size, const char *src, size_t n)
    579579{
    580         wchar_t ch;
    581         size_t src_off;
    582         size_t dest_off;
    583 
    584580        /* There must be space for a null terminator in the buffer. */
    585581        ASSERT(size > 0);
    586582       
    587         src_off = 0;
    588         dest_off = 0;
    589 
     583        size_t src_off = 0;
     584        size_t dest_off = 0;
     585       
     586        wchar_t ch;
    590587        while ((ch = str_decode(src, &src_off, n)) != 0) {
    591588                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    592589                        break;
    593590        }
    594 
     591       
    595592        dest[dest_off] = '\0';
     593}
     594
     595/** Duplicate string.
     596 *
     597 * Allocate a new string and copy characters from the source
     598 * string into it. The duplicate string is allocated via sleeping
     599 * malloc(), thus this function can sleep in no memory conditions.
     600 *
     601 * The allocation cannot fail and the return value is always
     602 * a valid pointer. The duplicate string is always a well-formed
     603 * null-terminated UTF-8 string, but it can differ from the source
     604 * string on the byte level.
     605 *
     606 * @param src Source string.
     607 *
     608 * @return Duplicate string.
     609 *
     610 */
     611char *str_dup(const char *src)
     612{
     613        size_t size = str_size(src) + 1;
     614        char *dest = malloc(size, 0);
     615        ASSERT(dest);
     616       
     617        str_cpy(dest, size, src);
     618        return dest;
     619}
     620
     621/** Duplicate string with size limit.
     622 *
     623 * Allocate a new string and copy up to @max_size bytes from the source
     624 * string into it. The duplicate string is allocated via sleeping
     625 * malloc(), thus this function can sleep in no memory conditions.
     626 * No more than @max_size + 1 bytes is allocated, but if the size
     627 * occupied by the source string is smaller than @max_size + 1,
     628 * less is allocated.
     629 *
     630 * The allocation cannot fail and the return value is always
     631 * a valid pointer. The duplicate string is always a well-formed
     632 * null-terminated UTF-8 string, but it can differ from the source
     633 * string on the byte level.
     634 *
     635 * @param src Source string.
     636 * @param n   Maximum number of bytes to duplicate.
     637 *
     638 * @return Duplicate string.
     639 *
     640 */
     641char *str_ndup(const char *src, size_t n)
     642{
     643        size_t size = str_size(src);
     644        if (size > n)
     645                size = n;
     646       
     647        char *dest = malloc(size + 1, 0);
     648        ASSERT(dest);
     649       
     650        str_ncpy(dest, size + 1, src, size);
     651        return dest;
    596652}
    597653
     
    705761}
    706762
     763/** Convert string to uint64_t (internal variant).
     764 *
     765 * @param nptr   Pointer to string.
     766 * @param endptr Pointer to the first invalid character is stored here.
     767 * @param base   Zero or number between 2 and 36 inclusive.
     768 * @param neg    Indication of unary minus is stored here.
     769 * @apram result Result of the conversion.
     770 *
     771 * @return EOK if conversion was successful.
     772 *
     773 */
     774static int str_uint(const char *nptr, char **endptr, unsigned int base,
     775    bool *neg, uint64_t *result)
     776{
     777        ASSERT(endptr != NULL);
     778        ASSERT(neg != NULL);
     779        ASSERT(result != NULL);
     780       
     781        *neg = false;
     782        const char *str = nptr;
     783       
     784        /* Ignore leading whitespace */
     785        while (isspace(*str))
     786                str++;
     787       
     788        if (*str == '-') {
     789                *neg = true;
     790                str++;
     791        } else if (*str == '+')
     792                str++;
     793       
     794        if (base == 0) {
     795                /* Decode base if not specified */
     796                base = 10;
     797               
     798                if (*str == '0') {
     799                        base = 8;
     800                        str++;
     801                       
     802                        switch (*str) {
     803                        case 'b':
     804                        case 'B':
     805                                base = 2;
     806                                str++;
     807                                break;
     808                        case 'o':
     809                        case 'O':
     810                                base = 8;
     811                                str++;
     812                                break;
     813                        case 'd':
     814                        case 'D':
     815                        case 't':
     816                        case 'T':
     817                                base = 10;
     818                                str++;
     819                                break;
     820                        case 'x':
     821                        case 'X':
     822                                base = 16;
     823                                str++;
     824                                break;
     825                        }
     826                }
     827        } else {
     828                /* Check base range */
     829                if ((base < 2) || (base > 36)) {
     830                        *endptr = (char *) str;
     831                        return EINVAL;
     832                }
     833        }
     834       
     835        *result = 0;
     836        const char *startstr = str;
     837       
     838        while (*str != 0) {
     839                unsigned int digit;
     840               
     841                if ((*str >= 'a') && (*str <= 'z'))
     842                        digit = *str - 'a' + 10;
     843                else if ((*str >= 'A') && (*str <= 'Z'))
     844                        digit = *str - 'A' + 10;
     845                else if ((*str >= '0') && (*str <= '9'))
     846                        digit = *str - '0';
     847                else
     848                        break;
     849               
     850                if (digit >= base)
     851                        break;
     852               
     853                uint64_t prev = *result;
     854                *result = (*result) * base + digit;
     855               
     856                if (*result < prev) {
     857                        /* Overflow */
     858                        *endptr = (char *) str;
     859                        return EOVERFLOW;
     860                }
     861               
     862                str++;
     863        }
     864       
     865        if (str == startstr) {
     866                /*
     867                 * No digits were decoded => first invalid character is
     868                 * the first character of the string.
     869                 */
     870                str = nptr;
     871        }
     872       
     873        *endptr = (char *) str;
     874       
     875        if (str == nptr)
     876                return EINVAL;
     877       
     878        return EOK;
     879}
     880
     881/** Convert string to uint64_t.
     882 *
     883 * @param nptr   Pointer to string.
     884 * @param endptr If not NULL, pointer to the first invalid character
     885 *               is stored here.
     886 * @param base   Zero or number between 2 and 36 inclusive.
     887 * @param strict Do not allow any trailing characters.
     888 * @apram result Result of the conversion.
     889 *
     890 * @return EOK if conversion was successful.
     891 *
     892 */
     893int str_uint64(const char *nptr, char **endptr, unsigned int base,
     894    bool strict, uint64_t *result)
     895{
     896        ASSERT(result != NULL);
     897       
     898        bool neg;
     899        char *lendptr;
     900        int ret = str_uint(nptr, &lendptr, base, &neg, result);
     901       
     902        if (endptr != NULL)
     903                *endptr = (char *) lendptr;
     904       
     905        if (ret != EOK)
     906                return ret;
     907       
     908        /* Do not allow negative values */
     909        if (neg)
     910                return EINVAL;
     911       
     912        /* Check whether we are at the end of
     913           the string in strict mode */
     914        if ((strict) && (*lendptr != 0))
     915                return EINVAL;
     916       
     917        return EOK;
     918}
     919
     920void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
     921{
     922        if (val > 10000000000000000000ULL) {
     923                *rv = val / 1000000000000000000ULL;
     924                *suffix = 'Z';
     925        } else if (val > 1000000000000000000ULL) {
     926                *rv = val / 1000000000000000ULL;
     927                *suffix = 'E';
     928        } else if (val > 1000000000000000ULL) {
     929                *rv = val / 1000000000000ULL;
     930                *suffix = 'T';
     931        } else if (val > 1000000000000ULL) {
     932                *rv = val / 1000000000ULL;
     933                *suffix = 'G';
     934        } else if (val > 1000000000ULL) {
     935                *rv = val / 1000000ULL;
     936                *suffix = 'M';
     937        } else if (val > 1000000ULL) {
     938                *rv = val / 1000ULL;
     939                *suffix = 'k';
     940        } else {
     941                *rv = val;
     942                *suffix = ' ';
     943        }
     944}
     945
    707946/** @}
    708947 */
  • kernel/generic/src/main/kinit.c

    r38aaacc2 rf4f866c  
    6767#include <debug.h>
    6868#include <str.h>
     69#include <sysinfo/stats.h>
    6970
    7071#ifdef CONFIG_SMP
     
    122123                } else
    123124                        panic("Unable to create kmp thread.");
     125               
    124126                thread_join(thread);
    125127                thread_detach(thread);
     
    149151         */
    150152        arch_post_smp_init();
     153       
     154        /* Start thread computing system load */
     155        thread = thread_create(kload, NULL, TASK, 0, "kload", false);
     156        if (thread != NULL)
     157                thread_ready(thread);
     158        else
     159                printf("Unable to create kload thread\n");
    151160       
    152161#ifdef CONFIG_KCONSOLE
  • kernel/generic/src/main/main.c

    r38aaacc2 rf4f866c  
    8484#include <main/main.h>
    8585#include <ipc/event.h>
     86#include <sysinfo/sysinfo.h>
     87#include <sysinfo/stats.h>
    8688
    8789/** Global configuration structure. */
     
    209211        /* Initialize at least 1 memory segment big enough for slab to work. */
    210212        LOG_EXEC(slab_cache_init());
     213        LOG_EXEC(sysinfo_init());
    211214        LOG_EXEC(btree_init());
    212215        LOG_EXEC(as_init());
     
    223226       
    224227        printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n",
    225             config.cpu_count, SIZE2MB(zone_total_size()));
    226        
     228            config.cpu_count, SIZE2MB(zones_total_size()));
     229
    227230        LOG_EXEC(cpu_init());
    228231       
     
    247250        LOG_EXEC(event_init());
    248251        LOG_EXEC(klog_init());
     252        LOG_EXEC(stats_init());
    249253       
    250254        /*
  • kernel/generic/src/main/version.c

    r38aaacc2 rf4f866c  
    5959{
    6060        printf("%s, release %s (%s)%s\nBuilt%s for %s\n%s\n",
    61                 project, release, name, revision, timestamp, arch, copyright);
     61            project, release, name, revision, timestamp, arch, copyright);
    6262}
    6363
  • kernel/generic/src/mm/frame.c

    r38aaacc2 rf4f866c  
    12021202
    12031203/** Return total size of all zones. */
    1204 uint64_t zone_total_size(void)
     1204uint64_t zones_total_size(void)
    12051205{
    12061206        ipl_t ipl = interrupts_disable();
     
    12181218}
    12191219
     1220void zones_stats(uint64_t *total, uint64_t *unavail, uint64_t *busy,
     1221    uint64_t *free)
     1222{
     1223        ASSERT(total != NULL);
     1224        ASSERT(unavail != NULL);
     1225        ASSERT(busy != NULL);
     1226        ASSERT(free != NULL);
     1227       
     1228        ipl_t ipl = interrupts_disable();
     1229        spinlock_lock(&zones.lock);
     1230       
     1231        *total = 0;
     1232        *unavail = 0;
     1233        *busy = 0;
     1234        *free = 0;
     1235       
     1236        size_t i;
     1237        for (i = 0; i < zones.count; i++) {
     1238                *total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
     1239               
     1240                if (zone_flags_available(zones.info[i].flags)) {
     1241                        *busy += (uint64_t) FRAMES2SIZE(zones.info[i].busy_count);
     1242                        *free += (uint64_t) FRAMES2SIZE(zones.info[i].free_count);
     1243                } else
     1244                        *unavail += (uint64_t) FRAMES2SIZE(zones.info[i].count);
     1245        }
     1246       
     1247        spinlock_unlock(&zones.lock);
     1248        interrupts_restore(ipl);
     1249}
     1250
    12201251/** Prints list of zones. */
    1221 void zone_print_list(void)
     1252void zones_print_list(void)
    12221253{
    12231254#ifdef __32_BITS__
  • kernel/generic/src/printf/printf.c

    r38aaacc2 rf4f866c  
    3434
    3535#include <print.h>
     36#include <stdarg.h>
    3637
    3738int printf(const char *fmt, ...)
  • kernel/generic/src/printf/printf_core.c

    r38aaacc2 rf4f866c  
    4646/** show prefixes 0x or 0 */
    4747#define __PRINTF_FLAG_PREFIX       0x00000001
     48
    4849/** signed / unsigned number */
    4950#define __PRINTF_FLAG_SIGNED       0x00000002
     51
    5052/** print leading zeroes */
    5153#define __PRINTF_FLAG_ZEROPADDED   0x00000004
     54
    5255/** align to left */
    5356#define __PRINTF_FLAG_LEFTALIGNED  0x00000010
     57
    5458/** always show + sign */
    5559#define __PRINTF_FLAG_SHOWPLUS     0x00000020
     60
    5661/** print space instead of plus */
    5762#define __PRINTF_FLAG_SPACESIGN    0x00000040
     63
    5864/** show big characters */
    5965#define __PRINTF_FLAG_BIGCHARS     0x00000080
     66
    6067/** number has - sign */
    6168#define __PRINTF_FLAG_NEGATIVE     0x00000100
     
    7986} qualifier_t;
    8087
    81 static char nullstr[] = "(NULL)";
    82 static char digits_small[] = "0123456789abcdef";
    83 static char digits_big[] = "0123456789ABCDEF";
    84 static char invalch = U_SPECIAL;
     88static const char *nullstr = "(NULL)";
     89static const char *digits_small = "0123456789abcdef";
     90static const char *digits_big = "0123456789ABCDEF";
     91static const char invalch = U_SPECIAL;
    8592
    8693/** Print one or more characters without adding newline.
     
    351358    uint32_t flags, printf_spec_t *ps)
    352359{
    353         char *digits;
     360        const char *digits;
    354361        if (flags & __PRINTF_FLAG_BIGCHARS)
    355362                digits = digits_big;
  • kernel/generic/src/proc/scheduler.c

    r38aaacc2 rf4f866c  
    202202                 */
    203203
     204                 spinlock_lock(&CPU->lock);
     205                 CPU->idle = true;
     206                 spinlock_unlock(&CPU->lock);
    204207                 cpu_sleep();
    205208                 goto loop;
     
    313316                spinlock_lock(&THREAD->lock);
    314317               
    315                 /* Update thread accounting */
    316                 THREAD->cycles += get_cycle() - THREAD->last_cycle;
     318                /* Update thread kernel accounting */
     319                THREAD->kcycles += get_cycle() - THREAD->last_cycle;
    317320               
    318321#ifndef CONFIG_FPU_LAZY
  • kernel/generic/src/proc/task.c

    r38aaacc2 rf4f866c  
    3333/**
    3434 * @file
    35  * @brief       Task management.
     35 * @brief Task management.
    3636 */
    3737
     
    6666 * The task is guaranteed to exist after it was found in the tasks_tree as
    6767 * long as:
     68 *
    6869 * @li the tasks_lock is held,
    6970 * @li the task's lock is held when task's lock is acquired before releasing
     
    99100        task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    100101        unsigned *cnt = (unsigned *) arg;
    101 
     102       
    102103        if (t != TASK) {
    103104                (*cnt)++;
     
    107108                task_kill_internal(t);
    108109        }
    109 
    110         return true;    /* continue the walk */
     110       
     111        /* Continue the walk */
     112        return true;
    111113}
    112114
     
    115117{
    116118        unsigned tasks_left;
    117 
     119       
    118120        do { /* Repeat until there are any tasks except TASK */
    119121                /* Messing with task structures, avoid deadlock */
     
    138140        task_t *ta = obj;
    139141        int i;
    140 
     142       
    141143        atomic_set(&ta->refcount, 0);
    142144        atomic_set(&ta->lifecount, 0);
    143145        atomic_set(&ta->active_calls, 0);
    144 
     146       
    145147        spinlock_initialize(&ta->lock, "task_ta_lock");
    146148        mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
    147 
     149       
    148150        list_initialize(&ta->th_head);
    149151        list_initialize(&ta->sync_box_head);
    150 
     152       
    151153        ipc_answerbox_init(&ta->answerbox, ta);
    152154        for (i = 0; i < IPC_MAX_PHONES; i++)
    153155                ipc_phone_init(&ta->phones[i]);
    154 
     156       
    155157#ifdef CONFIG_UDEBUG
    156158        /* Init kbox stuff */
     
    159161        mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
    160162#endif
    161 
     163       
    162164        return 0;
    163165}
     
    165167/** Create new task with no threads.
    166168 *
    167  * @param as            Task's address space.
    168  * @param name          Symbolic name (a copy is made).
    169  *
    170  * @return              New task's structure.
     169 * @param as   Task's address space.
     170 * @param name Symbolic name (a copy is made).
     171 *
     172 * @return New task's structure.
    171173 *
    172174 */
     
    181183        memcpy(ta->name, name, TASK_NAME_BUFLEN);
    182184        ta->name[TASK_NAME_BUFLEN - 1] = 0;
    183 
     185       
    184186        ta->context = CONTEXT;
    185187        ta->capabilities = 0;
    186         ta->cycles = 0;
     188        ta->ucycles = 0;
     189        ta->kcycles = 0;
     190
     191        ta->ipc_info.call_sent = 0;
     192        ta->ipc_info.call_recieved = 0;
     193        ta->ipc_info.answer_sent = 0;
     194        ta->ipc_info.answer_recieved = 0;
     195        ta->ipc_info.irq_notif_recieved = 0;
     196        ta->ipc_info.forwarded = 0;
    187197
    188198#ifdef CONFIG_UDEBUG
    189199        /* Init debugging stuff */
    190200        udebug_task_init(&ta->udebug);
    191 
     201       
    192202        /* Init kbox stuff */
    193203        ta->kb.finished = false;
    194204#endif
    195 
     205       
    196206        if ((ipc_phone_0) &&
    197207            (context_check(ipc_phone_0->task->context, ta->context)))
    198208                ipc_phone_connect(&ta->phones[0], ipc_phone_0);
    199 
     209       
    200210        btree_create(&ta->futexes);
    201211       
     
    215225/** Destroy task.
    216226 *
    217  * @param t             Task to be destroyed.
     227 * @param t Task to be destroyed.
     228 *
    218229 */
    219230void task_destroy(task_t *t)
     
    225236        avltree_delete(&tasks_tree, &t->tasks_tree_node);
    226237        spinlock_unlock(&tasks_lock);
    227 
     238       
    228239        /*
    229240         * Perform architecture specific task destruction.
    230241         */
    231242        task_destroy_arch(t);
    232 
     243       
    233244        /*
    234245         * Free up dynamically allocated state.
    235246         */
    236247        btree_destroy(&t->futexes);
    237 
     248       
    238249        /*
    239250         * Drop our reference to the address space.
     
    248259/** Syscall for reading task ID from userspace.
    249260 *
    250  * @param               uspace_task_id userspace address of 8-byte buffer
    251  *                      where to store current task ID.
    252  *
    253  * @return              Zero on success or an error code from @ref errno.h.
     261 * @param uspace_task_id Userspace address of 8-byte buffer
     262 *                       where to store current task ID.
     263 *
     264 * @return Zero on success or an error code from @ref errno.h.
     265 *
    254266 */
    255267unative_t sys_task_get_id(task_id_t *uspace_task_id)
     
    267279 * The name simplifies identifying the task in the task list.
    268280 *
    269  * @param name  The new name for the task. (typically the same
    270  *              as the command used to execute it).
     281 * @param name The new name for the task. (typically the same
     282 *             as the command used to execute it).
    271283 *
    272284 * @return 0 on success or an error code from @ref errno.h.
     285 *
    273286 */
    274287unative_t sys_task_set_name(const char *uspace_name, size_t name_len)
     
    276289        int rc;
    277290        char namebuf[TASK_NAME_BUFLEN];
    278 
     291       
    279292        /* Cap length of name and copy it from userspace. */
    280 
     293       
    281294        if (name_len > TASK_NAME_BUFLEN - 1)
    282295                name_len = TASK_NAME_BUFLEN - 1;
    283 
     296       
    284297        rc = copy_from_uspace(namebuf, uspace_name, name_len);
    285298        if (rc != 0)
    286299                return (unative_t) rc;
    287 
     300       
    288301        namebuf[name_len] = '\0';
    289302        str_cpy(TASK->name, TASK_NAME_BUFLEN, namebuf);
    290 
     303       
    291304        return EOK;
    292305}
     
    297310 * interrupts must be disabled.
    298311 *
    299  * @param id            Task ID.
    300  *
    301  * @return              Task structure address or NULL if there is no such task
    302  *                      ID.
    303  */
    304 task_t *task_find_by_id(task_id_t id) { avltree_node_t *node;
    305        
    306         node = avltree_search(&tasks_tree, (avltree_key_t) id);
    307 
     312 * @param id Task ID.
     313 *
     314 * @return Task structure address or NULL if there is no such task ID.
     315 *
     316 */
     317task_t *task_find_by_id(task_id_t id)
     318{
     319        avltree_node_t *node =
     320            avltree_search(&tasks_tree, (avltree_key_t) id);
     321       
    308322        if (node)
    309323                return avltree_get_instance(node, task_t, tasks_tree_node);
     324       
    310325        return NULL;
    311326}
     
    316331 * already disabled.
    317332 *
    318  * @param t             Pointer to thread.
    319  *
    320  * @return              Number of cycles used by the task and all its threads
    321  *                      so far.
    322  */
    323 uint64_t task_get_accounting(task_t *t)
    324 {
    325         /* Accumulated value of task */
    326         uint64_t ret = t->cycles;
     333 * @param t       Pointer to thread.
     334 * @param ucycles Out pointer to sum of all user cycles.
     335 * @param kcycles Out pointer to sum of all kernel cycles.
     336 *
     337 */
     338void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles)
     339{
     340        /* Accumulated values of task */
     341        uint64_t uret = t->ucycles;
     342        uint64_t kret = t->kcycles;
    327343       
    328344        /* Current values of threads */
     
    336352                        if (thr == THREAD) {
    337353                                /* Update accounting of current thread */
    338                                 thread_update_accounting();
     354                                thread_update_accounting(false);
    339355                        }
    340                         ret += thr->cycles;
     356                        uret += thr->ucycles;
     357                        kret += thr->kcycles;
    341358                }
    342359                spinlock_unlock(&thr->lock);
    343360        }
    344361       
    345         return ret;
     362        *ucycles = uret;
     363        *kcycles = kret;
    346364}
    347365
     
    349367{
    350368        link_t *cur;
    351 
     369       
    352370        /*
    353371         * Interrupt all threads.
     
    377395 * It signals all the task's threads to bail it out.
    378396 *
    379  * @param id            ID of the task to be killed.
    380  *
    381  * @return              Zero on success or an error code from errno.h.
     397 * @param id ID of the task to be killed.
     398 *
     399 * @return Zero on success or an error code from errno.h.
     400 *
    382401 */
    383402int task_kill(task_id_t id)
     
    406425        task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
    407426        int j;
    408                
     427       
    409428        spinlock_lock(&t->lock);
    410                        
    411         uint64_t cycles;
    412         char suffix;
    413         order(task_get_accounting(t), &cycles, &suffix);
    414 
     429       
     430        uint64_t ucycles;
     431        uint64_t kcycles;
     432        char usuffix, ksuffix;
     433        task_get_accounting(t, &ucycles, &kcycles);
     434        order_suffix(ucycles, &ucycles, &usuffix);
     435        order_suffix(kcycles, &kcycles, &ksuffix);
     436       
    415437#ifdef __32_BITS__     
    416         printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64
    417             "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
    418             suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
    419 #endif
    420 
     438        printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 "%c %9"
     439                PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as,
     440                ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount),
     441                atomic_get(&t->active_calls));
     442#endif
     443       
    421444#ifdef __64_BITS__
    422         printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64
    423             "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
    424             suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
    425 #endif
    426 
     445        printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 "%c %9"
     446                PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as,
     447                ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount),
     448                atomic_get(&t->active_calls));
     449#endif
     450       
    427451        for (j = 0; j < IPC_MAX_PHONES; j++) {
    428452                if (t->phones[j].callee)
     
    430454        }
    431455        printf("\n");
    432                        
     456       
    433457        spinlock_unlock(&t->lock);
    434458        return true;
     
    443467        ipl = interrupts_disable();
    444468        spinlock_lock(&tasks_lock);
    445 
    446 #ifdef __32_BITS__     
    447         printf("taskid name         ctx address    as         "
    448             "cycles     threads calls  callee\n");
    449         printf("------ ------------ --- ---------- ---------- "
    450             "---------- ------- ------ ------>\n");
    451 #endif
    452 
     469       
     470#ifdef __32_BITS__
     471        printf("taskid name         ctx address    as        "
     472            " ucycles    kcycles    threads calls  callee\n");
     473        printf("------ ------------ --- ---------- ----------"
     474            " ---------- ---------- ------- ------ ------>\n");
     475#endif
     476       
    453477#ifdef __64_BITS__
    454         printf("taskid name         ctx address            as                 "
    455             "cycles     threads calls  callee\n");
    456         printf("------ ------------ --- ------------------ ------------------ "
    457             "---------- ------- ------ ------>\n");
    458 #endif
    459 
     478        printf("taskid name         ctx address            as                "
     479            " ucycles    kcycles    threads calls  callee\n");
     480        printf("------ ------------ --- ------------------ ------------------"
     481            " ---------- ---------- ---------- ------- ------ ------>\n");
     482#endif
     483       
    460484        avltree_walk(&tasks_tree, task_print_walker, NULL);
    461 
     485       
    462486        spinlock_unlock(&tasks_lock);
    463487        interrupts_restore(ipl);
  • kernel/generic/src/proc/thread.c

    r38aaacc2 rf4f866c  
    5050#include <synch/rwlock.h>
    5151#include <cpu.h>
    52 #include <func.h>
     52#include <str.h>
    5353#include <context.h>
    5454#include <adt/avl.h>
     
    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.
     
    132137        spinlock_lock(&THREAD->lock);
    133138        if (!THREAD->uncounted) {
    134                 thread_update_accounting();
    135                 uint64_t cycles = THREAD->cycles;
    136                 THREAD->cycles = 0;
     139                thread_update_accounting(true);
     140                uint64_t ucycles = THREAD->ucycles;
     141                THREAD->ucycles = 0;
     142                uint64_t kcycles = THREAD->kcycles;
     143                THREAD->kcycles = 0;
     144
    137145                spinlock_unlock(&THREAD->lock);
    138146               
    139147                spinlock_lock(&TASK->lock);
    140                 TASK->cycles += cycles;
     148                TASK->ucycles += ucycles;
     149                TASK->kcycles += kcycles;
    141150                spinlock_unlock(&TASK->lock);
    142151        } else
     
    323332        t->thread_arg = arg;
    324333        t->ticks = -1;
    325         t->cycles = 0;
     334        t->ucycles = 0;
     335        t->kcycles = 0;
    326336        t->uncounted = uncounted;
    327337        t->priority = -1;               /* start in rq[0] */
     
    614624        thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
    615625       
    616         uint64_t cycles;
    617         char suffix;
    618         order(t->cycles, &cycles, &suffix);
     626        uint64_t ucycles, kcycles;
     627        char usuffix, ksuffix;
     628        order_suffix(t->ucycles, &ucycles, &usuffix);
     629        order_suffix(t->kcycles, &kcycles, &ksuffix);
    619630
    620631#ifdef __32_BITS__
    621         printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ",
    622             t->tid, t->name, t, thread_states[t->state], t->task,
    623         t->task->context, t->thread_code, t->kstack, cycles, suffix);
     632        printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9"
     633                PRIu64 "%c %9" PRIu64 "%c ", t->tid, t->name, t,
     634                thread_states[t->state], t->task, t->task->context, t->thread_code,
     635                t->kstack, ucycles, usuffix, kcycles, ksuffix);
    624636#endif
    625637
    626638#ifdef __64_BITS__
    627         printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ",
    628             t->tid, t->name, t, thread_states[t->state], t->task,
    629         t->task->context, t->thread_code, t->kstack, cycles, suffix);
     639        printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9"
     640                PRIu64 "%c %9" PRIu64 "%c ", t->tid, t->name, t,
     641                thread_states[t->state], t->task, t->task->context, t->thread_code,
     642                t->kstack, ucycles, usuffix, kcycles, ksuffix);
    630643#endif
    631644                       
     
    661674#ifdef __32_BITS__     
    662675        printf("tid    name       address    state    task       "
    663                 "ctx code       stack      cycles     cpu  "
     676                "ctx code       stack      ucycles    kcycles    cpu  "
    664677                "waitqueue\n");
    665678        printf("------ ---------- ---------- -------- ---------- "
    666                 "--- ---------- ---------- ---------- ---- "
     679                "--- ---------- ---------- ---------- ---------- ---- "
    667680                "----------\n");
    668681#endif
     
    670683#ifdef __64_BITS__
    671684        printf("tid    name       address            state    task               "
    672                 "ctx code               stack              cycles     cpu  "
     685                "ctx code               stack              ucycles    kcycles    cpu  "
    673686                "waitqueue\n");
    674687        printf("------ ---------- ------------------ -------- ------------------ "
    675                 "--- ------------------ ------------------ ---------- ---- "
     688                "--- ------------------ ------------------ ---------- ---------- ---- "
    676689                "------------------\n");
    677690#endif
     
    706719 * interrupts must be already disabled.
    707720 *
    708  */
    709 void thread_update_accounting(void)
     721 * @param user  True to update user accounting, false for kernel.
     722 */
     723void thread_update_accounting(bool user)
    710724{
    711725        uint64_t time = get_cycle();
    712         THREAD->cycles += time - THREAD->last_cycle;
     726        if (user) {
     727                THREAD->ucycles += time - THREAD->last_cycle;
     728        } else {
     729                THREAD->kcycles += time - THREAD->last_cycle;
     730        }
    713731        THREAD->last_cycle = time;
    714732}
     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
    715770
    716771/** Process syscall to create new thread.
  • kernel/generic/src/synch/waitq.c

    r38aaacc2 rf4f866c  
    5454#include <context.h>
    5555#include <adt/list.h>
     56#include <arch/cycle.h>
    5657
    5758static void waitq_sleep_timed_out(void *data);
     
    373374                if (!context_save(&THREAD->sleep_interruption_context)) {
    374375                        /* Short emulation of scheduler() return code. */
     376                        THREAD->last_cycle = get_cycle();
    375377                        spinlock_unlock(&THREAD->lock);
    376378                        return ESYNCH_INTERRUPTED;
     
    385387                if (!context_save(&THREAD->sleep_timeout_context)) {
    386388                        /* Short emulation of scheduler() return code. */
     389                        THREAD->last_cycle = get_cycle();
    387390                        spinlock_unlock(&THREAD->lock);
    388391                        return ESYNCH_TIMEOUT;
  • kernel/generic/src/syscall/syscall.c

    r38aaacc2 rf4f866c  
    6161        unative_t rc;
    6262
     63        /* Do userpace accounting */
     64        thread_update_accounting(true);
     65
    6366#ifdef CONFIG_UDEBUG
    6467        /*
     
    9598        }
    9699#endif
     100
     101        /* Do kernel accounting */
     102        thread_update_accounting(false);
    97103       
    98104        return rc;
     
    138144        (syshandler_t) sys_ipc_register_irq,
    139145        (syshandler_t) sys_ipc_unregister_irq,
    140 
     146       
    141147        /* Event notification syscalls. */
    142148        (syshandler_t) sys_event_subscribe,
     
    153159       
    154160        /* Sysinfo syscalls */
    155         (syshandler_t) sys_sysinfo_valid,
    156         (syshandler_t) sys_sysinfo_value,
     161        (syshandler_t) sys_sysinfo_get_tag,
     162        (syshandler_t) sys_sysinfo_get_value,
     163        (syshandler_t) sys_sysinfo_get_data_size,
     164        (syshandler_t) sys_sysinfo_get_data,
    157165       
    158166        /* Debug calls */
  • kernel/generic/src/sysinfo/sysinfo.c

    r38aaacc2 rf4f866c  
    3737#include <print.h>
    3838#include <syscall/copy.h>
     39#include <synch/spinlock.h>
     40#include <arch/asm.h>
     41#include <errno.h>
     42
     43/** Maximal sysinfo path length */
     44#define SYSINFO_MAX_PATH  2048
    3945
    4046bool fb_exported = false;
    41 sysinfo_item_t *_root = NULL;
    42 
    43 static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree)
    44 {
    45         if (subtree == NULL)
    46                 return NULL;
    47        
    48         while (subtree != NULL) {
    49                 int i = 0;
    50                 char *a = (char *) name;
    51                 char *b = subtree->name;
    52                
    53                 while ((a[i] == b[i]) && (b[i]))
     47
     48/** Global sysinfo tree root item */
     49static sysinfo_item_t *global_root = NULL;
     50
     51/** Sysinfo SLAB cache */
     52static slab_cache_t *sysinfo_item_slab;
     53
     54/** Sysinfo spinlock */
     55SPINLOCK_STATIC_INITIALIZE_NAME(sysinfo_lock, "sysinfo_lock");
     56
     57/** Sysinfo item constructor
     58 *
     59 */
     60static int sysinfo_item_constructor(void *obj, int kmflag)
     61{
     62        sysinfo_item_t *item = (sysinfo_item_t *) obj;
     63       
     64        item->name = NULL;
     65        item->val_type = SYSINFO_VAL_UNDEFINED;
     66        item->subtree_type = SYSINFO_SUBTREE_NONE;
     67        item->subtree.table = NULL;
     68        item->next = NULL;
     69       
     70        return 0;
     71}
     72
     73/** Sysinfo item destructor
     74 *
     75 * Note that the return value is not perfectly correct
     76 * since more space might get actually freed thanks
     77 * to the disposal of item->name
     78 *
     79 */
     80static int sysinfo_item_destructor(void *obj)
     81{
     82        sysinfo_item_t *item = (sysinfo_item_t *) obj;
     83       
     84        if (item->name != NULL)
     85                free(item->name);
     86       
     87        return 0;
     88}
     89
     90/** Initialize sysinfo subsystem
     91 *
     92 * Create SLAB cache for sysinfo items.
     93 *
     94 */
     95void sysinfo_init(void)
     96{
     97        sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
     98            sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
     99            sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
     100}
     101
     102/** Recursively find an item in sysinfo tree
     103 *
     104 * Should be called with interrupts disabled
     105 * and sysinfo_lock held.
     106 *
     107 * @param name    Current sysinfo path suffix.
     108 * @param subtree Current sysinfo (sub)tree root item.
     109 * @param ret     If the return value is NULL, this argument
     110 *                can be either also NULL (i.e. no item was
     111 *                found and no data was generated) or the
     112 *                original pointer is used to store the value
     113 *                generated by a generated subtree function.
     114 * @param dry_run Do not actually get any generated
     115 *                binary data, just calculate the size.
     116 *
     117 * @return Found item or NULL if no item in the fixed tree
     118 *         was found (N.B. ret).
     119 *
     120 */
     121static sysinfo_item_t *sysinfo_find_item(const char *name,
     122    sysinfo_item_t *subtree, sysinfo_return_t **ret, bool dry_run)
     123{
     124        ASSERT(subtree != NULL);
     125        ASSERT(ret != NULL);
     126       
     127        sysinfo_item_t *cur = subtree;
     128       
     129        /* Walk all siblings */
     130        while (cur != NULL) {
     131                size_t i = 0;
     132               
     133                /* Compare name with path */
     134                while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
    54135                        i++;
    55136               
    56                 if ((!a[i]) && (!b[i]))  /* Last name in path matches */
    57                         return subtree;
    58                
    59                 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
    60                         if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
    61                                 return sysinfo_find_item(a + i + 1, subtree->subinfo.table);
     137                /* Check for perfect name and path match */
     138                if ((name[i] == 0) && (cur->name[i] == 0))
     139                        return cur;
     140               
     141                /* Partial match up to the delimiter */
     142                if ((name[i] == '.') && (cur->name[i] == 0)) {
     143                        /* Look into the subtree */
     144                        switch (cur->subtree_type) {
     145                        case SYSINFO_SUBTREE_TABLE:
     146                                /* Recursively find in subtree */
     147                                return sysinfo_find_item(name + i + 1,
     148                                    cur->subtree.table, ret, dry_run);
     149                        case SYSINFO_SUBTREE_FUNCTION:
     150                                /* Get generated data */
     151                                **ret = cur->subtree.get_data(name + i + 1, dry_run);
     152                                return NULL;
     153                        default:
     154                                /* Not found, no data generated */
     155                                *ret = NULL;
     156                                return NULL;
     157                        }
     158                }
     159               
     160                cur = cur->next;
     161        }
     162       
     163        /* Not found, no data generated */
     164        *ret = NULL;
     165        return NULL;
     166}
     167
     168/** Recursively create items in sysinfo tree
     169 *
     170 * Should be called with interrupts disabled
     171 * and sysinfo_lock held.
     172 *
     173 * @param name     Current sysinfo path suffix.
     174 * @param psubtree Pointer to an already existing (sub)tree root
     175 *                 item or where to store a new tree root item.
     176 *
     177 * @return Existing or newly allocated sysinfo item or NULL
     178 *         if the current tree configuration does not allow to
     179 *         create a new item.
     180 *
     181 */
     182static sysinfo_item_t *sysinfo_create_path(const char *name,
     183    sysinfo_item_t **psubtree)
     184{
     185        ASSERT(psubtree != NULL);
     186       
     187        if (*psubtree == NULL) {
     188                /* No parent */
     189               
     190                size_t i = 0;
     191               
     192                /* Find the first delimiter in name */
     193                while ((name[i] != 0) && (name[i] != '.'))
     194                        i++;
     195               
     196                *psubtree =
     197                    (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
     198                ASSERT(*psubtree);
     199               
     200                /* Fill in item name up to the delimiter */
     201                (*psubtree)->name = str_ndup(name, i);
     202                ASSERT((*psubtree)->name);
     203               
     204                /* Create subtree items */
     205                if (name[i] == '.') {
     206                        (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
     207                        return sysinfo_create_path(name + i + 1,
     208                            &((*psubtree)->subtree.table));
     209                }
     210               
     211                /* No subtree needs to be created */
     212                return *psubtree;
     213        }
     214       
     215        sysinfo_item_t *cur = *psubtree;
     216       
     217        /* Walk all siblings */
     218        while (cur != NULL) {
     219                size_t i = 0;
     220               
     221                /* Compare name with path */
     222                while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
     223                        i++;
     224               
     225                /* Check for perfect name and path match
     226                 * -> item is already present.
     227                 */
     228                if ((name[i] == 0) && (cur->name[i] == 0))
     229                        return cur;
     230               
     231                /* Partial match up to the delimiter */
     232                if ((name[i] == '.') && (cur->name[i] == 0)) {
     233                        switch (cur->subtree_type) {
     234                        case SYSINFO_SUBTREE_NONE:
     235                                /* No subtree yet, create one */
     236                                cur->subtree_type = SYSINFO_SUBTREE_TABLE;
     237                                return sysinfo_create_path(name + i + 1,
     238                                    &(cur->subtree.table));
     239                        case SYSINFO_SUBTREE_TABLE:
     240                                /* Subtree already created, add new sibling */
     241                                return sysinfo_create_path(name + i + 1,
     242                                    &(cur->subtree.table));
     243                        default:
     244                                /* Subtree items handled by a function, this
     245                                 * cannot be overriden by a constant item.
     246                                 */
     247                                return NULL;
     248                        }
     249                }
     250               
     251                /* No match and no more siblings to check
     252                 * -> create a new sibling item.
     253                 */
     254                if (cur->next == NULL) {
     255                        /* Find the first delimiter in name */
     256                        i = 0;
     257                        while ((name[i] != 0) && (name[i] != '.'))
     258                                i++;
    62259                       
    63                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    64                         //      return NULL;
     260                        sysinfo_item_t *item =
     261                            (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
     262                        ASSERT(item);
    65263                       
    66                         return NULL; /* No subinfo */
    67                 }
    68                 /* No matches try next */
    69                 subtree = subtree->next;
    70         }
    71         return NULL;
    72 }
    73 
    74 static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree)
    75 {
    76         sysinfo_item_t *subtree;
    77         subtree = *psubtree;
    78        
    79         if (subtree == NULL) {
    80                 sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
    81                 int i = 0, j;
     264                        cur->next = item;
    82265                       
    83                 ASSERT(item);
    84                 *psubtree = item;
    85                 item->next = NULL;
    86                 item->val_type = SYSINFO_VAL_UNDEFINED;
    87                 item->subinfo.table = NULL;
    88 
    89                 while (name[i] && (name[i] != '.'))
    90                         i++;
     266                        /* Fill in item name up to the delimiter */
     267                        item->name = str_ndup(name, i);
     268                        ASSERT(item->name);
    91269                       
    92                 item->name = malloc(i, 0);
    93                 ASSERT(item->name);
    94 
    95                 for (j = 0; j < i; j++)
    96                         item->name[j] = name[j];
    97                 item->name[j] = 0;
    98                        
    99                 if (name[i]) { /* =='.' */
    100                         item->subinfo_type = SYSINFO_SUBINFO_TABLE;
    101                         return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
    102                 }
    103                 item->subinfo_type = SYSINFO_SUBINFO_NONE;
    104                 return item;
    105         }
    106 
    107         while (subtree != NULL) {
    108                 int i = 0, j;
    109                 char *a = (char *) name;
    110                 char *b = subtree->name;
    111                
    112                 while ((a[i] == b[i]) && (b[i]))
    113                         i++;
    114                
    115                 if ((!a[i]) && (!b[i])) /* Last name in path matches */
    116                         return subtree;
    117                
    118                 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
    119                         if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
    120                                 return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table));
    121                        
    122                         if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) {
    123                                 subtree->subinfo_type = SYSINFO_SUBINFO_TABLE;
    124                                 return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table));
     270                        /* Create subtree items */
     271                        if (name[i] == '.') {
     272                                item->subtree_type = SYSINFO_SUBTREE_TABLE;
     273                                return sysinfo_create_path(name + i + 1,
     274                                    &(item->subtree.table));
    125275                        }
    126276                       
    127                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    128                         //      return NULL;
    129                        
    130                         return NULL;
     277                        /* No subtree needs to be created */
     278                        return item;
    131279                }
    132                 /* No matches try next or create new*/
    133                 if (subtree->next == NULL) {
    134                         sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
    135                        
    136                         ASSERT(item);
    137                         subtree->next = item;
    138                         item->next = NULL;
    139                         item->val_type = SYSINFO_VAL_UNDEFINED;
    140                         item->subinfo.table = NULL;
    141 
    142                         i = 0;
    143                         while (name[i] && (name[i] != '.'))
    144                                 i++;
    145 
    146                         item->name = malloc(i, 0);
    147                         ASSERT(item->name);
    148                        
    149                         for (j = 0; j < i; j++)
    150                                 item->name[j] = name[j];
    151                        
    152                         item->name[j] = 0;
    153 
    154                         if(name[i]) { /* =='.' */
    155                                 item->subinfo_type = SYSINFO_SUBINFO_TABLE;
    156                                 return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
    157                         }
    158                         item->subinfo_type = SYSINFO_SUBINFO_NONE;
    159                         return item;
    160                 } else
    161                         subtree = subtree->next;
    162         }
    163 
    164         panic("Not reached.");
     280               
     281                cur = cur->next;
     282        }
     283       
     284        /* Unreachable */
     285        ASSERT(false);
    165286        return NULL;
    166287}
    167288
    168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
    169 {
     289/** Set sysinfo item with a constant numeric value
     290 *
     291 * @param name Sysinfo path.
     292 * @param root Pointer to the root item or where to store
     293 *             a new root item (NULL for global sysinfo root).
     294 * @param val  Value to store in the item.
     295 *
     296 */
     297void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
     298    unative_t val)
     299{
     300        /* Protect sysinfo tree consistency */
     301        ipl_t ipl = interrupts_disable();
     302        spinlock_lock(&sysinfo_lock);
     303       
    170304        if (root == NULL)
    171                 root = &_root;
    172        
    173         /* If already created create only returns pointer
    174            If not, create it */
     305                root = &global_root;
     306       
    175307        sysinfo_item_t *item = sysinfo_create_path(name, root);
    176        
    177         if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
    178                 item->val.val = val;                   
     308        if (item != NULL) {
    179309                item->val_type = SYSINFO_VAL_VAL;
    180         }
    181 }
    182 
    183 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
    184 {
     310                item->val.val = val;
     311        }
     312       
     313        spinlock_unlock(&sysinfo_lock);
     314        interrupts_restore(ipl);
     315}
     316
     317/** Set sysinfo item with a constant binary data
     318 *
     319 * Note that sysinfo only stores the pointer to the
     320 * binary data and does not touch it in any way. The
     321 * data should be static and immortal.
     322 *
     323 * @param name Sysinfo path.
     324 * @param root Pointer to the root item or where to store
     325 *             a new root item (NULL for global sysinfo root).
     326 * @param data Binary data.
     327 * @param size Size of the binary data.
     328 *
     329 */
     330void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
     331    void *data, size_t size)
     332{
     333        /* Protect sysinfo tree consistency */
     334        ipl_t ipl = interrupts_disable();
     335        spinlock_lock(&sysinfo_lock);
     336       
    185337        if (root == NULL)
    186                 root = &_root;
    187        
    188         /* If already created create only returns pointer
    189            If not, create it */
     338                root = &global_root;
     339       
    190340        sysinfo_item_t *item = sysinfo_create_path(name, root);
    191        
    192         if (item != NULL) { /* If in subsystem, unable to create or return so  unable to set */
    193                 item->val.fn = fn;                   
    194                 item->val_type = SYSINFO_VAL_FUNCTION;
    195         }
    196 }
    197 
    198 
     341        if (item != NULL) {
     342                item->val_type = SYSINFO_VAL_DATA;
     343                item->val.data.data = data;
     344                item->val.data.size = size;
     345        }
     346       
     347        spinlock_unlock(&sysinfo_lock);
     348        interrupts_restore(ipl);
     349}
     350
     351/** Set sysinfo item with a generated numeric value
     352 *
     353 * @param name Sysinfo path.
     354 * @param root Pointer to the root item or where to store
     355 *             a new root item (NULL for global sysinfo root).
     356 * @param fn   Numeric value generator function.
     357 *
     358 */
     359void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
     360    sysinfo_fn_val_t fn)
     361{
     362        /* Protect sysinfo tree consistency */
     363        ipl_t ipl = interrupts_disable();
     364        spinlock_lock(&sysinfo_lock);
     365       
     366        if (root == NULL)
     367                root = &global_root;
     368       
     369        sysinfo_item_t *item = sysinfo_create_path(name, root);
     370        if (item != NULL) {
     371                item->val_type = SYSINFO_VAL_FUNCTION_VAL;
     372                item->val.fn_val = fn;
     373        }
     374       
     375        spinlock_unlock(&sysinfo_lock);
     376        interrupts_restore(ipl);
     377}
     378
     379/** Set sysinfo item with a generated binary data
     380 *
     381 * Note that each time the generator function is called
     382 * it is supposed to return a new dynamically allocated
     383 * data. This data is then freed by sysinfo in the context
     384 * of the current sysinfo request.
     385 *
     386 * @param name Sysinfo path.
     387 * @param root Pointer to the root item or where to store
     388 *             a new root item (NULL for global sysinfo root).
     389 * @param fn   Binary data generator function.
     390 *
     391 */
     392void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
     393    sysinfo_fn_data_t fn)
     394{
     395        /* Protect sysinfo tree consistency */
     396        ipl_t ipl = interrupts_disable();
     397        spinlock_lock(&sysinfo_lock);
     398       
     399        if (root == NULL)
     400                root = &global_root;
     401       
     402        sysinfo_item_t *item = sysinfo_create_path(name, root);
     403        if (item != NULL) {
     404                item->val_type = SYSINFO_VAL_FUNCTION_DATA;
     405                item->val.fn_data = fn;
     406        }
     407       
     408        spinlock_unlock(&sysinfo_lock);
     409        interrupts_restore(ipl);
     410}
     411
     412/** Set sysinfo item with an undefined value
     413 *
     414 * @param name Sysinfo path.
     415 * @param root Pointer to the root item or where to store
     416 *             a new root item (NULL for global sysinfo root).
     417 *
     418 */
    199419void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    200420{
     421        /* Protect sysinfo tree consistency */
     422        ipl_t ipl = interrupts_disable();
     423        spinlock_lock(&sysinfo_lock);
     424       
    201425        if (root == NULL)
    202                 root = &_root;
    203        
    204         /* If already created create only returns pointer
    205            If not, create it */
     426                root = &global_root;
     427       
    206428        sysinfo_item_t *item = sysinfo_create_path(name, root);
    207        
    208429        if (item != NULL)
    209430                item->val_type = SYSINFO_VAL_UNDEFINED;
    210 }
    211 
    212 
    213 void sysinfo_dump(sysinfo_item_t **proot, int depth)
    214 {
    215         sysinfo_item_t *root;
    216         if (proot == NULL)
    217                 proot = &_root;
    218        
    219         root = *proot;
    220        
    221         while (root != NULL) {
    222                 int i;
    223                 unative_t val = 0;
    224                 const char *vtype = NULL;
    225                
    226                
    227                 for (i = 0; i < depth; i++)
    228                         printf("  ");
    229                
    230                 switch (root->val_type) {
     431       
     432        spinlock_unlock(&sysinfo_lock);
     433        interrupts_restore(ipl);
     434}
     435
     436/** Set sysinfo item with a generated subtree
     437 *
     438 * @param name Sysinfo path.
     439 * @param root Pointer to the root item or where to store
     440 *             a new root item (NULL for global sysinfo root).
     441 * @param fn   Subtree generator function.
     442 *
     443 */
     444void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
     445    sysinfo_fn_subtree_t fn)
     446{
     447        /* Protect sysinfo tree consistency */
     448        ipl_t ipl = interrupts_disable();
     449        spinlock_lock(&sysinfo_lock);
     450       
     451        if (root == NULL)
     452                root = &global_root;
     453       
     454        sysinfo_item_t *item = sysinfo_create_path(name, root);
     455       
     456        /* Change the type of the subtree only if it is not already
     457           a fixed subtree */
     458        if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
     459                item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
     460                item->subtree.get_data = fn;
     461        }
     462       
     463        spinlock_unlock(&sysinfo_lock);
     464        interrupts_restore(ipl);
     465}
     466
     467/** Sysinfo dump indentation helper routine
     468 *
     469 * @param depth Number of indentation characters to print.
     470 *
     471 */
     472static void sysinfo_indent(unsigned int depth)
     473{
     474        unsigned int i;
     475        for (i = 0; i < depth; i++)
     476                printf("  ");
     477}
     478
     479/** Dump the structure of sysinfo tree
     480 *
     481 * Should be called with interrupts disabled
     482 * and sysinfo_lock held. Because this routine
     483 * might take a reasonable long time to proceed,
     484 * having the spinlock held is not optimal, but
     485 * there is no better simple solution.
     486 *
     487 * @param root  Root item of the current (sub)tree.
     488 * @param depth Current depth in the sysinfo tree.
     489 *
     490 */
     491static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
     492{
     493        sysinfo_item_t *cur = root;
     494       
     495        /* Walk all siblings */
     496        while (cur != NULL) {
     497                sysinfo_indent(depth);
     498               
     499                unative_t val;
     500                size_t size;
     501               
     502                /* Display node value and type */
     503                switch (cur->val_type) {
    231504                case SYSINFO_VAL_UNDEFINED:
    232                         val = 0;
    233                         vtype = "UND";
     505                        printf("+ %s\n", cur->name);
    234506                        break;
    235507                case SYSINFO_VAL_VAL:
    236                         val = root->val.val;
    237                         vtype = "VAL";
    238                         break;
    239                 case SYSINFO_VAL_FUNCTION:
    240                         val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
    241                         vtype = "FUN";
    242                         break;
     508                        printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
     509                            cur->val.val, cur->val.val);
     510                        break;
     511                case SYSINFO_VAL_DATA:
     512                        printf("+ %s (%" PRIs" bytes)\n", cur->name,
     513                            cur->val.data.size);
     514                        break;
     515                case SYSINFO_VAL_FUNCTION_VAL:
     516                        val = cur->val.fn_val(cur);
     517                        printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
     518                            cur->name, val, val);
     519                        break;
     520                case SYSINFO_VAL_FUNCTION_DATA:
     521                        /* N.B.: No data was actually returned (only a dry run) */
     522                        (void) cur->val.fn_data(cur, &size, true);
     523                        printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
     524                            size);
     525                        break;
     526                default:
     527                        printf("+ %s [unknown]\n", cur->name);
    243528                }
    244529               
    245                 printf("%s    %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val,
    246                         val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ?
    247                         "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ?
    248                         "TAB" : "FUN"));
    249                
    250                 if (root->subinfo_type == SYSINFO_SUBINFO_TABLE)
    251                         sysinfo_dump(&(root -> subinfo.table), depth + 1);
    252                
    253                 root = root->next;
    254         }
    255 }
    256 
    257 sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root)
    258 {
    259         // TODO: Implement Subsystem subinfo (by function implemented subinfo)
    260 
    261         sysinfo_rettype_t ret = {0, false};
    262 
     530                /* Recursivelly nest into the subtree */
     531                switch (cur->subtree_type) {
     532                case SYSINFO_SUBTREE_NONE:
     533                        break;
     534                case SYSINFO_SUBTREE_TABLE:
     535                        sysinfo_dump_internal(cur->subtree.table, depth + 1);
     536                        break;
     537                case SYSINFO_SUBTREE_FUNCTION:
     538                        sysinfo_indent(depth + 1);
     539                        printf("+ [generated subtree]\n");
     540                        break;
     541                default:
     542                        sysinfo_indent(depth + 1);
     543                        printf("+ [unknown subtree]\n");
     544                }
     545               
     546                cur = cur->next;
     547        }
     548}
     549
     550/** Dump the structure of sysinfo tree
     551 *
     552 * @param root  Root item of the sysinfo (sub)tree.
     553 *              If it is NULL then consider the global
     554 *              sysinfo tree.
     555 *
     556 */
     557void sysinfo_dump(sysinfo_item_t *root)
     558{
     559        /* Avoid other functions to mess with sysinfo
     560           while we are dumping it */
     561        ipl_t ipl = interrupts_disable();
     562        spinlock_lock(&sysinfo_lock);
     563       
    263564        if (root == NULL)
    264                 root = &_root;
    265        
    266         sysinfo_item_t *item = sysinfo_find_item(name, *root);
     565                sysinfo_dump_internal(global_root, 0);
     566        else
     567                sysinfo_dump_internal(root, 0);
     568       
     569        spinlock_unlock(&sysinfo_lock);
     570        interrupts_restore(ipl);
     571}
     572
     573/** Return sysinfo item value determined by name
     574 *
     575 * Should be called with interrupts disabled
     576 * and sysinfo_lock held.
     577 *
     578 * @param name    Sysinfo path.
     579 * @param root    Root item of the sysinfo (sub)tree.
     580 *                If it is NULL then consider the global
     581 *                sysinfo tree.
     582 * @param dry_run Do not actually get any generated
     583 *                binary data, just calculate the size.
     584 *
     585 * @return Item value (constant or generated).
     586 *
     587 */
     588static sysinfo_return_t sysinfo_get_item(const char *name,
     589    sysinfo_item_t **root, bool dry_run)
     590{
     591        if (root == NULL)
     592                root = &global_root;
     593       
     594        /* Try to find the item or generate data */
     595        sysinfo_return_t ret;
     596        sysinfo_return_t *ret_ptr = &ret;
     597        sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
     598            dry_run);
    267599       
    268600        if (item != NULL) {
    269                 if (item->val_type == SYSINFO_VAL_UNDEFINED)
    270                         return ret;
     601                /* Item found in the fixed sysinfo tree */
     602               
     603                ret.tag = item->val_type;
     604                switch (item->val_type) {
     605                case SYSINFO_VAL_UNDEFINED:
     606                        break;
     607                case SYSINFO_VAL_VAL:
     608                        ret.val = item->val.val;
     609                        break;
     610                case SYSINFO_VAL_DATA:
     611                        ret.data = item->val.data;
     612                        break;
     613                case SYSINFO_VAL_FUNCTION_VAL:
     614                        ret.val = item->val.fn_val(item);
     615                        break;
     616                case SYSINFO_VAL_FUNCTION_DATA:
     617                        ret.data.data = item->val.fn_data(item, &ret.data.size,
     618                            dry_run);
     619                        break;
     620                }
     621        } else {
     622                /* No item in the fixed sysinfo tree */
     623                if (ret_ptr == NULL) {
     624                        /* Even no data was generated */
     625                        ret.tag = SYSINFO_VAL_UNDEFINED;
     626                }
     627        }
     628       
     629        return ret;
     630}
     631
     632/** Return sysinfo item determined by name from user space
     633 *
     634 * Should be called with interrupts disabled
     635 * and sysinfo_lock held. The path string passed from
     636 * the user space has to be properly null-terminated
     637 * (the last passed character must be null).
     638 *
     639 * @param ptr     Sysinfo path in the user address space.
     640 * @param size    Size of the path string.
     641 * @param dry_run Do not actually get any generated
     642 *                binary data, just calculate the size.
     643 *
     644 */
     645static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
     646    bool dry_run)
     647{
     648        sysinfo_return_t ret;
     649        ret.tag = SYSINFO_VAL_UNDEFINED;
     650       
     651        if (size > SYSINFO_MAX_PATH)
     652                return ret;
     653       
     654        char *path = (char *) malloc(size + 1, 0);
     655        ASSERT(path);
     656       
     657        if ((copy_from_uspace(path, ptr, size + 1) == 0)
     658            && (path[size] == 0))
     659                ret = sysinfo_get_item(path, NULL, dry_run);
     660       
     661        free(path);
     662        return ret;
     663}
     664
     665/** Get the sysinfo value type (syscall)
     666 *
     667 * The path string passed from the user space has
     668 * to be properly null-terminated (the last passed
     669 * character must be null).
     670 *
     671 * @param path_ptr  Sysinfo path in the user address space.
     672 * @param path_size Size of the path string.
     673 *
     674 * @return Item value type.
     675 *
     676 */
     677unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
     678{
     679        /* Avoid other functions to mess with sysinfo
     680           while we are reading it */
     681        ipl_t ipl = interrupts_disable();
     682        spinlock_lock(&sysinfo_lock);
     683       
     684        /* Get the item.
     685       
     686           N.B.: There is no need to free any potential generated
     687           binary data since we request a dry run */
     688        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
     689       
     690        /* Map generated value types to constant types
     691           (user space does not care whether the
     692           value is constant or generated) */
     693        if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
     694                ret.tag = SYSINFO_VAL_VAL;
     695        else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
     696                ret.tag = SYSINFO_VAL_DATA;
     697       
     698        spinlock_unlock(&sysinfo_lock);
     699        interrupts_restore(ipl);
     700       
     701        return (unative_t) ret.tag;
     702}
     703
     704/** Get the sysinfo numerical value (syscall)
     705 *
     706 * The path string passed from the user space has
     707 * to be properly null-terminated (the last passed
     708 * character must be null).
     709 *
     710 * @param path_ptr  Sysinfo path in the user address space.
     711 * @param path_size Size of the path string.
     712 * @param value_ptr User space pointer where to store the
     713 *                  numberical value.
     714 *
     715 * @return Error code (EOK in case of no error).
     716 *
     717 */
     718unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
     719    void *value_ptr)
     720{
     721        /* Avoid other functions to mess with sysinfo
     722           while we are reading it */
     723        ipl_t ipl = interrupts_disable();
     724        spinlock_lock(&sysinfo_lock);
     725       
     726        /* Get the item.
     727       
     728           N.B.: There is no need to free any potential generated
     729           binary data since we request a dry run */
     730        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
     731        int rc;
     732       
     733        /* Only constant or generated numerical value is returned */
     734        if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
     735                rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
     736        else
     737                rc = EINVAL;
     738       
     739        spinlock_unlock(&sysinfo_lock);
     740        interrupts_restore(ipl);
     741       
     742        return (unative_t) rc;
     743}
     744
     745/** Get the sysinfo binary data size (syscall)
     746 *
     747 * The path string passed from the user space has
     748 * to be properly null-terminated (the last passed
     749 * character must be null).
     750 *
     751 * @param path_ptr  Sysinfo path in the user address space.
     752 * @param path_size Size of the path string.
     753 * @param size_ptr  User space pointer where to store the
     754 *                  binary data size.
     755 *
     756 * @return Error code (EOK in case of no error).
     757 *
     758 */
     759unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
     760    void *size_ptr)
     761{
     762        /* Avoid other functions to mess with sysinfo
     763           while we are reading it */
     764        ipl_t ipl = interrupts_disable();
     765        spinlock_lock(&sysinfo_lock);
     766       
     767        /* Get the item.
     768       
     769           N.B.: There is no need to free any potential generated
     770           binary data since we request a dry run */
     771        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
     772        int rc;
     773       
     774        /* Only the size of constant or generated binary data is considered */
     775        if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
     776                rc = copy_to_uspace(size_ptr, &ret.data.size,
     777                    sizeof(ret.data.size));
     778        else
     779                rc = EINVAL;
     780       
     781        spinlock_unlock(&sysinfo_lock);
     782        interrupts_restore(ipl);
     783       
     784        return (unative_t) rc;
     785}
     786
     787/** Get the sysinfo binary data (syscall)
     788 *
     789 * The path string passed from the user space has
     790 * to be properly null-terminated (the last passed
     791 * character must be null).
     792 *
     793 * The user space buffer must be sized exactly according
     794 * to the size of the binary data, otherwise the request
     795 * fails.
     796 *
     797 * @param path_ptr    Sysinfo path in the user address space.
     798 * @param path_size   Size of the path string.
     799 * @param buffer_ptr  User space pointer to the buffer where
     800 *                    to store the binary data.
     801 * @param buffer_size User space buffer size.
     802 *
     803 * @return Error code (EOK in case of no error).
     804 *
     805 */
     806unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
     807    void *buffer_ptr, size_t buffer_size)
     808{
     809        /* Avoid other functions to mess with sysinfo
     810           while we are reading it */
     811        ipl_t ipl = interrupts_disable();
     812        spinlock_lock(&sysinfo_lock);
     813       
     814        /* Get the item */
     815        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, false);
     816        int rc;
     817       
     818        /* Only constant or generated binary data is considered */
     819        if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
     820                /* Check destination buffer size */
     821                if (ret.data.size == buffer_size)
     822                        rc = copy_to_uspace(buffer_ptr, ret.data.data,
     823                            ret.data.size);
    271824                else
    272                         ret.valid = true;
    273                
    274                 if (item->val_type == SYSINFO_VAL_VAL)
    275                         ret.val = item->val.val;
    276                 else
    277                         ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item);
    278         }
    279         return ret;
    280 }
    281 
    282 #define SYSINFO_MAX_LEN 1024
    283 
    284 unative_t sys_sysinfo_valid(unative_t ptr, unative_t len)
    285 {
    286         char *str;
    287         sysinfo_rettype_t ret = {0, 0};
    288 
    289         if (len > SYSINFO_MAX_LEN)
    290                 return ret.valid;
    291         str = malloc(len + 1, 0);
    292        
    293         ASSERT(str);
    294         if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
    295                 ret = sysinfo_get_val(str, NULL);
    296        
    297         free(str);
    298         return ret.valid;
    299 }
    300 
    301 unative_t sys_sysinfo_value(unative_t ptr, unative_t len)
    302 {
    303         char *str;
    304         sysinfo_rettype_t ret = {0, 0};
    305        
    306         if (len > SYSINFO_MAX_LEN)
    307                 return ret.val;
    308         str = malloc(len + 1, 0);
    309        
    310         ASSERT(str);
    311         if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
    312                 ret = sysinfo_get_val(str, NULL);
    313        
    314         free(str);
    315         return ret.val;
     825                        rc = ENOMEM;
     826        } else
     827                rc = EINVAL;
     828       
     829        /* N.B.: The generated binary data should be freed */
     830        if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
     831                free(ret.data.data);
     832       
     833        spinlock_unlock(&sysinfo_lock);
     834        interrupts_restore(ipl);
     835       
     836        return (unative_t) rc;
    316837}
    317838
  • kernel/generic/src/time/clock.c

    r38aaacc2 rf4f866c  
    8686        uptime->seconds1 = 0;
    8787        uptime->seconds2 = 0;
    88         uptime->useconds = 0; 
     88        uptime->useconds = 0;
    8989
    9090        clock_parea.pbase = (uintptr_t) faddr;
     
    137137        size_t missed_clock_ticks = CPU->missed_clock_ticks;
    138138        unsigned int i;
     139
     140        /* Account lost ticks to CPU usage */
     141        if (CPU->idle) {
     142                ASSERT(missed_clock_ticks == 0);
     143                CPU->idle_ticks++;
     144        } else {
     145                CPU->busy_ticks += missed_clock_ticks + 1;
     146        }
     147        CPU->idle = false;
    139148
    140149        /*
Note: See TracChangeset for help on using the changeset viewer.