Changes in kernel/generic/src/mm/as.c [5df1963:826599a2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/as.c
r5df1963 r826599a2 520 520 } 521 521 522 /** Remove reference to address space area share info. 523 * 524 * If the reference count drops to 0, the sh_info is deallocated. 525 * 526 * @param sh_info Pointer to address space area share info. 527 * 528 */ 529 NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info) 530 { 531 bool dealloc = false; 532 533 mutex_lock(&sh_info->lock); 534 ASSERT(sh_info->refcount); 535 536 if (--sh_info->refcount == 0) { 537 dealloc = true; 538 539 /* 540 * Now walk carefully the pagemap B+tree and free/remove 541 * reference from all frames found there. 542 */ 543 list_foreach(sh_info->pagemap.leaf_list, leaf_link, 544 btree_node_t, node) { 545 btree_key_t i; 546 547 for (i = 0; i < node->keys; i++) 548 frame_free((uintptr_t) node->value[i], 1); 549 } 550 551 } 552 mutex_unlock(&sh_info->lock); 553 554 if (dealloc) { 555 if (sh_info->backend && sh_info->backend->destroy_shared_data) { 556 sh_info->backend->destroy_shared_data( 557 sh_info->backend_shared_data); 558 } 559 btree_destroy(&sh_info->pagemap); 560 free(sh_info); 561 } 562 } 563 564 522 565 /** Create address space area of common attributes. 523 566 * … … 529 572 * @param attrs Attributes of the area. 530 573 * @param backend Address space area backend. NULL if no backend is used. 531 * @param backend_data NULL or a pointer to an array holding two void *.574 * @param backend_data NULL or a pointer to custom backend data. 532 575 * @param base Starting virtual address of the area. 533 576 * If set to -1, a suitable mappable area is found. … … 566 609 } 567 610 568 if (overflows_into_positive(*base, size)) 611 if (overflows_into_positive(*base, size)) { 612 mutex_unlock(&as->lock); 569 613 return NULL; 614 } 570 615 571 616 if (!check_area_conflicts(as, *base, pages, guarded, NULL)) { … … 584 629 area->resident = 0; 585 630 area->base = *base; 631 area->backend = backend; 586 632 area->sh_info = NULL; 587 area->backend = backend;588 633 589 634 if (backend_data) … … 591 636 else 592 637 memsetb(&area->backend_data, sizeof(area->backend_data), 0); 593 638 639 share_info_t *si = NULL; 640 641 /* 642 * Create the sharing info structure. 643 * We do this in advance for every new area, even if it is not going 644 * to be shared. 645 */ 646 if (!(attrs & AS_AREA_ATTR_PARTIAL)) { 647 si = (share_info_t *) malloc(sizeof(share_info_t), 0); 648 mutex_initialize(&si->lock, MUTEX_PASSIVE); 649 si->refcount = 1; 650 si->shared = false; 651 si->backend_shared_data = NULL; 652 si->backend = backend; 653 btree_create(&si->pagemap); 654 655 area->sh_info = si; 656 657 if (area->backend && area->backend->create_shared_data) { 658 if (!area->backend->create_shared_data(area)) { 659 free(area); 660 mutex_unlock(&as->lock); 661 sh_info_remove_reference(si); 662 return NULL; 663 } 664 } 665 } 666 594 667 if (area->backend && area->backend->create) { 595 668 if (!area->backend->create(area)) { 596 669 free(area); 597 670 mutex_unlock(&as->lock); 671 if (!(attrs & AS_AREA_ATTR_PARTIAL)) 672 sh_info_remove_reference(si); 598 673 return NULL; 599 674 } 600 675 } 601 676 602 677 btree_create(&area->used_space); 603 678 btree_insert(&as->as_area_btree, *base, (void *) area, … … 709 784 } 710 785 711 if (area->sh_info) { 786 mutex_lock(&area->sh_info->lock); 787 if (area->sh_info->shared) { 712 788 /* 713 789 * Remapping of shared address space areas 714 790 * is not supported. 715 791 */ 792 mutex_unlock(&area->sh_info->lock); 716 793 mutex_unlock(&area->lock); 717 794 mutex_unlock(&as->lock); 718 795 return ENOTSUP; 719 796 } 797 mutex_unlock(&area->sh_info->lock); 720 798 721 799 size_t pages = SIZE2FRAMES((address - area->base) + size); … … 881 959 } 882 960 883 /** Remove reference to address space area share info.884 *885 * If the reference count drops to 0, the sh_info is deallocated.886 *887 * @param sh_info Pointer to address space area share info.888 *889 */890 NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info)891 {892 bool dealloc = false;893 894 mutex_lock(&sh_info->lock);895 ASSERT(sh_info->refcount);896 897 if (--sh_info->refcount == 0) {898 dealloc = true;899 900 /*901 * Now walk carefully the pagemap B+tree and free/remove902 * reference from all frames found there.903 */904 list_foreach(sh_info->pagemap.leaf_list, leaf_link,905 btree_node_t, node) {906 btree_key_t i;907 908 for (i = 0; i < node->keys; i++)909 frame_free((uintptr_t) node->value[i], 1);910 }911 912 }913 mutex_unlock(&sh_info->lock);914 915 if (dealloc) {916 btree_destroy(&sh_info->pagemap);917 free(sh_info);918 }919 }920 921 961 /** Destroy address space area. 922 962 * … … 1000 1040 area->attributes |= AS_AREA_ATTR_PARTIAL; 1001 1041 1002 if (area->sh_info) 1003 sh_info_remove_reference(area->sh_info); 1042 sh_info_remove_reference(area->sh_info); 1004 1043 1005 1044 mutex_unlock(&area->lock); … … 1088 1127 */ 1089 1128 share_info_t *sh_info = src_area->sh_info; 1090 if (!sh_info) { 1091 sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0); 1092 mutex_initialize(&sh_info->lock, MUTEX_PASSIVE); 1093 sh_info->refcount = 2; 1094 btree_create(&sh_info->pagemap); 1095 src_area->sh_info = sh_info; 1096 1129 1130 mutex_lock(&sh_info->lock); 1131 sh_info->refcount++; 1132 bool shared = sh_info->shared; 1133 sh_info->shared = true; 1134 mutex_unlock(&sh_info->lock); 1135 1136 if (!shared) { 1097 1137 /* 1098 1138 * Call the backend to setup sharing. 1139 * This only happens once for each sh_info. 1099 1140 */ 1100 1141 src_area->backend->share(src_area); 1101 } else {1102 mutex_lock(&sh_info->lock);1103 sh_info->refcount++;1104 mutex_unlock(&sh_info->lock);1105 1142 } 1106 1143 … … 1221 1258 } 1222 1259 1223 if ((area->sh_info) || (area->backend != &anon_backend)) { 1224 /* Copying shared areas not supported yet */ 1260 if (area->backend != &anon_backend) { 1225 1261 /* Copying non-anonymous memory not supported yet */ 1226 1262 mutex_unlock(&area->lock); … … 1228 1264 return ENOTSUP; 1229 1265 } 1266 1267 mutex_lock(&area->sh_info->lock); 1268 if (area->sh_info->shared) { 1269 /* Copying shared areas not supported yet */ 1270 mutex_unlock(&area->sh_info->lock); 1271 mutex_unlock(&area->lock); 1272 mutex_unlock(&as->lock); 1273 return ENOTSUP; 1274 } 1275 mutex_unlock(&area->sh_info->lock); 1230 1276 1231 1277 /* … … 1679 1725 ASSERT(count); 1680 1726 1681 btree_node_t *leaf ;1727 btree_node_t *leaf = NULL; 1682 1728 size_t pages = (size_t) btree_search(&area->used_space, page, &leaf); 1683 1729 if (pages) { … … 1687 1733 return false; 1688 1734 } 1735 1736 ASSERT(leaf != NULL); 1689 1737 1690 1738 if (!leaf->keys) {
Note:
See TracChangeset
for help on using the changeset viewer.