Ignore:
File:
1 edited

Legend:

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

    rf72906c radb252c0  
    6060#include <config.h>
    6161#include <str.h>
     62
     63#define BITMAP_BLOCK_SIZE  1024
    6264
    6365zones_t zones;
     
    234236         * the bitmap if the last argument is NULL.
    235237         */
    236        
    237238        return ((zone->flags & ZONE_AVAILABLE) &&
    238239            bitmap_allocate_range(&zone->bitmap, count, zone->base,
    239             FRAME_LOWPRIO, constraint, NULL));
    240 }
    241 
    242 /** Find a zone that can allocate specified number of frames
    243  *
    244  * This function searches among all zones. Assume interrupts are
    245  * disabled and zones lock is locked.
    246  *
    247  * @param count      Number of free frames we are trying to find.
    248  * @param flags      Required flags of the zone.
    249  * @param constraint Indication of bits that cannot be set in the
    250  *                   physical frame number of the first allocated frame.
    251  * @param hint       Preferred zone.
    252  *
    253  * @return Zone that can allocate specified number of frames.
    254  * @return -1 if no zone can satisfy the request.
    255  *
    256  */
    257 NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags,
    258     pfn_t constraint, size_t hint)
    259 {
    260         for (size_t pos = 0; pos < zones.count; pos++) {
    261                 size_t i = (pos + hint) % zones.count;
    262                
    263                 /* Check whether the zone meets the search criteria. */
    264                 if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
    265                         continue;
    266                
    267                 /* Check if the zone can satisfy the allocation request. */
    268                 if (zone_can_alloc(&zones.info[i], count, constraint))
    269                         return i;
    270         }
    271        
    272         return (size_t) -1;
    273 }
    274 
    275 /** Check if frame range  priority memory
    276  *
    277  * @param pfn   Starting frame.
    278  * @param count Number of frames.
    279  *
    280  * @return True if the range contains only priority memory.
    281  *
    282  */
    283 NO_TRACE static bool is_high_priority(pfn_t base, size_t count)
    284 {
    285         return (base + count <= FRAME_LOWPRIO);
    286 }
    287 
    288 /** Find a zone that can allocate specified number of frames
    289  *
    290  * This function ignores zones that contain only high-priority
    291  * memory. Assume interrupts are disabled and zones lock is locked.
    292  *
    293  * @param count      Number of free frames we are trying to find.
    294  * @param flags      Required flags of the zone.
    295  * @param constraint Indication of bits that cannot be set in the
    296  *                   physical frame number of the first allocated frame.
    297  * @param hint       Preferred zone.
    298  *
    299  * @return Zone that can allocate specified number of frames.
    300  * @return -1 if no low-priority zone can satisfy the request.
    301  *
    302  */
    303 NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags,
    304     pfn_t constraint, size_t hint)
    305 {       
    306         for (size_t pos = 0; pos < zones.count; pos++) {
    307                 size_t i = (pos + hint) % zones.count;
    308                
    309                 /* Skip zones containing only high-priority memory. */
    310                 if (is_high_priority(zones.info[i].base, zones.info[i].count))
    311                         continue;
    312                
    313                 /* Check whether the zone meets the search criteria. */
    314                 if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
    315                         continue;
    316                
    317                 /* Check if the zone can satisfy the allocation request. */
    318                 if (zone_can_alloc(&zones.info[i], count, constraint))
    319                         return i;
    320         }
    321        
    322         return (size_t) -1;
     240            constraint, NULL));
    323241}
    324242
     
    332250 * @param constraint Indication of bits that cannot be set in the
    333251 *                   physical frame number of the first allocated frame.
    334  * @param hint       Preferred zone.
    335  *
    336  * @return Zone that can allocate specified number of frames.
    337  * @return -1 if no zone can satisfy the request.
     252 * @param hind       Preferred zone.
    338253 *
    339254 */
     
    344259                hint = 0;
    345260       
    346         /*
    347          * Prefer zones with low-priority memory over
    348          * zones with high-priority memory.
    349          */
    350        
    351         size_t znum = find_free_zone_lowprio(count, flags, constraint, hint);
    352         if (znum != (size_t) -1)
    353                 return znum;
    354        
    355         /* Take all zones into account */
    356         return find_free_zone_all(count, flags, constraint, hint);
     261        size_t i = hint;
     262        do {
     263                /*
     264                 * Check whether the zone meets the search criteria.
     265                 */
     266                if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
     267                        /*
     268                         * Check if the zone can satisfy the allocation request.
     269                         */
     270                        if (zone_can_alloc(&zones.info[i], count, constraint))
     271                                return i;
     272                }
     273               
     274                i++;
     275                if (i >= zones.count)
     276                        i = 0;
     277               
     278        } while (i != hint);
     279       
     280        return (size_t) -1;
    357281}
    358282
     
    390314        size_t index;
    391315        int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
    392             FRAME_LOWPRIO, constraint, &index);
     316            constraint, &index);
    393317       
    394318        ASSERT(avail);
     
    428352       
    429353        if (!--frame->refcount) {
    430                 bitmap_set(&zone->bitmap, index, 0);
     354                bitmap_free_range(&zone->bitmap, index, 1);
    431355               
    432356                /* Update zone information. */
     
    486410       
    487411        bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count,
    488             confdata + (sizeof(frame_t) * zones.info[z1].count));
     412            BITMAP_BLOCK_SIZE, confdata +
     413            (sizeof(frame_t) * zones.info[z1].count));
    489414        bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count);
    490415       
     
    653578                 */
    654579               
    655                 bitmap_initialize(&zone->bitmap, count, confdata +
    656                     (sizeof(frame_t) * count));
     580                bitmap_initialize(&zone->bitmap, count, BITMAP_BLOCK_SIZE,
     581                    confdata + (sizeof(frame_t) * count));
    657582                bitmap_clear_range(&zone->bitmap, 0, count);
    658583               
     
    666591                        frame_initialize(&zone->frames[i]);
    667592        } else {
    668                 bitmap_initialize(&zone->bitmap, 0, NULL);
     593                bitmap_initialize(&zone->bitmap, 0, 0, NULL);
    669594                zone->frames = NULL;
    670595        }
     
    680605size_t zone_conf_size(size_t count)
    681606{
    682         return (count * sizeof(frame_t) + bitmap_size(count));
     607        return (count * sizeof(frame_t) +
     608            bitmap_size(count, BITMAP_BLOCK_SIZE));
    683609}
    684610
     
    961887}
    962888
     889uintptr_t frame_alloc_noreserve(size_t count, frame_flags_t flags,
     890    uintptr_t constraint)
     891{
     892        return frame_alloc_generic(count, flags | FRAME_NO_RESERVE, constraint,
     893            NULL);
     894}
     895
    963896/** Free frames of physical memory.
    964897 *
     
    12081141        /*
    12091142         * Because printing may require allocation of memory, we may not hold
    1210          * the frame allocator locks when printing zone statistics. Therefore,
     1143         * the frame allocator locks when printing zone statistics.  Therefore,
    12111144         * we simply gather the statistics under the protection of the locks and
    12121145         * print the statistics when the locks have been released.
     
    12171150         */
    12181151       
    1219         size_t free_lowmem = 0;
    1220         size_t free_highmem = 0;
    1221         size_t free_highprio = 0;
    1222        
    12231152        for (size_t i = 0;; i++) {
    12241153                irq_spinlock_lock(&zones.lock, true);
     
    12291158                }
    12301159               
    1231                 pfn_t fbase = zones.info[i].base;
    1232                 uintptr_t base = PFN2ADDR(fbase);
     1160                uintptr_t base = PFN2ADDR(zones.info[i].base);
    12331161                size_t count = zones.info[i].count;
    12341162                zone_flags_t flags = zones.info[i].flags;
     
    12361164                size_t busy_count = zones.info[i].busy_count;
    12371165               
     1166                irq_spinlock_unlock(&zones.lock, true);
     1167               
    12381168                bool available = ((flags & ZONE_AVAILABLE) != 0);
    1239                 bool lowmem = ((flags & ZONE_LOWMEM) != 0);
    1240                 bool highmem = ((flags & ZONE_HIGHMEM) != 0);
    1241                 bool highprio = is_high_priority(fbase, count);
    1242                
    1243                 if (available) {
    1244                         if (lowmem)
    1245                                 free_lowmem += free_count;
    1246                        
    1247                         if (highmem)
    1248                                 free_highmem += free_count;
    1249                        
    1250                         if (highprio) {
    1251                                 free_highprio += free_count;
    1252                         } else {
    1253                                 /*
    1254                                  * Walk all frames of the zone and examine
    1255                                  * all high priority memory to get accurate
    1256                                  * statistics.
    1257                                  */
    1258                                
    1259                                 for (size_t index = 0; index < count; index++) {
    1260                                         if (is_high_priority(fbase + index, 0)) {
    1261                                                 if (!bitmap_get(&zones.info[i].bitmap, index))
    1262                                                         free_highprio++;
    1263                                         } else
    1264                                                 break;
    1265                                 }
    1266                         }
    1267                 }
    1268                
    1269                 irq_spinlock_unlock(&zones.lock, true);
    12701169               
    12711170                printf("%-4zu", i);
     
    12921191                printf("\n");
    12931192        }
    1294        
    1295         printf("\n");
    1296        
    1297         uint64_t size;
    1298         const char *size_suffix;
    1299        
    1300         bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
    1301             false);
    1302         printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
    1303             free_lowmem, size, size_suffix);
    1304        
    1305         bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
    1306             false);
    1307         printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
    1308             free_highmem, size, size_suffix);
    1309        
    1310         bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
    1311             false);
    1312         printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
    1313             free_highprio, size, size_suffix);
    13141193}
    13151194
     
    13371216        }
    13381217       
    1339         size_t free_lowmem = 0;
    1340         size_t free_highmem = 0;
    1341         size_t free_highprio = 0;
    1342        
    1343         pfn_t fbase = zones.info[znum].base;
    1344         uintptr_t base = PFN2ADDR(fbase);
     1218        uintptr_t base = PFN2ADDR(zones.info[znum].base);
    13451219        zone_flags_t flags = zones.info[znum].flags;
    13461220        size_t count = zones.info[znum].count;
     
    13481222        size_t busy_count = zones.info[znum].busy_count;
    13491223       
     1224        irq_spinlock_unlock(&zones.lock, true);
     1225       
    13501226        bool available = ((flags & ZONE_AVAILABLE) != 0);
    1351         bool lowmem = ((flags & ZONE_LOWMEM) != 0);
    1352         bool highmem = ((flags & ZONE_HIGHMEM) != 0);
    1353         bool highprio = is_high_priority(fbase, count);
    1354        
    1355         if (available) {
    1356                 if (lowmem)
    1357                         free_lowmem = free_count;
    1358                
    1359                 if (highmem)
    1360                         free_highmem = free_count;
    1361                
    1362                 if (highprio) {
    1363                         free_highprio = free_count;
    1364                 } else {
    1365                         /*
    1366                          * Walk all frames of the zone and examine
    1367                          * all high priority memory to get accurate
    1368                          * statistics.
    1369                          */
    1370                        
    1371                         for (size_t index = 0; index < count; index++) {
    1372                                 if (is_high_priority(fbase + index, 0)) {
    1373                                         if (!bitmap_get(&zones.info[znum].bitmap, index))
    1374                                                 free_highprio++;
    1375                                 } else
    1376                                         break;
    1377                         }
    1378                 }
    1379         }
    1380        
    1381         irq_spinlock_unlock(&zones.lock, true);
    13821227       
    13831228        uint64_t size;
    13841229        const char *size_suffix;
    1385        
    13861230        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
    13871231       
    1388         printf("Zone number:             %zu\n", znum);
    1389         printf("Zone base address:       %p\n", (void *) base);
    1390         printf("Zone size:               %zu frames (%" PRIu64 " %s)\n", count,
     1232        printf("Zone number:       %zu\n", znum);
     1233        printf("Zone base address: %p\n", (void *) base);
     1234        printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
    13911235            size, size_suffix);
    1392         printf("Zone flags:              %c%c%c%c%c\n",
     1236        printf("Zone flags:        %c%c%c%c%c\n",
    13931237            available ? 'A' : '-',
    13941238            (flags & ZONE_RESERVED) ? 'R' : '-',
     
    14001244                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
    14011245                    false);
    1402                 printf("Allocated space:         %zu frames (%" PRIu64 " %s)\n",
     1246                printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
    14031247                    busy_count, size, size_suffix);
    1404                
    14051248                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
    14061249                    false);
    1407                 printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
     1250                printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
    14081251                    free_count, size, size_suffix);
    1409                
    1410                 bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
    1411                     false);
    1412                 printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
    1413                     free_lowmem, size, size_suffix);
    1414                
    1415                 bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
    1416                     false);
    1417                 printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
    1418                     free_highmem, size, size_suffix);
    1419                
    1420                 bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
    1421                     false);
    1422                 printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
    1423                     free_highprio, size, size_suffix);
    14241252        }
    14251253}
Note: See TracChangeset for help on using the changeset viewer.