Changeset c30a015 in mainline for kernel/generic/src/sysinfo/sysinfo.c


Ignore:
Timestamp:
2012-03-03T10:32:47Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7689590
Parents:
d0d7afb (diff), 0499235 (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 with mainline

File:
1 edited

Legend:

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

    rd0d7afb rc30a015  
    11/*
    22 * Copyright (c) 2006 Jakub Vana
     3 * Copyright (c) 2012 Martin Decky
    34 * All rights reserved.
    45 *
     
    99100            sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
    100101            sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
    101 
     102       
    102103        mutex_initialize(&sysinfo_lock, MUTEX_ACTIVE);
    103104}
     
    110111 * @param subtree Current sysinfo (sub)tree root item.
    111112 * @param ret     If the return value is NULL, this argument
    112  *                can be either also NULL (i.e. no item was
     113 *                can be set either to NULL (i.e. no item was
    113114 *                found and no data was generated) or the
    114115 *                original pointer is used to store the value
     
    125126{
    126127        ASSERT(subtree != NULL);
    127         ASSERT(ret != NULL);
    128128       
    129129        sysinfo_item_t *cur = subtree;
     
    151151                        case SYSINFO_SUBTREE_FUNCTION:
    152152                                /* Get generated data */
    153                                 **ret = cur->subtree.get_data(name + i + 1, dry_run);
     153                                if (ret != NULL)
     154                                        **ret = cur->subtree.generator.fn(name + i + 1,
     155                                            dry_run, cur->subtree.generator.data);
     156                               
    154157                                return NULL;
    155158                        default:
    156159                                /* Not found, no data generated */
    157                                 *ret = NULL;
     160                                if (ret != NULL)
     161                                        *ret = NULL;
     162                               
    158163                                return NULL;
    159164                        }
     
    164169       
    165170        /* Not found, no data generated */
    166         *ret = NULL;
     171        if (ret != NULL)
     172                *ret = NULL;
     173       
    167174        return NULL;
    168175}
     
    352359 *             a new root item (NULL for global sysinfo root).
    353360 * @param fn   Numeric value generator function.
    354  *
    355  */
    356 void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
    357     sysinfo_fn_val_t fn)
     361 * @param data Private data.
     362 *
     363 */
     364void sysinfo_set_item_gen_val(const char *name, sysinfo_item_t **root,
     365    sysinfo_fn_val_t fn, void *data)
    358366{
    359367        /* Protect sysinfo tree consistency */
     
    366374        if (item != NULL) {
    367375                item->val_type = SYSINFO_VAL_FUNCTION_VAL;
    368                 item->val.fn_val = fn;
     376                item->val.gen_val.fn = fn;
     377                item->val.gen_val.data = data;
    369378        }
    370379       
     
    383392 *             a new root item (NULL for global sysinfo root).
    384393 * @param fn   Binary data generator function.
    385  *
    386  */
    387 void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
    388     sysinfo_fn_data_t fn)
     394 * @param data Private data.
     395 *
     396 */
     397void sysinfo_set_item_gen_data(const char *name, sysinfo_item_t **root,
     398    sysinfo_fn_data_t fn, void *data)
    389399{
    390400        /* Protect sysinfo tree consistency */
     
    397407        if (item != NULL) {
    398408                item->val_type = SYSINFO_VAL_FUNCTION_DATA;
    399                 item->val.fn_data = fn;
     409                item->val.gen_data.fn = fn;
     410                item->val.gen_data.data = data;
    400411        }
    401412       
     
    431442 *             a new root item (NULL for global sysinfo root).
    432443 * @param fn   Subtree generator function.
     444 * @param data Private data to be passed to the generator.
    433445 *
    434446 */
    435447void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
    436     sysinfo_fn_subtree_t fn)
     448    sysinfo_fn_subtree_t fn, void *data)
    437449{
    438450        /* Protect sysinfo tree consistency */
     
    448460        if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
    449461                item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
    450                 item->subtree.get_data = fn;
     462                item->subtree.generator.fn = fn;
     463                item->subtree.generator.data = data;
    451464        }
    452465       
     
    456469/** Sysinfo dump indentation helper routine
    457470 *
    458  * @param depth Number of indentation characters to print.
    459  *
    460  */
    461 NO_TRACE static void sysinfo_indent(unsigned int depth)
    462 {
    463         unsigned int i;
    464         for (i = 0; i < depth; i++)
    465                 printf("  ");
     471 * @param depth Number of spaces to print.
     472 *
     473 */
     474NO_TRACE static void sysinfo_indent(size_t spaces)
     475{
     476        for (size_t i = 0; i < spaces; i++)
     477                printf(" ");
    466478}
    467479
     
    470482 * Should be called with sysinfo_lock held.
    471483 *
    472  * @param root  Root item of the current (sub)tree.
    473  * @param depth Current depth in the sysinfo tree.
    474  *
    475  */
    476 NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
    477 {
    478         sysinfo_item_t *cur = root;
    479        
     484 * @param root   Root item of the current (sub)tree.
     485 * @param spaces Current indentation level.
     486 *
     487 */
     488NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, size_t spaces)
     489{
    480490        /* Walk all siblings */
    481         while (cur != NULL) {
    482                 sysinfo_indent(depth);
     491        for (sysinfo_item_t *cur = root; cur; cur = cur->next) {
     492                size_t length;
     493               
     494                if (spaces == 0) {
     495                        printf("%s", cur->name);
     496                        length = str_length(cur->name);
     497                } else {
     498                        sysinfo_indent(spaces);
     499                        printf(".%s", cur->name);
     500                        length = str_length(cur->name) + 1;
     501                }
    483502               
    484503                sysarg_t val;
     
    488507                switch (cur->val_type) {
    489508                case SYSINFO_VAL_UNDEFINED:
    490                         printf("+ %s\n", cur->name);
     509                        printf(" [undefined]\n");
    491510                        break;
    492511                case SYSINFO_VAL_VAL:
    493                         printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
    494                             cur->val.val, cur->val.val);
     512                        printf(" -> %" PRIun" (%#" PRIxn ")\n", cur->val.val,
     513                            cur->val.val);
    495514                        break;
    496515                case SYSINFO_VAL_DATA:
    497                         printf("+ %s (%zu bytes)\n", cur->name,
    498                             cur->val.data.size);
     516                        printf(" (%zu bytes)\n", cur->val.data.size);
    499517                        break;
    500518                case SYSINFO_VAL_FUNCTION_VAL:
    501                         val = cur->val.fn_val(cur);
    502                         printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
    503                             cur->name, val, val);
     519                        val = cur->val.gen_val.fn(cur, cur->val.gen_val.data);
     520                        printf(" -> %" PRIun" (%#" PRIxn ") [generated]\n", val,
     521                            val);
    504522                        break;
    505523                case SYSINFO_VAL_FUNCTION_DATA:
    506524                        /* N.B.: No data was actually returned (only a dry run) */
    507                         (void) cur->val.fn_data(cur, &size, true);
    508                         printf("+ %s (%zu bytes) [generated]\n", cur->name,
    509                             size);
     525                        (void) cur->val.gen_data.fn(cur, &size, true,
     526                            cur->val.gen_data.data);
     527                        printf(" (%zu bytes) [generated]\n", size);
    510528                        break;
    511529                default:
     
    518536                        break;
    519537                case SYSINFO_SUBTREE_TABLE:
    520                         sysinfo_dump_internal(cur->subtree.table, depth + 1);
     538                        sysinfo_dump_internal(cur->subtree.table, spaces + length);
    521539                        break;
    522540                case SYSINFO_SUBTREE_FUNCTION:
    523                         sysinfo_indent(depth + 1);
    524                         printf("+ [generated subtree]\n");
     541                        sysinfo_indent(spaces + length);
     542                        printf("<generated subtree>\n");
    525543                        break;
    526544                default:
    527                         sysinfo_indent(depth + 1);
    528                         printf("+ [unknown subtree]\n");
     545                        sysinfo_indent(spaces + length);
     546                        printf("<unknown subtree>\n");
    529547                }
    530                
    531                 cur = cur->next;
    532548        }
    533549}
     
    594610                        break;
    595611                case SYSINFO_VAL_FUNCTION_VAL:
    596                         ret.val = item->val.fn_val(item);
     612                        ret.val = item->val.gen_val.fn(item, item->val.gen_val.data);
    597613                        break;
    598614                case SYSINFO_VAL_FUNCTION_DATA:
    599                         ret.data.data = item->val.fn_data(item, &ret.data.size,
    600                             dry_run);
     615                        ret.data.data = item->val.gen_data.fn(item, &ret.data.size,
     616                            dry_run, item->val.gen_data.data);
    601617                        break;
    602618                }
     
    635651        ASSERT(path);
    636652       
    637         if ((copy_from_uspace(path, ptr, size + 1) == 0)
    638             && (path[size] == 0)) {
     653        if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
     654            (path[size] == 0)) {
    639655                /*
    640656                 * Prevent other functions from messing with sysinfo while we
     
    645661                mutex_unlock(&sysinfo_lock);
    646662        }
     663       
    647664        free(path);
    648665        return ret;
     666}
     667
     668/** Return sysinfo keys determined by name
     669 *
     670 * Should be called with sysinfo_lock held.
     671 *
     672 * @param name    Sysinfo path.
     673 * @param root    Root item of the sysinfo (sub)tree.
     674 *                If it is NULL then consider the global
     675 *                sysinfo tree.
     676 * @param dry_run Do not actually get any generated
     677 *                binary data, just calculate the size.
     678 *
     679 * @return Item value (constant or generated).
     680 *
     681 */
     682NO_TRACE static sysinfo_return_t sysinfo_get_keys(const char *name,
     683    sysinfo_item_t **root, bool dry_run)
     684{
     685        if (root == NULL)
     686                root = &global_root;
     687       
     688        sysinfo_item_t *subtree = NULL;
     689       
     690        if (name[0] != 0) {
     691                /* Try to find the item */
     692                sysinfo_item_t *item =
     693                    sysinfo_find_item(name, *root, NULL, dry_run);
     694                if ((item != NULL) &&
     695                    (item->subtree_type == SYSINFO_SUBTREE_TABLE))
     696                        subtree = item->subtree.table;
     697        } else
     698                subtree = *root;
     699       
     700        sysinfo_return_t ret;
     701       
     702        if (subtree != NULL) {
     703                /*
     704                 * Calculate the size of subkeys.
     705                 */
     706                size_t size = 0;
     707                for (sysinfo_item_t *cur = subtree; cur; cur = cur->next)
     708                        size += str_size(cur->name) + 1;
     709               
     710                if (dry_run) {
     711                        ret.tag = SYSINFO_VAL_DATA;
     712                        ret.data.data = NULL;
     713                        ret.data.size = size;
     714                } else {
     715                        /* Allocate buffer for subkeys */
     716                        char *names = (char *) malloc(size, FRAME_ATOMIC);
     717                        if (names == NULL)
     718                                return ret;
     719                       
     720                        size_t pos = 0;
     721                        for (sysinfo_item_t *cur = subtree; cur; cur = cur->next) {
     722                                str_cpy(names + pos, size - pos, cur->name);
     723                                pos += str_size(cur->name) + 1;
     724                        }
     725                       
     726                        /* Correct return value */
     727                        ret.tag = SYSINFO_VAL_DATA;
     728                        ret.data.data = (void *) names;
     729                        ret.data.size = size;
     730                }
     731        } else {
     732                /* No item in the fixed sysinfo tree */
     733                ret.tag = SYSINFO_VAL_UNDEFINED;
     734        }
     735       
     736        return ret;
     737}
     738
     739/** Return sysinfo keys determined by name from user space
     740 *
     741 * The path string passed from the user space has to be properly
     742 * null-terminated (the last passed character must be null).
     743 *
     744 * @param ptr     Sysinfo path in the user address space.
     745 * @param size    Size of the path string.
     746 * @param dry_run Do not actually get any generated
     747 *                binary data, just calculate the size.
     748 *
     749 */
     750NO_TRACE static sysinfo_return_t sysinfo_get_keys_uspace(void *ptr, size_t size,
     751    bool dry_run)
     752{
     753        sysinfo_return_t ret;
     754        ret.tag = SYSINFO_VAL_UNDEFINED;
     755       
     756        if (size > SYSINFO_MAX_PATH)
     757                return ret;
     758       
     759        char *path = (char *) malloc(size + 1, 0);
     760        ASSERT(path);
     761       
     762        if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
     763            (path[size] == 0)) {
     764                /*
     765                 * Prevent other functions from messing with sysinfo while we
     766                 * are reading it.
     767                 */
     768                mutex_lock(&sysinfo_lock);
     769                ret = sysinfo_get_keys(path, NULL, dry_run);
     770                mutex_unlock(&sysinfo_lock);
     771        }
     772       
     773        free(path);
     774        return ret;
     775}
     776
     777/** Get the sysinfo keys size (syscall)
     778 *
     779 * The path string passed from the user space has
     780 * to be properly null-terminated (the last passed
     781 * character must be null).
     782 *
     783 * @param path_ptr  Sysinfo path in the user address space.
     784 * @param path_size Size of the path string.
     785 * @param size_ptr  User space pointer where to store the
     786 *                  keys size.
     787 *
     788 * @return Error code (EOK in case of no error).
     789 *
     790 */
     791sysarg_t sys_sysinfo_get_keys_size(void *path_ptr, size_t path_size,
     792    void *size_ptr)
     793{
     794        int rc;
     795       
     796        /*
     797         * Get the keys.
     798         *
     799         * N.B.: There is no need to free any potential keys
     800         * since we request a dry run.
     801         */
     802        sysinfo_return_t ret =
     803            sysinfo_get_keys_uspace(path_ptr, path_size, true);
     804       
     805        /* Check return data tag */
     806        if (ret.tag == SYSINFO_VAL_DATA)
     807                rc = copy_to_uspace(size_ptr, &ret.data.size,
     808                    sizeof(ret.data.size));
     809        else
     810                rc = EINVAL;
     811       
     812        return (sysarg_t) rc;
     813}
     814
     815/** Get the sysinfo keys (syscall)
     816 *
     817 * The path string passed from the user space has
     818 * to be properly null-terminated (the last passed
     819 * character must be null).
     820 *
     821 * If the user space buffer size does not equal
     822 * the actual size of the returned data, the data
     823 * is truncated.
     824 *
     825 * The actual size of data returned is stored to
     826 * size_ptr.
     827 *
     828 * @param path_ptr    Sysinfo path in the user address space.
     829 * @param path_size   Size of the path string.
     830 * @param buffer_ptr  User space pointer to the buffer where
     831 *                    to store the binary data.
     832 * @param buffer_size User space buffer size.
     833 * @param size_ptr    User space pointer where to store the
     834 *                    binary data size.
     835 *
     836 * @return Error code (EOK in case of no error).
     837 *
     838 */
     839sysarg_t sys_sysinfo_get_keys(void *path_ptr, size_t path_size,
     840    void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
     841{
     842        int rc;
     843       
     844        /* Get the keys */
     845        sysinfo_return_t ret = sysinfo_get_keys_uspace(path_ptr, path_size,
     846            false);
     847       
     848        /* Check return data tag */
     849        if (ret.tag == SYSINFO_VAL_DATA) {
     850                size_t size = min(ret.data.size, buffer_size);
     851                rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
     852                if (rc == EOK)
     853                        rc = copy_to_uspace(size_ptr, &size, sizeof(size));
     854               
     855                free(ret.data.data);
     856        } else
     857                rc = EINVAL;
     858       
     859        return (sysarg_t) rc;
    649860}
    650861
     
    672883       
    673884        /*
    674          * Map generated value types to constant types (user space does not care
    675          * whether the value is constant or generated).
     885         * Map generated value types to constant types (user space does
     886         * not care whether the value is constant or generated).
    676887         */
    677888        if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
     
    701912{
    702913        int rc;
    703 
     914       
    704915        /*
    705916         * Get the item.
    706917         *
    707          * N.B.: There is no need to free any potential generated binary data
    708          * since we request a dry run.
     918         * N.B.: There is no need to free any potential generated binary
     919         * data since we request a dry run.
    709920         */
    710921        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
     
    741952         * Get the item.
    742953         *
    743          * N.B.: There is no need to free any potential generated binary data
    744          * since we request a dry run.
     954         * N.B.: There is no need to free any potential generated binary
     955         * data since we request a dry run.
    745956         */
    746957        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
Note: See TracChangeset for help on using the changeset viewer.