Changeset 8d6bc2d5 in mainline


Ignore:
Timestamp:
2006-05-24T22:02:59Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9dfc69a
Parents:
567807b1
Message:

Reimplement memory sharing. Currently, only
anonymous address space areas can be shared.

Location:
generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • generic/include/mm/as.h

    r567807b1 r8d6bc2d5  
    149149extern void as_switch(as_t *old, as_t *new);
    150150extern void as_free(as_t *as);
    151 extern int as_area_steal(task_t *src_task, __address src_base, size_t acc_size, __address dst_base);
     151extern int as_area_share(as_t *src_as, __address src_base, size_t acc_size, __address dst_base);
    152152extern size_t as_get_size(__address base);
    153153extern int used_space_insert(as_area_t *a, __address page, count_t count);
  • generic/src/ipc/sysipc.c

    r567807b1 r8d6bc2d5  
    130130        } else if (IPC_GET_METHOD(*olddata) == IPC_M_AS_AREA_SEND) {
    131131                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));
    135143                }
    136144        }
  • generic/src/mm/as.c

    r567807b1 r8d6bc2d5  
    451451}
    452452
    453 /** Steal address space area from another task.
    454  *
    455  * Address space area is stolen from another task
    456  * Moreover, any existing mapping
    457  * is copied as well, providing thus a mechanism
    458  * for sharing group of pages. The source address
    459  * space area and any associated mapping is preserved.
    460  *
    461  * @param src_task Pointer of source task
     453/** 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
    462462 * @param src_base Base address of the source address space area.
    463463 * @param acc_size Expected size of the source area
     
    468468 *         EPERM if there was a problem in accepting the area or
    469469 *         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 */
     473int as_area_share(as_t *src_as, __address src_base, size_t acc_size,
    473474                  __address dst_base)
    474475{
    475476        ipl_t ipl;
    476         count_t i;
    477         as_t *src_as;       
    478477        int src_flags;
    479478        size_t src_size;
    480479        as_area_t *src_area, *dst_area;
     480        share_info_t *sh_info;
     481        link_t *cur;
    481482
    482483        ipl = interrupts_disable();
    483         spinlock_lock(&src_task->lock);
    484         src_as = src_task->as;
    485        
    486484        mutex_lock(&src_as->lock);
    487485        src_area = find_area_and_lock(src_as, src_base);
     
    490488                 * Could not find the source address space area.
    491489                 */
    492                 spinlock_unlock(&src_task->lock);
    493490                mutex_unlock(&src_as->lock);
    494491                interrupts_restore(ipl);
    495492                return ENOENT;
    496493        }
     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       
    497505        src_size = src_area->pages * PAGE_SIZE;
    498506        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
    499562        mutex_unlock(&src_area->lock);
    500563        mutex_unlock(&src_as->lock);
    501564
    502         if (src_size != acc_size) {
    503                 spinlock_unlock(&src_task->lock);
    504                 interrupts_restore(ipl);
    505                 return EPERM;
    506         }
    507565        /*
    508566         * Create copy of the source address space area.
     
    516574                 * Destination address space area could not be created.
    517575                 */
    518                 spinlock_unlock(&src_task->lock);
     576                sh_info_remove_reference(sh_info);
     577               
    519578                interrupts_restore(ipl);
    520579                return ENOMEM;
    521580        }
    522581       
    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 
    558582        /*
    559583         * Now the destination address space area has been
    560584         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    561          * attribute.
     585         * attribute and set the sh_info.
    562586         */     
    563587        mutex_lock(&dst_area->lock);
    564588        dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
     589        dst_area->sh_info = sh_info;
    565590        mutex_unlock(&dst_area->lock);
    566591       
    567         mutex_unlock(&AS->lock);
    568         mutex_unlock(&src_as->lock);
    569592        interrupts_restore(ipl);
    570593       
     
    14791502                 */
    14801503                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);
    14821506                if (!frame) {
    14831507                        bool allocate = true;
     
    15011525                                 * Insert the address of the newly allocated frame to the pagemap.
    15021526                                 */
    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);
    15041528                        }
    15051529                }
Note: See TracChangeset for help on using the changeset viewer.