Ignore:
Timestamp:
2010-04-17T01:28:38Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9d6bfa5
Parents:
9256ad29
Message:

sysinfo overhaul

  • cleanup (nicer data structures, use of SLAB allocator)
  • add support for storing arbitrary binary data
  • properly reimplement non-constant values (generated by functions)
  • add support for non-constant subtrees (generated by functions)
  • syscall ABI change, libc API change
  • reflect changes in user code

libc: task_spawn() can now return error code

  • reflect change in user code, print error strings after failed task_spawn()

uspace cleanup

  • more use of string and other constants
  • more use of str_error()
  • unify error reporting in init
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/sysinfo/sysinfo.c

    r9256ad29 rd9fae235  
    3737#include <print.h>
    3838#include <syscall/copy.h>
     39#include <errno.h>
     40
     41#define SYSINFO_MAX_PATH  2048
    3942
    4043bool 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]))
     44
     45static sysinfo_item_t *global_root = NULL;
     46static slab_cache_t *sysinfo_item_slab;
     47
     48static int sysinfo_item_constructor(void *obj, int kmflag)
     49{
     50        sysinfo_item_t *item = (sysinfo_item_t *) obj;
     51       
     52        item->name = NULL;
     53        item->val_type = SYSINFO_VAL_UNDEFINED;
     54        item->subtree_type = SYSINFO_SUBTREE_NONE;
     55        item->next = NULL;
     56       
     57        return 0;
     58}
     59
     60static int sysinfo_item_destructor(void *obj)
     61{
     62        sysinfo_item_t *item = (sysinfo_item_t *) obj;
     63       
     64        if (item->name != NULL)
     65                free(item->name);
     66       
     67        return 0;
     68}
     69
     70void sysinfo_init(void)
     71{
     72        sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
     73            sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
     74            sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
     75}
     76
     77static sysinfo_item_t *sysinfo_find_item(const char *name,
     78    sysinfo_item_t *subtree)
     79{
     80        sysinfo_item_t *cur = subtree;
     81       
     82        while (cur != NULL) {
     83                size_t i = 0;
     84               
     85                /* Compare name with path */
     86                while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
    5487                        i++;
    5588               
    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);
     89                /* Check for perfect name and path match */
     90                if ((name[i] == 0) && (cur->name[i] == 0))
     91                        return cur;
     92               
     93                /* Partial match up to the delimiter */
     94                if ((name[i] == '.') && (cur->name[i] == 0)) {
     95                        /* Look into the subtree */
     96                        switch (cur->subtree_type) {
     97                        case SYSINFO_SUBTREE_TABLE:
     98                                /* Recursively find in subtree */
     99                                return sysinfo_find_item(name + i + 1, cur->subtree.table);
     100                        case SYSINFO_SUBTREE_FUNCTION:
     101                                /* Get generated item */
     102                                return cur->subtree.find_item(name + i + 1);
     103                        default:
     104                                /* Not found */
     105                                return NULL;
     106                        }
     107                }
     108               
     109                cur = cur->next;
     110        }
     111       
     112        return NULL;
     113}
     114
     115static sysinfo_item_t *sysinfo_create_path(const char *name,
     116    sysinfo_item_t **psubtree)
     117{
     118        if (*psubtree == NULL) {
     119                /* No parent */
     120               
     121                size_t i = 0;
     122               
     123                /* Find the first delimiter in name */
     124                while ((name[i] != 0) && (name[i] != '.'))
     125                        i++;
     126               
     127                *psubtree =
     128                    (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
     129                ASSERT(*psubtree);
     130               
     131                /* Fill in item name up to the delimiter */
     132                (*psubtree)->name = str_ndup(name, i);
     133                ASSERT((*psubtree)->name);
     134               
     135                /* Create subtree items */
     136                if (name[i] == '.') {
     137                        (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
     138                        return sysinfo_create_path(name + i + 1,
     139                            &((*psubtree)->subtree.table));
     140                }
     141               
     142                /* No subtree needs to be created */
     143                return *psubtree;
     144        }
     145       
     146        sysinfo_item_t *cur = *psubtree;
     147       
     148        while (cur != NULL) {
     149                size_t i = 0;
     150               
     151                /* Compare name with path */
     152                while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
     153                        i++;
     154               
     155                /* Check for perfect name and path match
     156                 * -> item is already present.
     157                 */
     158                if ((name[i] == 0) && (cur->name[i] == 0))
     159                        return cur;
     160               
     161                /* Partial match up to the delimiter */
     162                if ((name[i] == '.') && (cur->name[i] == 0)) {
     163                        switch (cur->subtree_type) {
     164                        case SYSINFO_SUBTREE_NONE:
     165                                /* No subtree yet, create one */
     166                                cur->subtree_type = SYSINFO_SUBTREE_TABLE;
     167                                return sysinfo_create_path(name + i + 1,
     168                                    &(cur->subtree.table));
     169                        case SYSINFO_SUBTREE_TABLE:
     170                                /* Subtree already created, add new sibling */
     171                                return sysinfo_create_path(name + i + 1,
     172                                    &(cur->subtree.table));
     173                        default:
     174                                /* Subtree items handled by a function, this
     175                                 * cannot be overriden.
     176                                 */
     177                                return NULL;
     178                        }
     179                }
     180               
     181                /* No match and no more siblings to check
     182                 * -> create a new sibling item.
     183                 */
     184                if (cur->next == NULL) {
     185                        /* Find the first delimiter in name */
     186                        i = 0;
     187                        while ((name[i] != 0) && (name[i] != '.'))
     188                                i++;
    62189                       
    63                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    64                         //      return NULL;
     190                        sysinfo_item_t *item =
     191                            (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
     192                        ASSERT(item);
    65193                       
    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;
     194                        cur->next = item;
    82195                       
    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++;
     196                        /* Fill in item name up to the delimiter */
     197                        item->name = str_ndup(name, i);
     198                        ASSERT(item->name);
    91199                       
    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));
     200                        /* Create subtree items */
     201                        if (name[i] == '.') {
     202                                item->subtree_type = SYSINFO_SUBTREE_TABLE;
     203                                return sysinfo_create_path(name + i + 1,
     204                                    &(item->subtree.table));
    125205                        }
    126206                       
    127                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    128                         //      return NULL;
    129                        
    130                         return NULL;
    131                 }
    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;
     207                        /* No subtree needs to be created */
    159208                        return item;
    160                 } else
    161                         subtree = subtree->next;
    162         }
    163 
    164         panic("Not reached.");
     209                }
     210               
     211                /* Get next sibling */
     212                cur = cur->next;
     213        }
     214       
     215        /* Unreachable */
     216        ASSERT(false);
    165217        return NULL;
    166218}
    167219
    168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
    169 {
    170         if (root == NULL)
    171                 root = &_root;
    172        
    173         /* If already created create only returns pointer
    174            If not, create it */
     220void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
     221    unative_t val)
     222{
     223        if (root == NULL)
     224                root = &global_root;
     225       
    175226        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;                   
     227        if (item != NULL) {
    179228                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 {
    185         if (root == NULL)
    186                 root = &_root;
    187        
    188         /* If already created create only returns pointer
    189            If not, create it */
     229                item->val.val = val;
     230        }
     231}
     232
     233void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
     234    void *data, size_t size)
     235{
     236        if (root == NULL)
     237                root = &global_root;
     238       
    190239        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 
     240        if (item != NULL) {
     241                item->val_type = SYSINFO_VAL_DATA;
     242                item->val.data.data = data;
     243                item->val.data.size = size;
     244        }
     245}
     246
     247void sysinfo_set_item_val_fn(const char *name, sysinfo_item_t **root,
     248    sysinfo_fn_val_t fn)
     249{
     250        if (root == NULL)
     251                root = &global_root;
     252       
     253        sysinfo_item_t *item = sysinfo_create_path(name, root);
     254        if (item != NULL) {
     255                item->val_type = SYSINFO_VAL_FUNCTION_VAL;
     256                item->val.fn_val = fn;
     257        }
     258}
     259
     260void sysinfo_set_item_data_fn(const char *name, sysinfo_item_t **root,
     261    sysinfo_fn_data_t fn)
     262{
     263        if (root == NULL)
     264                root = &global_root;
     265       
     266        sysinfo_item_t *item = sysinfo_create_path(name, root);
     267        if (item != NULL) {
     268                item->val_type = SYSINFO_VAL_FUNCTION_DATA;
     269                item->val.fn_data = fn;
     270        }
     271}
    198272
    199273void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    200274{
    201275        if (root == NULL)
    202                 root = &_root;
    203        
    204         /* If already created create only returns pointer
    205            If not, create it */
     276                root = &global_root;
     277       
    206278        sysinfo_item_t *item = sysinfo_create_path(name, root);
    207        
    208279        if (item != NULL)
    209280                item->val_type = SYSINFO_VAL_UNDEFINED;
    210281}
    211282
    212 
    213 void sysinfo_dump(sysinfo_item_t **proot, int depth)
    214 {
    215         sysinfo_item_t *root;
     283static void sysinfo_indent(unsigned int depth)
     284{
     285        unsigned int i;
     286        for (i = 0; i < depth; i++)
     287                printf("  ");
     288}
     289
     290void sysinfo_dump(sysinfo_item_t **proot, unsigned int depth)
     291{
    216292        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) {
     293                proot = &global_root;
     294       
     295        sysinfo_item_t *cur = *proot;
     296       
     297        while (cur != NULL) {
     298                sysinfo_indent(depth);
     299               
     300                unative_t val;
     301                size_t size;
     302               
     303                switch (cur->val_type) {
    231304                case SYSINFO_VAL_UNDEFINED:
    232                         val = 0;
    233                         vtype = "UND";
     305                        printf("+ %s\n", cur->name);
    234306                        break;
    235307                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;
    243                 }
    244                
    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 
    263         if (root == NULL)
    264                 root = &_root;
     308                        printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
     309                            cur->val.val, cur->val.val);
     310                        break;
     311                case SYSINFO_VAL_DATA:
     312                        printf("+ %s (%" PRIs" bytes)\n", cur->name,
     313                            cur->val.data.size);
     314                        break;
     315                case SYSINFO_VAL_FUNCTION_VAL:
     316                        val = cur->val.fn_val(cur);
     317                        printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
     318                            cur->name, val, val);
     319                        break;
     320                case SYSINFO_VAL_FUNCTION_DATA:
     321                        cur->val.fn_data(cur, &size);
     322                        printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
     323                            size);
     324                        break;
     325                default:
     326                        printf("+ %s [unknown]\n", cur->name);
     327                }
     328               
     329                switch (cur->subtree_type) {
     330                case SYSINFO_SUBTREE_NONE:
     331                        break;
     332                case SYSINFO_SUBTREE_TABLE:
     333                        sysinfo_dump(&(cur->subtree.table), depth + 1);
     334                        break;
     335                case SYSINFO_SUBTREE_FUNCTION:
     336                        sysinfo_indent(depth + 1);
     337                        printf("  [generated subtree]\n");
     338                        break;
     339                default:
     340                        sysinfo_indent(depth + 1);
     341                        printf("  [unknown subtree]\n");
     342                }
     343               
     344                cur = cur->next;
     345        }
     346}
     347
     348sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root)
     349{
     350        if (root == NULL)
     351                root = &global_root;
    265352       
    266353        sysinfo_item_t *item = sysinfo_find_item(name, *root);
     354        sysinfo_return_t ret;
    267355       
    268356        if (item != NULL) {
    269                 if (item->val_type == SYSINFO_VAL_UNDEFINED)
    270                         return ret;
    271                 else
    272                         ret.valid = true;
    273                
    274                 if (item->val_type == SYSINFO_VAL_VAL)
     357                switch (item->val_type) {
     358                case SYSINFO_VAL_UNDEFINED:
     359                        ret.tag = SYSINFO_VAL_UNDEFINED;
     360                        break;
     361                case SYSINFO_VAL_VAL:
     362                        ret.tag = SYSINFO_VAL_VAL;
    275363                        ret.val = item->val.val;
    276                 else
    277                         ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item);
    278         }
     364                        break;
     365                case SYSINFO_VAL_DATA:
     366                        ret.tag = SYSINFO_VAL_DATA;
     367                        ret.data = item->val.data;
     368                        break;
     369                case SYSINFO_VAL_FUNCTION_VAL:
     370                        ret.tag = SYSINFO_VAL_VAL;
     371                        ret.val = item->val.fn_val(item);
     372                        break;
     373                case SYSINFO_VAL_FUNCTION_DATA:
     374                        ret.tag = SYSINFO_VAL_DATA;
     375                        ret.data.data = item->val.fn_data(item, &ret.data.size);
     376                        break;
     377                }
     378        } else
     379                ret.tag = SYSINFO_VAL_UNDEFINED;
     380       
    279381        return ret;
    280382}
    281383
    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;
     384static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size)
     385{
     386        sysinfo_return_t ret;
     387        ret.tag = SYSINFO_VAL_UNDEFINED;
     388       
     389        if (size > SYSINFO_MAX_PATH)
     390                return ret;
     391       
     392        char *path = (char *) malloc(size + 1, 0);
     393        ASSERT(path);
     394       
     395        if ((copy_from_uspace(path, ptr, size + 1) == 0)
     396            && (path[size] == 0)) {
     397                ret = sysinfo_get_item(path, NULL);
     398                free(path);
     399        }
     400       
     401        return ret;
     402}
     403
     404unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
     405{
     406        return (unative_t) sysinfo_get_item_uspace(path_ptr, path_size).tag;
     407}
     408
     409unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
     410    void *value_ptr)
     411{
     412        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
     413       
     414        if (ret.tag != SYSINFO_VAL_VAL)
     415                return (unative_t) EINVAL;
     416       
     417        return (unative_t) copy_to_uspace(value_ptr, &ret.val,
     418            sizeof(ret.val));
     419}
     420
     421unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
     422    void *size_ptr)
     423{
     424        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
     425       
     426        if (ret.tag != SYSINFO_VAL_DATA)
     427                return (unative_t) EINVAL;
     428       
     429        return (unative_t) copy_to_uspace(size_ptr, &ret.data.size,
     430            sizeof(ret.data.size));
     431}
     432
     433unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
     434    void *buffer_ptr, size_t buffer_size)
     435{
     436        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
     437       
     438        if (ret.tag != SYSINFO_VAL_DATA)
     439                return (unative_t) EINVAL;
     440       
     441        if (ret.data.size != buffer_size)
     442                return ENOMEM;
     443       
     444        return (unative_t) copy_to_uspace(buffer_ptr, ret.data.data,
     445            ret.data.size);
    316446}
    317447
Note: See TracChangeset for help on using the changeset viewer.