Changeset e3ee9b9 in mainline for kernel/generic/src/mm/as.c


Ignore:
Timestamp:
2010-07-02T12:44:00Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7a0359b, cefb126, e2ea4ab1
Parents:
b5382d4f
Message:

remove forward static function declarations and reorder functions
(if not needed for recursion, forward static function declaration only increases source code size and makes it much harder to instantly tell whether a function is actually static or not)

coding style changes
(no change in functionality)

File:
1 edited

Legend:

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

    rb5382d4f re3ee9b9  
    116116as_t *AS_KERNEL = NULL;
    117117
    118 static unsigned int area_flags_to_page_flags(unsigned int);
    119 static as_area_t *find_area_and_lock(as_t *, uintptr_t);
    120 static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *);
    121 static void sh_info_remove_reference(share_info_t *);
    122 
    123118static int as_constructor(void *obj, unsigned int flags)
    124119{
     
    296291        if (atomic_predec(&as->refcount) == 0)
    297292                as_destroy(as);
     293}
     294
     295/** Check area conflicts with other areas.
     296 *
     297 * @param as         Address space.
     298 * @param va         Starting virtual address of the area being tested.
     299 * @param size       Size of the area being tested.
     300 * @param avoid_area Do not touch this area.
     301 *
     302 * @return True if there is no conflict, false otherwise.
     303 *
     304 */
     305static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
     306    as_area_t *avoid_area)
     307{
     308        ASSERT(mutex_locked(&as->lock));
     309       
     310        /*
     311         * We don't want any area to have conflicts with NULL page.
     312         *
     313         */
     314        if (overlaps(va, size, NULL, PAGE_SIZE))
     315                return false;
     316       
     317        /*
     318         * The leaf node is found in O(log n), where n is proportional to
     319         * the number of address space areas belonging to as.
     320         * The check for conflicts is then attempted on the rightmost
     321         * record in the left neighbour, the leftmost record in the right
     322         * neighbour and all records in the leaf node itself.
     323         *
     324         */
     325        btree_node_t *leaf;
     326        as_area_t *area =
     327            (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     328        if (area) {
     329                if (area != avoid_area)
     330                        return false;
     331        }
     332       
     333        /* First, check the two border cases. */
     334        btree_node_t *node =
     335            btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     336        if (node) {
     337                area = (as_area_t *) node->value[node->keys - 1];
     338               
     339                mutex_lock(&area->lock);
     340               
     341                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     342                        mutex_unlock(&area->lock);
     343                        return false;
     344                }
     345               
     346                mutex_unlock(&area->lock);
     347        }
     348       
     349        node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
     350        if (node) {
     351                area = (as_area_t *) node->value[0];
     352               
     353                mutex_lock(&area->lock);
     354               
     355                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     356                        mutex_unlock(&area->lock);
     357                        return false;
     358                }
     359               
     360                mutex_unlock(&area->lock);
     361        }
     362       
     363        /* Second, check the leaf node. */
     364        btree_key_t i;
     365        for (i = 0; i < leaf->keys; i++) {
     366                area = (as_area_t *) leaf->value[i];
     367               
     368                if (area == avoid_area)
     369                        continue;
     370               
     371                mutex_lock(&area->lock);
     372               
     373                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     374                        mutex_unlock(&area->lock);
     375                        return false;
     376                }
     377               
     378                mutex_unlock(&area->lock);
     379        }
     380       
     381        /*
     382         * So far, the area does not conflict with other areas.
     383         * Check if it doesn't conflict with kernel address space.
     384         *
     385         */
     386        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
     387                return !overlaps(va, size,
     388                    KERNEL_ADDRESS_SPACE_START,
     389                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     390        }
     391       
     392        return true;
    298393}
    299394
     
    357452       
    358453        return area;
     454}
     455
     456/** Find address space area and lock it.
     457 *
     458 * @param as Address space.
     459 * @param va Virtual address.
     460 *
     461 * @return Locked address space area containing va on success or
     462 *         NULL on failure.
     463 *
     464 */
     465static as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
     466{
     467        ASSERT(mutex_locked(&as->lock));
     468       
     469        btree_node_t *leaf;
     470        as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     471        if (area) {
     472                /* va is the base address of an address space area */
     473                mutex_lock(&area->lock);
     474                return area;
     475        }
     476       
     477        /*
     478         * Search the leaf node and the righmost record of its left neighbour
     479         * to find out whether this is a miss or va belongs to an address
     480         * space area found there.
     481         *
     482         */
     483       
     484        /* First, search the leaf node itself. */
     485        btree_key_t i;
     486       
     487        for (i = 0; i < leaf->keys; i++) {
     488                area = (as_area_t *) leaf->value[i];
     489               
     490                mutex_lock(&area->lock);
     491               
     492                if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
     493                        return area;
     494               
     495                mutex_unlock(&area->lock);
     496        }
     497       
     498        /*
     499         * Second, locate the left neighbour and test its last record.
     500         * Because of its position in the B+tree, it must have base < va.
     501         *
     502         */
     503        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     504        if (lnode) {
     505                area = (as_area_t *) lnode->value[lnode->keys - 1];
     506               
     507                mutex_lock(&area->lock);
     508               
     509                if (va < area->base + area->pages * PAGE_SIZE)
     510                        return area;
     511               
     512                mutex_unlock(&area->lock);
     513        }
     514       
     515        return NULL;
    359516}
    360517
     
    553710}
    554711
     712/** Remove reference to address space area share info.
     713 *
     714 * If the reference count drops to 0, the sh_info is deallocated.
     715 *
     716 * @param sh_info Pointer to address space area share info.
     717 *
     718 */
     719static void sh_info_remove_reference(share_info_t *sh_info)
     720{
     721        bool dealloc = false;
     722       
     723        mutex_lock(&sh_info->lock);
     724        ASSERT(sh_info->refcount);
     725       
     726        if (--sh_info->refcount == 0) {
     727                dealloc = true;
     728                link_t *cur;
     729               
     730                /*
     731                 * Now walk carefully the pagemap B+tree and free/remove
     732                 * reference from all frames found there.
     733                 */
     734                for (cur = sh_info->pagemap.leaf_head.next;
     735                    cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
     736                        btree_node_t *node
     737                            = list_get_instance(cur, btree_node_t, leaf_link);
     738                        btree_key_t i;
     739                       
     740                        for (i = 0; i < node->keys; i++)
     741                                frame_free((uintptr_t) node->value[i]);
     742                }
     743               
     744        }
     745        mutex_unlock(&sh_info->lock);
     746       
     747        if (dealloc) {
     748                btree_destroy(&sh_info->pagemap);
     749                free(sh_info);
     750        }
     751}
     752
    555753/** Destroy address space area.
    556754 *
     
    8051003}
    8061004
     1005/** Convert address space area flags to page flags.
     1006 *
     1007 * @param aflags Flags of some address space area.
     1008 *
     1009 * @return Flags to be passed to page_mapping_insert().
     1010 *
     1011 */
     1012static unsigned int area_flags_to_page_flags(unsigned int aflags)
     1013{
     1014        unsigned int flags = PAGE_USER | PAGE_PRESENT;
     1015       
     1016        if (aflags & AS_AREA_READ)
     1017                flags |= PAGE_READ;
     1018               
     1019        if (aflags & AS_AREA_WRITE)
     1020                flags |= PAGE_WRITE;
     1021       
     1022        if (aflags & AS_AREA_EXEC)
     1023                flags |= PAGE_EXEC;
     1024       
     1025        if (aflags & AS_AREA_CACHEABLE)
     1026                flags |= PAGE_CACHEABLE;
     1027       
     1028        return flags;
     1029}
     1030
    8071031/** Change adress space area flags.
    8081032 *
     
    11611385}
    11621386
    1163 /** Convert address space area flags to page flags.
    1164  *
    1165  * @param aflags Flags of some address space area.
    1166  *
    1167  * @return Flags to be passed to page_mapping_insert().
    1168  *
    1169  */
    1170 unsigned int area_flags_to_page_flags(unsigned int aflags)
    1171 {
    1172         unsigned int flags = PAGE_USER | PAGE_PRESENT;
    1173        
    1174         if (aflags & AS_AREA_READ)
    1175                 flags |= PAGE_READ;
    1176                
    1177         if (aflags & AS_AREA_WRITE)
    1178                 flags |= PAGE_WRITE;
    1179        
    1180         if (aflags & AS_AREA_EXEC)
    1181                 flags |= PAGE_EXEC;
    1182        
    1183         if (aflags & AS_AREA_CACHEABLE)
    1184                 flags |= PAGE_CACHEABLE;
    1185        
    1186         return flags;
    1187 }
     1387
    11881388
    11891389/** Compute flags for virtual address translation subsytem.
     
    12721472/** Test whether page tables are locked.
    12731473 *
    1274  * @param as            Address space where the page tables belong.
    1275  *
    1276  * @return              True if the page tables belonging to the address soace
    1277  *                      are locked, otherwise false.
     1474 * @param as Address space where the page tables belong.
     1475 *
     1476 * @return True if the page tables belonging to the address soace
     1477 *         are locked, otherwise false.
    12781478 */
    12791479bool page_table_locked(as_t *as)
     
    12831483
    12841484        return as_operations->page_table_locked(as);
    1285 }
    1286 
    1287 
    1288 /** Find address space area and lock it.
    1289  *
    1290  * @param as Address space.
    1291  * @param va Virtual address.
    1292  *
    1293  * @return Locked address space area containing va on success or
    1294  *         NULL on failure.
    1295  *
    1296  */
    1297 as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
    1298 {
    1299         ASSERT(mutex_locked(&as->lock));
    1300 
    1301         btree_node_t *leaf;
    1302         as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    1303         if (area) {
    1304                 /* va is the base address of an address space area */
    1305                 mutex_lock(&area->lock);
    1306                 return area;
    1307         }
    1308        
    1309         /*
    1310          * Search the leaf node and the righmost record of its left neighbour
    1311          * to find out whether this is a miss or va belongs to an address
    1312          * space area found there.
    1313          *
    1314          */
    1315        
    1316         /* First, search the leaf node itself. */
    1317         btree_key_t i;
    1318        
    1319         for (i = 0; i < leaf->keys; i++) {
    1320                 area = (as_area_t *) leaf->value[i];
    1321                
    1322                 mutex_lock(&area->lock);
    1323                
    1324                 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
    1325                         return area;
    1326                
    1327                 mutex_unlock(&area->lock);
    1328         }
    1329        
    1330         /*
    1331          * Second, locate the left neighbour and test its last record.
    1332          * Because of its position in the B+tree, it must have base < va.
    1333          *
    1334          */
    1335         btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    1336         if (lnode) {
    1337                 area = (as_area_t *) lnode->value[lnode->keys - 1];
    1338                
    1339                 mutex_lock(&area->lock);
    1340                
    1341                 if (va < area->base + area->pages * PAGE_SIZE)
    1342                         return area;
    1343                
    1344                 mutex_unlock(&area->lock);
    1345         }
    1346        
    1347         return NULL;
    1348 }
    1349 
    1350 /** Check area conflicts with other areas.
    1351  *
    1352  * @param as         Address space.
    1353  * @param va         Starting virtual address of the area being tested.
    1354  * @param size       Size of the area being tested.
    1355  * @param avoid_area Do not touch this area.
    1356  *
    1357  * @return True if there is no conflict, false otherwise.
    1358  *
    1359  */
    1360 bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
    1361     as_area_t *avoid_area)
    1362 {
    1363         ASSERT(mutex_locked(&as->lock));
    1364 
    1365         /*
    1366          * We don't want any area to have conflicts with NULL page.
    1367          *
    1368          */
    1369         if (overlaps(va, size, NULL, PAGE_SIZE))
    1370                 return false;
    1371        
    1372         /*
    1373          * The leaf node is found in O(log n), where n is proportional to
    1374          * the number of address space areas belonging to as.
    1375          * The check for conflicts is then attempted on the rightmost
    1376          * record in the left neighbour, the leftmost record in the right
    1377          * neighbour and all records in the leaf node itself.
    1378          *
    1379          */
    1380         btree_node_t *leaf;
    1381         as_area_t *area =
    1382             (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    1383         if (area) {
    1384                 if (area != avoid_area)
    1385                         return false;
    1386         }
    1387        
    1388         /* First, check the two border cases. */
    1389         btree_node_t *node =
    1390             btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    1391         if (node) {
    1392                 area = (as_area_t *) node->value[node->keys - 1];
    1393                
    1394                 mutex_lock(&area->lock);
    1395                
    1396                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    1397                         mutex_unlock(&area->lock);
    1398                         return false;
    1399                 }
    1400                
    1401                 mutex_unlock(&area->lock);
    1402         }
    1403        
    1404         node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    1405         if (node) {
    1406                 area = (as_area_t *) node->value[0];
    1407                
    1408                 mutex_lock(&area->lock);
    1409                
    1410                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    1411                         mutex_unlock(&area->lock);
    1412                         return false;
    1413                 }
    1414                
    1415                 mutex_unlock(&area->lock);
    1416         }
    1417        
    1418         /* Second, check the leaf node. */
    1419         btree_key_t i;
    1420         for (i = 0; i < leaf->keys; i++) {
    1421                 area = (as_area_t *) leaf->value[i];
    1422                
    1423                 if (area == avoid_area)
    1424                         continue;
    1425                
    1426                 mutex_lock(&area->lock);
    1427                
    1428                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    1429                         mutex_unlock(&area->lock);
    1430                         return false;
    1431                 }
    1432                
    1433                 mutex_unlock(&area->lock);
    1434         }
    1435        
    1436         /*
    1437          * So far, the area does not conflict with other areas.
    1438          * Check if it doesn't conflict with kernel address space.
    1439          *
    1440          */
    1441         if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    1442                 return !overlaps(va, size,
    1443                     KERNEL_ADDRESS_SPACE_START,
    1444                     KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    1445         }
    1446        
    1447         return true;
    14481485}
    14491486
     
    19601997}
    19611998
    1962 /** Remove reference to address space area share info.
    1963  *
    1964  * If the reference count drops to 0, the sh_info is deallocated.
    1965  *
    1966  * @param sh_info Pointer to address space area share info.
    1967  *
    1968  */
    1969 void sh_info_remove_reference(share_info_t *sh_info)
    1970 {
    1971         bool dealloc = false;
    1972        
    1973         mutex_lock(&sh_info->lock);
    1974         ASSERT(sh_info->refcount);
    1975        
    1976         if (--sh_info->refcount == 0) {
    1977                 dealloc = true;
    1978                 link_t *cur;
    1979                
    1980                 /*
    1981                  * Now walk carefully the pagemap B+tree and free/remove
    1982                  * reference from all frames found there.
    1983                  */
    1984                 for (cur = sh_info->pagemap.leaf_head.next;
    1985                     cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
    1986                         btree_node_t *node
    1987                             = list_get_instance(cur, btree_node_t, leaf_link);
    1988                         btree_key_t i;
    1989                        
    1990                         for (i = 0; i < node->keys; i++)
    1991                                 frame_free((uintptr_t) node->value[i]);
    1992                 }
    1993                
    1994         }
    1995         mutex_unlock(&sh_info->lock);
    1996        
    1997         if (dealloc) {
    1998                 btree_destroy(&sh_info->pagemap);
    1999                 free(sh_info);
    2000         }
    2001 }
    2002 
    20031999/*
    20042000 * Address space related syscalls.
Note: See TracChangeset for help on using the changeset viewer.