Changeset 83b6ba9f in mainline
- Timestamp:
- 2014-02-18T00:18:48Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8aaf9dc
- Parents:
- 89dcf93
- Location:
- kernel/generic
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/mm/as.h
r89dcf93 r83b6ba9f 140 140 /** This structure can be deallocated if refcount drops to 0. */ 141 141 size_t refcount; 142 142 /** True if the area has been ever shared. */ 143 bool shared; 144 143 145 /** 144 146 * B+tree containing complete map of anonymous pages of the shared area. 145 147 */ 146 148 btree_t pagemap; 149 150 /** Address space area backend. */ 151 struct mem_backend *backend; 152 /** Address space area shared data. */ 153 void *backend_shared_data; 147 154 } share_info_t; 148 155 … … 227 234 int (* page_fault)(as_area_t *, uintptr_t, pf_access_t); 228 235 void (* frame_free)(as_area_t *, uintptr_t, uintptr_t); 236 237 bool (* create_shared_data)(as_area_t *); 238 void (* destroy_shared_data)(void *); 229 239 } mem_backend_t; 230 240 -
kernel/generic/src/mm/as.c
r89dcf93 r83b6ba9f 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 * … … 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 /* -
kernel/generic/src/mm/backend_anon.c
r89dcf93 r83b6ba9f 76 76 .page_fault = anon_page_fault, 77 77 .frame_free = anon_frame_free, 78 79 .create_shared_data = NULL, 80 .destroy_shared_data = NULL 78 81 }; 79 82 … … 190 193 return AS_PF_FAULT; 191 194 192 if (area->sh_info) { 195 mutex_lock(&area->sh_info->lock); 196 if (area->sh_info->shared) { 193 197 btree_node_t *leaf; 194 198 … … 200 204 * mapping, a new frame is allocated and the mapping is created. 201 205 */ 202 mutex_lock(&area->sh_info->lock);203 206 frame = (uintptr_t) btree_search(&area->sh_info->pagemap, 204 207 upage - area->base, &leaf); … … 232 235 } 233 236 frame_reference_add(ADDR2PFN(frame)); 234 mutex_unlock(&area->sh_info->lock);235 237 } else { 236 238 … … 254 256 * Reserve the memory for this page now. 255 257 */ 256 if (!reserve_try_alloc(1)) 258 if (!reserve_try_alloc(1)) { 259 mutex_unlock(&area->sh_info->lock); 257 260 return AS_PF_SILENT; 261 } 258 262 } 259 263 … … 262 266 km_temporary_page_put(kpage); 263 267 } 268 mutex_unlock(&area->sh_info->lock); 264 269 265 270 /* -
kernel/generic/src/mm/backend_elf.c
r89dcf93 r83b6ba9f 75 75 .page_fault = elf_page_fault, 76 76 .frame_free = elf_frame_free, 77 78 .create_shared_data = NULL, 79 .destroy_shared_data = NULL 77 80 }; 78 81 … … 274 277 start_anon = entry->p_vaddr + entry->p_filesz; 275 278 276 if (area->sh_info) { 279 mutex_lock(&area->sh_info->lock); 280 if (area->sh_info->shared) { 277 281 bool found = false; 278 282 … … 281 285 */ 282 286 283 mutex_lock(&area->sh_info->lock);284 287 frame = (uintptr_t) btree_search(&area->sh_info->pagemap, 285 288 upage - area->base, &leaf); … … 384 387 } 385 388 386 if (dirty && area->sh_info ) {389 if (dirty && area->sh_info->shared) { 387 390 frame_reference_add(ADDR2PFN(frame)); 388 391 btree_insert(&area->sh_info->pagemap, upage - area->base, … … 390 393 } 391 394 392 if (area->sh_info) 393 mutex_unlock(&area->sh_info->lock); 395 mutex_unlock(&area->sh_info->lock); 394 396 395 397 page_mapping_insert(AS, upage, frame, as_area_get_flags(area)); -
kernel/generic/src/mm/backend_phys.c
r89dcf93 r83b6ba9f 55 55 static bool phys_is_shareable(as_area_t *); 56 56 57 static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t); 57 58 58 static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t); 59 static bool phys_create_shared_data(as_area_t *); 60 static void phys_destroy_shared_data(void *); 61 62 typedef struct { 63 uintptr_t base; 64 size_t frames; 65 } phys_shared_data_t; 59 66 60 67 mem_backend_t phys_backend = { … … 69 76 .page_fault = phys_page_fault, 70 77 .frame_free = NULL, 78 79 .create_shared_data = phys_create_shared_data, 80 .destroy_shared_data = phys_destroy_shared_data 71 81 }; 82 72 83 73 84 bool phys_create(as_area_t *area) … … 92 103 void phys_destroy(as_area_t *area) 93 104 { 94 mem_backend_data_t *data = &area->backend_data; 95 bool last = true; 96 97 if (area->sh_info) { 98 mutex_lock(&area->sh_info->lock); 99 if (area->sh_info->refcount != 1) 100 last = false; 101 mutex_unlock(&area->sh_info->lock); 102 } 103 104 if (last && data->anonymous) 105 frame_free(data->base, data->frames); 105 /* 106 * Nothing to do. 107 * The anonymous frames, if any, are released in 108 * phys_destroy_shared_data(). 109 */ 106 110 } 107 111 … … 149 153 } 150 154 155 bool phys_create_shared_data(as_area_t *area) 156 { 157 /* 158 * For anonymous phys areas, create the shared data. 159 */ 160 if (area->backend_data.anonymous) { 161 phys_shared_data_t *data; 162 163 data = (phys_shared_data_t *) malloc(sizeof(*data), 0); 164 165 data->base = area->backend_data.base; 166 data->frames = area->backend_data.frames; 167 area->sh_info->backend_shared_data = data; 168 } 169 170 return true; 171 } 172 173 void phys_destroy_shared_data(void *opaque_data) 174 { 175 phys_shared_data_t *data = (phys_shared_data_t *) opaque_data; 176 177 if (data) { 178 frame_free(data->base, data->frames); 179 free(data); 180 } 181 } 182 151 183 /** @} 152 184 */
Note:
See TracChangeset
for help on using the changeset viewer.