Changeset 80bfb601 in mainline for kernel/generic/src/sysinfo/sysinfo.c
- Timestamp:
- 2010-04-18T09:57:19Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d869398
- Parents:
- fce3536
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/sysinfo/sysinfo.c
rfce3536 r80bfb601 41 41 #include <errno.h> 42 42 43 /** Maximal sysinfo path length */ 43 44 #define SYSINFO_MAX_PATH 2048 44 45 45 46 bool fb_exported = false; 46 47 48 /** Global sysinfo tree root item */ 47 49 static sysinfo_item_t *global_root = NULL; 50 51 /** Sysinfo SLAB cache */ 48 52 static slab_cache_t *sysinfo_item_slab; 49 53 54 /** Sysinfo spinlock */ 50 55 SPINLOCK_STATIC_INITIALIZE_NAME(sysinfo_lock, "sysinfo_lock"); 51 56 57 /** Sysinfo item constructor 58 * 59 */ 52 60 static int sysinfo_item_constructor(void *obj, int kmflag) 53 61 { … … 63 71 } 64 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 */ 65 80 static int sysinfo_item_destructor(void *obj) 66 81 { … … 73 88 } 74 89 90 /** Initialize sysinfo subsystem 91 * 92 * Create SLAB cache for sysinfo items. 93 * 94 */ 75 95 void sysinfo_init(void) 76 96 { … … 80 100 } 81 101 82 /** Recursively find item in sysinfo tree102 /** Recursively find an item in sysinfo tree 83 103 * 84 104 * Should be called with interrupts disabled 85 105 * and sysinfo_lock held. 86 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 * 115 * @return Found item or NULL if no item in the fixed tree 116 * was found (N.B. ret). 117 * 87 118 */ 88 119 static sysinfo_item_t *sysinfo_find_item(const char *name, … … 94 125 sysinfo_item_t *cur = subtree; 95 126 127 /* Walk all siblings */ 96 128 while (cur != NULL) { 97 129 size_t i = 0; … … 118 150 return NULL; 119 151 default: 120 /* Not found */152 /* Not found, no data generated */ 121 153 *ret = NULL; 122 154 return NULL; … … 127 159 } 128 160 161 /* Not found, no data generated */ 129 162 *ret = NULL; 130 163 return NULL; … … 135 168 * Should be called with interrupts disabled 136 169 * and sysinfo_lock held. 170 * 171 * @param name Current sysinfo path suffix. 172 * @param psubtree Pointer to an already existing (sub)tree root 173 * item or where to store a new tree root item. 174 * 175 * @return Existing or newly allocated sysinfo item or NULL 176 * if the current tree configuration does not allow to 177 * create a new item. 137 178 * 138 179 */ … … 172 213 sysinfo_item_t *cur = *psubtree; 173 214 215 /* Walk all siblings */ 174 216 while (cur != NULL) { 175 217 size_t i = 0; … … 199 241 default: 200 242 /* Subtree items handled by a function, this 201 * cannot be overriden .243 * cannot be overriden by a constant item. 202 244 */ 203 245 return NULL; … … 235 277 } 236 278 237 /* Get next sibling */238 279 cur = cur->next; 239 280 } … … 244 285 } 245 286 287 /** Set sysinfo item with a constant numeric value 288 * 289 * @param name Sysinfo path. 290 * @param root Pointer to the root item or where to store 291 * a new root item (NULL for global sysinfo root). 292 * @param val Value to store in the item. 293 * 294 */ 246 295 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, 247 296 unative_t val) 248 297 { 298 /* Protect sysinfo tree consistency */ 249 299 ipl_t ipl = interrupts_disable(); 250 300 spinlock_lock(&sysinfo_lock); … … 263 313 } 264 314 315 /** Set sysinfo item with a constant binary data 316 * 317 * Note that sysinfo only stores the pointer to the 318 * binary data and does not touch it in any way. The 319 * data should be static and immortal. 320 * 321 * @param name Sysinfo path. 322 * @param root Pointer to the root item or where to store 323 * a new root item (NULL for global sysinfo root). 324 * @param data Binary data. 325 * @param size Size of the binary data. 326 * 327 */ 265 328 void sysinfo_set_item_data(const char *name, sysinfo_item_t **root, 266 329 void *data, size_t size) 267 330 { 331 /* Protect sysinfo tree consistency */ 268 332 ipl_t ipl = interrupts_disable(); 269 333 spinlock_lock(&sysinfo_lock); … … 283 347 } 284 348 349 /** Set sysinfo item with a generated numeric value 350 * 351 * @param name Sysinfo path. 352 * @param root Pointer to the root item or where to store 353 * a new root item (NULL for global sysinfo root). 354 * @param fn Numeric value generator function. 355 * 356 */ 285 357 void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root, 286 358 sysinfo_fn_val_t fn) 287 359 { 360 /* Protect sysinfo tree consistency */ 288 361 ipl_t ipl = interrupts_disable(); 289 362 spinlock_lock(&sysinfo_lock); … … 302 375 } 303 376 377 /** Set sysinfo item with a generated binary data 378 * 379 * Note that each time the generator function is called 380 * it is supposed to return a new dynamically allocated 381 * data. This data is then freed by sysinfo in the context 382 * of the current sysinfo request. 383 * 384 * @param name Sysinfo path. 385 * @param root Pointer to the root item or where to store 386 * a new root item (NULL for global sysinfo root). 387 * @param fn Binary data generator function. 388 * 389 */ 304 390 void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root, 305 391 sysinfo_fn_data_t fn) 306 392 { 393 /* Protect sysinfo tree consistency */ 307 394 ipl_t ipl = interrupts_disable(); 308 395 spinlock_lock(&sysinfo_lock); … … 321 408 } 322 409 410 /** Set sysinfo item with an undefined value 411 * 412 * @param name Sysinfo path. 413 * @param root Pointer to the root item or where to store 414 * a new root item (NULL for global sysinfo root). 415 * 416 */ 323 417 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root) 324 418 { 419 /* Protect sysinfo tree consistency */ 325 420 ipl_t ipl = interrupts_disable(); 326 421 spinlock_lock(&sysinfo_lock); … … 337 432 } 338 433 434 /** Set sysinfo item with a generated subtree 435 * 436 * @param name Sysinfo path. 437 * @param root Pointer to the root item or where to store 438 * a new root item (NULL for global sysinfo root). 439 * @param fn Subtree generator function. 440 * 441 */ 339 442 void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root, 340 443 sysinfo_fn_subtree_t fn) 341 444 { 445 /* Protect sysinfo tree consistency */ 342 446 ipl_t ipl = interrupts_disable(); 343 447 spinlock_lock(&sysinfo_lock); … … 347 451 348 452 sysinfo_item_t *item = sysinfo_create_path(name, root); 453 454 /* Change the type of the subtree only if it is not already 455 a fixed subtree */ 349 456 if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) { 350 457 item->subtree_type = SYSINFO_SUBTREE_FUNCTION; … … 357 464 358 465 /** Sysinfo dump indentation helper routine 466 * 467 * @param depth Number of indentation characters to print. 359 468 * 360 469 */ … … 374 483 * there is no better simple solution. 375 484 * 485 * @param root Root item of the current (sub)tree. 486 * @param depth Current depth in the sysinfo tree. 487 * 376 488 */ 377 489 static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth) … … 379 491 sysinfo_item_t *cur = root; 380 492 493 /* Walk all siblings */ 381 494 while (cur != NULL) { 382 495 sysinfo_indent(depth); … … 386 499 size_t size; 387 500 501 /* Display node value and type */ 388 502 switch (cur->val_type) { 389 503 case SYSINFO_VAL_UNDEFINED: … … 405 519 case SYSINFO_VAL_FUNCTION_DATA: 406 520 data = cur->val.fn_data(cur, &size); 521 522 /* N.B.: The generated binary data should be freed */ 407 523 if (data != NULL) 408 524 free(data); … … 415 531 } 416 532 533 /* Recursivelly nest into the subtree */ 417 534 switch (cur->subtree_type) { 418 535 case SYSINFO_SUBTREE_NONE: … … 434 551 } 435 552 553 /** Dump the structure of sysinfo tree 554 * 555 * @param root Root item of the sysinfo (sub)tree. 556 * If it is NULL then consider the global 557 * sysinfo tree. 558 * 559 */ 436 560 void sysinfo_dump(sysinfo_item_t *root) 437 561 { 562 /* Avoid other functions to mess with sysinfo 563 while we are dumping it */ 438 564 ipl_t ipl = interrupts_disable(); 439 565 spinlock_lock(&sysinfo_lock); … … 448 574 } 449 575 450 /** Return sysinfo item determined by name576 /** Return sysinfo item value determined by name 451 577 * 452 578 * Should be called with interrupts disabled 453 579 * and sysinfo_lock held. 454 580 * 581 * @param name Sysinfo path. 582 * @param root Root item of the sysinfo (sub)tree. 583 * If it is NULL then consider the global 584 * sysinfo tree. 585 * 586 * @return Item value (constant or generated). 587 * 455 588 */ 456 589 static sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root) … … 459 592 root = &global_root; 460 593 594 /* Try to find the item or generate data */ 461 595 sysinfo_return_t ret; 462 596 sysinfo_return_t *ret_ptr = &ret; … … 464 598 465 599 if (item != NULL) { 600 /* Item found in the fixed sysinfo tree */ 601 466 602 ret.tag = item->val_type; 467 603 switch (item->val_type) { … … 482 618 } 483 619 } else { 484 if (ret_ptr == NULL) 620 /* No item in the fixed sysinfo tree */ 621 if (ret_ptr == NULL) { 622 /* Even no data was generated */ 485 623 ret.tag = SYSINFO_VAL_UNDEFINED; 624 } 486 625 } 487 626 … … 492 631 * 493 632 * Should be called with interrupts disabled 494 * and sysinfo_lock held. 633 * and sysinfo_lock held. The path string passed from 634 * the user space has to be properly null-terminated 635 * (the last passed character must be null). 636 * 637 * @param ptr Sysinfo path in the user address space. 638 * @param size Size of the path string. 495 639 * 496 640 */ … … 514 658 } 515 659 660 /** Get the sysinfo value type (syscall) 661 * 662 * The path string passed from the user space has 663 * to be properly null-terminated (the last passed 664 * character must be null). 665 * 666 * @param path_ptr Sysinfo path in the user address space. 667 * @param path_size Size of the path string. 668 * 669 * @return Item value type. 670 * 671 */ 516 672 unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size) 517 673 { 518 ipl_t ipl = interrupts_disable(); 519 spinlock_lock(&sysinfo_lock); 520 674 /* Avoid other functions to mess with sysinfo 675 while we are reading it */ 676 ipl_t ipl = interrupts_disable(); 677 spinlock_lock(&sysinfo_lock); 678 679 /* Get the item */ 521 680 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 522 681 682 /* N.B.: The generated binary data should be freed */ 523 683 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL)) 524 684 free(ret.data.data); 525 685 686 /* Map generated value types to constant types 687 (user space does not care whether the 688 value is constant or generated) */ 526 689 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL) 527 690 ret.tag = SYSINFO_VAL_VAL; … … 535 698 } 536 699 700 /** Get the sysinfo numerical value (syscall) 701 * 702 * The path string passed from the user space has 703 * to be properly null-terminated (the last passed 704 * character must be null). 705 * 706 * @param path_ptr Sysinfo path in the user address space. 707 * @param path_size Size of the path string. 708 * @param value_ptr User space pointer where to store the 709 * numberical value. 710 * 711 * @return Error code (EOK in case of no error). 712 * 713 */ 537 714 unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size, 538 715 void *value_ptr) 539 716 { 540 ipl_t ipl = interrupts_disable(); 541 spinlock_lock(&sysinfo_lock); 542 717 /* Avoid other functions to mess with sysinfo 718 while we are reading it */ 719 ipl_t ipl = interrupts_disable(); 720 spinlock_lock(&sysinfo_lock); 721 722 /* Get the item */ 543 723 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 544 724 int rc; 545 725 726 /* Only constant or generated numerical value is returned */ 546 727 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL)) 547 728 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val)); … … 549 730 rc = EINVAL; 550 731 732 /* N.B.: The generated binary data should be freed */ 551 733 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL)) 552 734 free(ret.data.data); … … 558 740 } 559 741 742 /** Get the sysinfo binary data size (syscall) 743 * 744 * The path string passed from the user space has 745 * to be properly null-terminated (the last passed 746 * character must be null). 747 * 748 * @param path_ptr Sysinfo path in the user address space. 749 * @param path_size Size of the path string. 750 * @param size_ptr User space pointer where to store the 751 * binary data size. 752 * 753 * @return Error code (EOK in case of no error). 754 * 755 */ 560 756 unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size, 561 757 void *size_ptr) 562 758 { 563 ipl_t ipl = interrupts_disable(); 564 spinlock_lock(&sysinfo_lock); 565 759 /* Avoid other functions to mess with sysinfo 760 while we are reading it */ 761 ipl_t ipl = interrupts_disable(); 762 spinlock_lock(&sysinfo_lock); 763 764 /* Get the item */ 566 765 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 567 766 int rc; 568 767 768 /* Only the size of constant or generated binary data is considered */ 569 769 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) 570 770 rc = copy_to_uspace(size_ptr, &ret.data.size, … … 573 773 rc = EINVAL; 574 774 775 /* N.B.: The generated binary data should be freed */ 575 776 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL)) 576 777 free(ret.data.data); … … 582 783 } 583 784 785 /** Get the sysinfo binary data (syscall) 786 * 787 * The path string passed from the user space has 788 * to be properly null-terminated (the last passed 789 * character must be null). 790 * 791 * The user space buffer must be sized exactly according 792 * to the size of the binary data, otherwise the request 793 * fails. 794 * 795 * @param path_ptr Sysinfo path in the user address space. 796 * @param path_size Size of the path string. 797 * @param buffer_ptr User space pointer to the buffer where 798 * to store the binary data. 799 * @param buffer_size User space buffer size. 800 * 801 * @return Error code (EOK in case of no error). 802 * 803 */ 584 804 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size, 585 805 void *buffer_ptr, size_t buffer_size) 586 806 { 587 ipl_t ipl = interrupts_disable(); 588 spinlock_lock(&sysinfo_lock); 589 807 /* Avoid other functions to mess with sysinfo 808 while we are reading it */ 809 ipl_t ipl = interrupts_disable(); 810 spinlock_lock(&sysinfo_lock); 811 812 /* Get the item */ 590 813 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 591 814 int rc; 592 815 816 /* Only constant or generated binary data is considered */ 593 817 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) { 818 /* Check destination buffer size */ 594 819 if (ret.data.size == buffer_size) 595 820 rc = copy_to_uspace(buffer_ptr, ret.data.data, … … 600 825 rc = EINVAL; 601 826 827 /* N.B.: The generated binary data should be freed */ 602 828 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL)) 603 829 free(ret.data.data);
Note:
See TracChangeset
for help on using the changeset viewer.