Ignore:
File:
1 edited

Legend:

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

    r59fb782 r83b6ba9f  
    488488       
    489489        /* Eventually check the addresses behind each area */
    490         list_foreach(as->as_area_btree.leaf_list, cur) {
    491                 btree_node_t *node =
    492                     list_get_instance(cur, btree_node_t, leaf_link);
     490        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t, node) {
    493491               
    494492                for (btree_key_t i = 0; i < node->keys; i++) {
     
    521519        return (uintptr_t) -1;
    522520}
     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 */
     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
    523564
    524565/** Create address space area of common attributes.
     
    568609        }
    569610
    570         if (overflows_into_positive(*base, size))
     611        if (overflows_into_positive(*base, size)) {
     612                mutex_unlock(&as->lock);
    571613                return NULL;
     614        }
    572615
    573616        if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
     
    586629        area->resident = 0;
    587630        area->base = *base;
     631        area->backend = backend;
    588632        area->sh_info = NULL;
    589         area->backend = backend;
    590633       
    591634        if (backend_data)
     
    593636        else
    594637                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
    595        
     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
    596667        if (area->backend && area->backend->create) {
    597668                if (!area->backend->create(area)) {
    598669                        free(area);
    599670                        mutex_unlock(&as->lock);
     671                        if (!(attrs & AS_AREA_ATTR_PARTIAL))
     672                                sh_info_remove_reference(si);
    600673                        return NULL;
    601674                }
    602675        }
    603        
     676
    604677        btree_create(&area->used_space);
    605678        btree_insert(&as->as_area_btree, *base, (void *) area,
     
    711784        }
    712785       
    713         if (area->sh_info) {
     786        mutex_lock(&area->sh_info->lock);
     787        if (area->sh_info->shared) {
    714788                /*
    715789                 * Remapping of shared address space areas
    716790                 * is not supported.
    717791                 */
     792                mutex_unlock(&area->sh_info->lock);
    718793                mutex_unlock(&area->lock);
    719794                mutex_unlock(&as->lock);
    720795                return ENOTSUP;
    721796        }
     797        mutex_unlock(&area->sh_info->lock);
    722798       
    723799        size_t pages = SIZE2FRAMES((address - area->base) + size);
     
    883959}
    884960
    885 /** Remove reference to address space area share info.
    886  *
    887  * If the reference count drops to 0, the sh_info is deallocated.
    888  *
    889  * @param sh_info Pointer to address space area share info.
    890  *
    891  */
    892 NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info)
    893 {
    894         bool dealloc = false;
    895        
    896         mutex_lock(&sh_info->lock);
    897         ASSERT(sh_info->refcount);
    898        
    899         if (--sh_info->refcount == 0) {
    900                 dealloc = true;
    901                
    902                 /*
    903                  * Now walk carefully the pagemap B+tree and free/remove
    904                  * reference from all frames found there.
    905                  */
    906                 list_foreach(sh_info->pagemap.leaf_list, cur) {
    907                         btree_node_t *node
    908                             = list_get_instance(cur, btree_node_t, leaf_link);
    909                         btree_key_t i;
    910                        
    911                         for (i = 0; i < node->keys; i++)
    912                                 frame_free((uintptr_t) node->value[i]);
    913                 }
    914                
    915         }
    916         mutex_unlock(&sh_info->lock);
    917        
    918         if (dealloc) {
    919                 btree_destroy(&sh_info->pagemap);
    920                 free(sh_info);
    921         }
    922 }
    923 
    924961/** Destroy address space area.
    925962 *
     
    956993         * Visit only the pages mapped by used_space B+tree.
    957994         */
    958         list_foreach(area->used_space.leaf_list, cur) {
    959                 btree_node_t *node;
     995        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     996            node) {
    960997                btree_key_t i;
    961998               
    962                 node = list_get_instance(cur, btree_node_t, leaf_link);
    963999                for (i = 0; i < node->keys; i++) {
    9641000                        uintptr_t ptr = node->key[i];
     
    10041040        area->attributes |= AS_AREA_ATTR_PARTIAL;
    10051041       
    1006         if (area->sh_info)
    1007                 sh_info_remove_reference(area->sh_info);
     1042        sh_info_remove_reference(area->sh_info);
    10081043       
    10091044        mutex_unlock(&area->lock);
     
    10921127         */
    10931128        share_info_t *sh_info = src_area->sh_info;
    1094         if (!sh_info) {
    1095                 sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
    1096                 mutex_initialize(&sh_info->lock, MUTEX_PASSIVE);
    1097                 sh_info->refcount = 2;
    1098                 btree_create(&sh_info->pagemap);
    1099                 src_area->sh_info = sh_info;
    1100                
     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) {
    11011137                /*
    11021138                 * Call the backend to setup sharing.
     1139                 * This only happens once for each sh_info.
    11031140                 */
    11041141                src_area->backend->share(src_area);
    1105         } else {
    1106                 mutex_lock(&sh_info->lock);
    1107                 sh_info->refcount++;
    1108                 mutex_unlock(&sh_info->lock);
    11091142        }
    11101143       
     
    12251258        }
    12261259       
    1227         if ((area->sh_info) || (area->backend != &anon_backend)) {
    1228                 /* Copying shared areas not supported yet */
     1260        if (area->backend != &anon_backend) {
    12291261                /* Copying non-anonymous memory not supported yet */
    12301262                mutex_unlock(&area->lock);
     
    12321264                return ENOTSUP;
    12331265        }
     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);
    12341276       
    12351277        /*
     
    12381280        size_t used_pages = 0;
    12391281       
    1240         list_foreach(area->used_space.leaf_list, cur) {
    1241                 btree_node_t *node
    1242                     = list_get_instance(cur, btree_node_t, leaf_link);
     1282        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     1283            node) {
    12431284                btree_key_t i;
    12441285               
     
    12641305        size_t frame_idx = 0;
    12651306       
    1266         list_foreach(area->used_space.leaf_list, cur) {
    1267                 btree_node_t *node = list_get_instance(cur, btree_node_t,
    1268                     leaf_link);
     1307        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     1308            node) {
    12691309                btree_key_t i;
    12701310               
     
    13161356        frame_idx = 0;
    13171357       
    1318         list_foreach(area->used_space.leaf_list, cur) {
    1319                 btree_node_t *node
    1320                     = list_get_instance(cur, btree_node_t, leaf_link);
     1358        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     1359            node) {
    13211360                btree_key_t i;
    13221361               
     
    21822221        size_t area_cnt = 0;
    21832222       
    2184         list_foreach(as->as_area_btree.leaf_list, cur) {
    2185                 btree_node_t *node =
    2186                     list_get_instance(cur, btree_node_t, leaf_link);
     2223        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
     2224            node) {
    21872225                area_cnt += node->keys;
    21882226        }
     
    21952233        size_t area_idx = 0;
    21962234       
    2197         list_foreach(as->as_area_btree.leaf_list, cur) {
    2198                 btree_node_t *node =
    2199                     list_get_instance(cur, btree_node_t, leaf_link);
     2235        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
     2236            node) {
    22002237                btree_key_t i;
    22012238               
     
    22312268       
    22322269        /* Print out info about address space areas */
    2233         list_foreach(as->as_area_btree.leaf_list, cur) {
    2234                 btree_node_t *node
    2235                     = list_get_instance(cur, btree_node_t, leaf_link);
     2270        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
     2271            node) {
    22362272                btree_key_t i;
    22372273               
Note: See TracChangeset for help on using the changeset viewer.