Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/as.c

    r5df1963 r826599a2  
    520520}
    521521
     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 */
     529NO_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
    522565/** Create address space area of common attributes.
    523566 *
     
    529572 * @param attrs        Attributes of the area.
    530573 * @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.
    532575 * @param base         Starting virtual address of the area.
    533576 *                     If set to -1, a suitable mappable area is found.
     
    566609        }
    567610
    568         if (overflows_into_positive(*base, size))
     611        if (overflows_into_positive(*base, size)) {
     612                mutex_unlock(&as->lock);
    569613                return NULL;
     614        }
    570615
    571616        if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
     
    584629        area->resident = 0;
    585630        area->base = *base;
     631        area->backend = backend;
    586632        area->sh_info = NULL;
    587         area->backend = backend;
    588633       
    589634        if (backend_data)
     
    591636        else
    592637                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
    594667        if (area->backend && area->backend->create) {
    595668                if (!area->backend->create(area)) {
    596669                        free(area);
    597670                        mutex_unlock(&as->lock);
     671                        if (!(attrs & AS_AREA_ATTR_PARTIAL))
     672                                sh_info_remove_reference(si);
    598673                        return NULL;
    599674                }
    600675        }
    601        
     676
    602677        btree_create(&area->used_space);
    603678        btree_insert(&as->as_area_btree, *base, (void *) area,
     
    709784        }
    710785       
    711         if (area->sh_info) {
     786        mutex_lock(&area->sh_info->lock);
     787        if (area->sh_info->shared) {
    712788                /*
    713789                 * Remapping of shared address space areas
    714790                 * is not supported.
    715791                 */
     792                mutex_unlock(&area->sh_info->lock);
    716793                mutex_unlock(&area->lock);
    717794                mutex_unlock(&as->lock);
    718795                return ENOTSUP;
    719796        }
     797        mutex_unlock(&area->sh_info->lock);
    720798       
    721799        size_t pages = SIZE2FRAMES((address - area->base) + size);
     
    881959}
    882960
    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/remove
    902                  * 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 
    921961/** Destroy address space area.
    922962 *
     
    10001040        area->attributes |= AS_AREA_ATTR_PARTIAL;
    10011041       
    1002         if (area->sh_info)
    1003                 sh_info_remove_reference(area->sh_info);
     1042        sh_info_remove_reference(area->sh_info);
    10041043       
    10051044        mutex_unlock(&area->lock);
     
    10881127         */
    10891128        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) {
    10971137                /*
    10981138                 * Call the backend to setup sharing.
     1139                 * This only happens once for each sh_info.
    10991140                 */
    11001141                src_area->backend->share(src_area);
    1101         } else {
    1102                 mutex_lock(&sh_info->lock);
    1103                 sh_info->refcount++;
    1104                 mutex_unlock(&sh_info->lock);
    11051142        }
    11061143       
     
    12211258        }
    12221259       
    1223         if ((area->sh_info) || (area->backend != &anon_backend)) {
    1224                 /* Copying shared areas not supported yet */
     1260        if (area->backend != &anon_backend) {
    12251261                /* Copying non-anonymous memory not supported yet */
    12261262                mutex_unlock(&area->lock);
     
    12281264                return ENOTSUP;
    12291265        }
     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);
    12301276       
    12311277        /*
     
    16791725        ASSERT(count);
    16801726       
    1681         btree_node_t *leaf;
     1727        btree_node_t *leaf = NULL;
    16821728        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
    16831729        if (pages) {
     
    16871733                return false;
    16881734        }
     1735
     1736        ASSERT(leaf != NULL);
    16891737       
    16901738        if (!leaf->keys) {
Note: See TracChangeset for help on using the changeset viewer.