Changes in kernel/generic/src/sysinfo/sysinfo.c [9a426d1f:f97f1e51] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/sysinfo/sysinfo.c
r9a426d1f rf97f1e51 1 1 /* 2 2 * Copyright (c) 2006 Jakub Vana 3 * Copyright (c) 2012 Martin Decky 3 4 * All rights reserved. 4 5 * … … 96 97 void sysinfo_init(void) 97 98 { 98 sysinfo_item_slab = slab_cache_create("sysinfo_item_ slab",99 sysinfo_item_slab = slab_cache_create("sysinfo_item_t", 99 100 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor, 100 101 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED); 101 102 102 103 mutex_initialize(&sysinfo_lock, MUTEX_ACTIVE); 103 104 } … … 110 111 * @param subtree Current sysinfo (sub)tree root item. 111 112 * @param ret If the return value is NULL, this argument 112 * can be either also NULL (i.e. no item was113 * can be set either to NULL (i.e. no item was 113 114 * found and no data was generated) or the 114 115 * original pointer is used to store the value … … 125 126 { 126 127 ASSERT(subtree != NULL); 127 ASSERT(ret != NULL);128 128 129 129 sysinfo_item_t *cur = subtree; … … 151 151 case SYSINFO_SUBTREE_FUNCTION: 152 152 /* 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 154 157 return NULL; 155 158 default: 156 159 /* Not found, no data generated */ 157 *ret = NULL; 160 if (ret != NULL) 161 *ret = NULL; 162 158 163 return NULL; 159 164 } … … 164 169 165 170 /* Not found, no data generated */ 166 *ret = NULL; 171 if (ret != NULL) 172 *ret = NULL; 173 167 174 return NULL; 168 175 } … … 352 359 * a new root item (NULL for global sysinfo root). 353 360 * @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 */ 364 void sysinfo_set_item_gen_val(const char *name, sysinfo_item_t **root, 365 sysinfo_fn_val_t fn, void *data) 358 366 { 359 367 /* Protect sysinfo tree consistency */ … … 366 374 if (item != NULL) { 367 375 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; 369 378 } 370 379 … … 383 392 * a new root item (NULL for global sysinfo root). 384 393 * @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 */ 397 void sysinfo_set_item_gen_data(const char *name, sysinfo_item_t **root, 398 sysinfo_fn_data_t fn, void *data) 389 399 { 390 400 /* Protect sysinfo tree consistency */ … … 397 407 if (item != NULL) { 398 408 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; 400 411 } 401 412 … … 431 442 * a new root item (NULL for global sysinfo root). 432 443 * @param fn Subtree generator function. 444 * @param data Private data to be passed to the generator. 433 445 * 434 446 */ 435 447 void 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) 437 449 { 438 450 /* Protect sysinfo tree consistency */ … … 448 460 if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) { 449 461 item->subtree_type = SYSINFO_SUBTREE_FUNCTION; 450 item->subtree.get_data = fn; 462 item->subtree.generator.fn = fn; 463 item->subtree.generator.data = data; 451 464 } 452 465 … … 456 469 /** Sysinfo dump indentation helper routine 457 470 * 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 */ 474 NO_TRACE static void sysinfo_indent(size_t spaces) 475 { 476 for (size_t i = 0; i < spaces; i++) 477 printf(" "); 466 478 } 467 479 … … 470 482 * Should be called with sysinfo_lock held. 471 483 * 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 */ 488 NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, size_t spaces) 489 { 480 490 /* 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 } 483 502 484 503 sysarg_t val; … … 488 507 switch (cur->val_type) { 489 508 case SYSINFO_VAL_UNDEFINED: 490 printf(" + %s\n", cur->name);509 printf(" [undefined]\n"); 491 510 break; 492 511 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); 495 514 break; 496 515 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); 499 517 break; 500 518 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); 504 522 break; 505 523 case SYSINFO_VAL_FUNCTION_DATA: 506 524 /* 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 525 (void) cur->val.gen_data.fn(cur, &size, true, 526 cur->val.gen_data.data); 527 printf(" (%zu bytes) [generated]\n", size); 510 528 break; 511 529 default: … … 518 536 break; 519 537 case SYSINFO_SUBTREE_TABLE: 520 sysinfo_dump_internal(cur->subtree.table, depth + 1);538 sysinfo_dump_internal(cur->subtree.table, spaces + length); 521 539 break; 522 540 case SYSINFO_SUBTREE_FUNCTION: 523 sysinfo_indent( depth + 1);524 printf(" + [generated subtree]\n");541 sysinfo_indent(spaces + length); 542 printf("<generated subtree>\n"); 525 543 break; 526 544 default: 527 sysinfo_indent( depth + 1);528 printf(" + [unknown subtree]\n");545 sysinfo_indent(spaces + length); 546 printf("<unknown subtree>\n"); 529 547 } 530 531 cur = cur->next;532 548 } 533 549 } … … 594 610 break; 595 611 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); 597 613 break; 598 614 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); 601 617 break; 602 618 } … … 635 651 ASSERT(path); 636 652 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)) { 639 655 /* 640 656 * Prevent other functions from messing with sysinfo while we … … 645 661 mutex_unlock(&sysinfo_lock); 646 662 } 663 647 664 free(path); 648 665 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 */ 682 NO_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 */ 750 NO_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 */ 791 sysarg_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 */ 839 sysarg_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; 649 860 } 650 861 … … 672 883 673 884 /* 674 * Map generated value types to constant types (user space does not care675 * 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). 676 887 */ 677 888 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL) … … 701 912 { 702 913 int rc; 703 914 704 915 /* 705 916 * Get the item. 706 917 * 707 * N.B.: There is no need to free any potential generated binary data708 * 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. 709 920 */ 710 921 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true); … … 741 952 * Get the item. 742 953 * 743 * N.B.: There is no need to free any potential generated binary data744 * 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. 745 956 */ 746 957 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
Note:
See TracChangeset
for help on using the changeset viewer.