Changeset 8d6bc2d5 in mainline
- Timestamp:
- 2006-05-24T22:02:59Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9dfc69a
- Parents:
- 567807b1
- Location:
- generic
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/include/mm/as.h
r567807b1 r8d6bc2d5 149 149 extern void as_switch(as_t *old, as_t *new); 150 150 extern void as_free(as_t *as); 151 extern int as_area_s teal(task_t *src_task, __address src_base, size_t acc_size, __address dst_base);151 extern int as_area_share(as_t *src_as, __address src_base, size_t acc_size, __address dst_base); 152 152 extern size_t as_get_size(__address base); 153 153 extern int used_space_insert(as_area_t *a, __address page, count_t count); -
generic/src/ipc/sysipc.c
r567807b1 r8d6bc2d5 130 130 } else if (IPC_GET_METHOD(*olddata) == IPC_M_AS_AREA_SEND) { 131 131 if (!IPC_GET_RETVAL(answer->data)) { /* Accepted, handle as_area receipt */ 132 return as_area_steal(answer->sender, 133 IPC_GET_ARG2(*olddata),IPC_GET_ARG3(*olddata), 134 IPC_GET_ARG1(answer->data)); 132 ipl_t ipl; 133 as_t *as; 134 135 ipl = interrupts_disable(); 136 spinlock_lock(&answer->sender->lock); 137 as = answer->sender->as; 138 spinlock_unlock(&answer->sender->lock); 139 interrupts_restore(ipl); 140 141 return as_area_share(as, IPC_GET_ARG2(*olddata),IPC_GET_ARG3(*olddata), 142 IPC_GET_ARG1(answer->data)); 135 143 } 136 144 } -
generic/src/mm/as.c
r567807b1 r8d6bc2d5 451 451 } 452 452 453 /** S teal address space area from another task.454 * 455 * Address space area is stolen from another task456 * Moreover, any existing mapping457 * is copied as well, providing thus a mechanism458 * for sharing group of pages. The source address459 * s pace area and any associated mapping is preserved.460 * 461 * @param src_ task Pointer of source task453 /** Share address space area with another or the same address space. 454 * 455 * Address space area of anonymous memory is shared with a new address 456 * space area. If the source address space area has not been shared so 457 * far, a new sh_info is created and the original mapping is duplicated 458 * in its pagemap B+tree. The new address space are simply gets the 459 * sh_info of the source area. 460 * 461 * @param src_as Pointer to source address space 462 462 * @param src_base Base address of the source address space area. 463 463 * @param acc_size Expected size of the source area … … 468 468 * EPERM if there was a problem in accepting the area or 469 469 * ENOMEM if there was a problem in allocating destination 470 * address space area. 471 */ 472 int as_area_steal(task_t *src_task, __address src_base, size_t acc_size, 470 * address space area. ENOTSUP is returned if an attempt 471 * to share non-anonymous address space area is detected. 472 */ 473 int as_area_share(as_t *src_as, __address src_base, size_t acc_size, 473 474 __address dst_base) 474 475 { 475 476 ipl_t ipl; 476 count_t i;477 as_t *src_as;478 477 int src_flags; 479 478 size_t src_size; 480 479 as_area_t *src_area, *dst_area; 480 share_info_t *sh_info; 481 link_t *cur; 481 482 482 483 ipl = interrupts_disable(); 483 spinlock_lock(&src_task->lock);484 src_as = src_task->as;485 486 484 mutex_lock(&src_as->lock); 487 485 src_area = find_area_and_lock(src_as, src_base); … … 490 488 * Could not find the source address space area. 491 489 */ 492 spinlock_unlock(&src_task->lock);493 490 mutex_unlock(&src_as->lock); 494 491 interrupts_restore(ipl); 495 492 return ENOENT; 496 493 } 494 495 if (!src_area->backend || src_area->backend != &anon_backend) { 496 /* 497 * As of now, only anonymous address space areas can be shared. 498 */ 499 mutex_unlock(&src_area->lock); 500 mutex_unlock(&src_as->lock); 501 interrupts_restore(ipl); 502 return ENOTSUP; 503 } 504 497 505 src_size = src_area->pages * PAGE_SIZE; 498 506 src_flags = src_area->flags; 507 508 if (src_size != acc_size) { 509 mutex_unlock(&src_area->lock); 510 mutex_unlock(&src_as->lock); 511 interrupts_restore(ipl); 512 return EPERM; 513 } 514 515 /* 516 * Now we are committed to sharing the area. 517 * First prepare the area for sharing. 518 * Then it will be safe to unlock it. 519 */ 520 sh_info = src_area->sh_info; 521 if (!sh_info) { 522 sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0); 523 mutex_initialize(&sh_info->lock); 524 sh_info->refcount = 2; 525 btree_create(&sh_info->pagemap); 526 src_area->sh_info = sh_info; 527 } else { 528 mutex_lock(&sh_info->lock); 529 sh_info->refcount++; 530 mutex_unlock(&sh_info->lock); 531 } 532 533 /* 534 * Copy used portions of the area to sh_info's page map. 535 */ 536 mutex_lock(&sh_info->lock); 537 for (cur = src_area->used_space.leaf_head.next; cur != &src_area->used_space.leaf_head; cur = cur->next) { 538 btree_node_t *node; 539 int i; 540 541 node = list_get_instance(cur, btree_node_t, leaf_link); 542 for (i = 0; i < node->keys; i++) { 543 __address base = node->key[i]; 544 count_t count = (count_t) node->value[i]; 545 int j; 546 547 for (j = 0; j < count; j++) { 548 pte_t *pte; 549 550 page_table_lock(src_as, false); 551 pte = page_mapping_find(src_as, base + j*PAGE_SIZE); 552 ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte)); 553 btree_insert(&sh_info->pagemap, (base + j*PAGE_SIZE) - src_area->base, 554 (void *) PTE_GET_FRAME(pte), NULL); 555 page_table_unlock(src_as, false); 556 } 557 558 } 559 } 560 mutex_unlock(&sh_info->lock); 561 499 562 mutex_unlock(&src_area->lock); 500 563 mutex_unlock(&src_as->lock); 501 564 502 if (src_size != acc_size) {503 spinlock_unlock(&src_task->lock);504 interrupts_restore(ipl);505 return EPERM;506 }507 565 /* 508 566 * Create copy of the source address space area. … … 516 574 * Destination address space area could not be created. 517 575 */ 518 spinlock_unlock(&src_task->lock); 576 sh_info_remove_reference(sh_info); 577 519 578 interrupts_restore(ipl); 520 579 return ENOMEM; 521 580 } 522 581 523 spinlock_unlock(&src_task->lock);524 525 /*526 * Avoid deadlock by first locking the address space with lower address.527 */528 if (AS < src_as) {529 mutex_lock(&AS->lock);530 mutex_lock(&src_as->lock);531 } else {532 mutex_lock(&AS->lock);533 mutex_lock(&src_as->lock);534 }535 536 for (i = 0; i < SIZE2FRAMES(src_size); i++) {537 pte_t *pte;538 __address frame;539 540 page_table_lock(src_as, false);541 pte = page_mapping_find(src_as, src_base + i*PAGE_SIZE);542 if (pte && PTE_VALID(pte)) {543 ASSERT(PTE_PRESENT(pte));544 frame = PTE_GET_FRAME(pte);545 if (!(src_flags & AS_AREA_DEVICE))546 frame_reference_add(ADDR2PFN(frame));547 page_table_unlock(src_as, false);548 } else {549 page_table_unlock(src_as, false);550 continue;551 }552 553 page_table_lock(AS, false);554 page_mapping_insert(AS, dst_base + i*PAGE_SIZE, frame, area_flags_to_page_flags(src_flags));555 page_table_unlock(AS, false);556 }557 558 582 /* 559 583 * Now the destination address space area has been 560 584 * fully initialized. Clear the AS_AREA_ATTR_PARTIAL 561 * attribute .585 * attribute and set the sh_info. 562 586 */ 563 587 mutex_lock(&dst_area->lock); 564 588 dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL; 589 dst_area->sh_info = sh_info; 565 590 mutex_unlock(&dst_area->lock); 566 591 567 mutex_unlock(&AS->lock);568 mutex_unlock(&src_as->lock);569 592 interrupts_restore(ipl); 570 593 … … 1479 1502 */ 1480 1503 mutex_lock(&area->sh_info->lock); 1481 frame = (__address) btree_search(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE), &leaf); 1504 frame = (__address) btree_search(&area->sh_info->pagemap, 1505 ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf); 1482 1506 if (!frame) { 1483 1507 bool allocate = true; … … 1501 1525 * Insert the address of the newly allocated frame to the pagemap. 1502 1526 */ 1503 btree_insert(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE) , (void *) frame, leaf);1527 btree_insert(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE) - area->base, (void *) frame, leaf); 1504 1528 } 1505 1529 }
Note:
See TracChangeset
for help on using the changeset viewer.