Ignore:
File:
1 edited

Legend:

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

    rc12f891 r905721b  
    3838 *
    3939 * This file contains the physical frame allocator and memory zone management.
    40  * The frame allocator is built on top of the two-level bitmap structure.
    41  *
     40 * The frame allocator is built on top of the buddy allocator.
     41 *
     42 * @see buddy.c
    4243 */
    4344
     
    5455#include <arch.h>
    5556#include <print.h>
    56 #include <log.h>
    5757#include <align.h>
    5858#include <mm/slab.h>
     
    6161#include <config.h>
    6262#include <str.h>
    63 #include <proc/thread.h> /* THREAD */
    6463
    6564zones_t zones;
     
    7473static size_t mem_avail_gen = 0;  /**< Generation counter. */
    7574
     75/********************/
     76/* Helper functions */
     77/********************/
     78
     79NO_TRACE static inline size_t frame_index(zone_t *zone, frame_t *frame)
     80{
     81        return (size_t) (frame - zone->frames);
     82}
     83
     84NO_TRACE static inline size_t frame_index_abs(zone_t *zone, frame_t *frame)
     85{
     86        return (size_t) (frame - zone->frames) + zone->base;
     87}
     88
     89NO_TRACE static inline bool frame_index_valid(zone_t *zone, size_t index)
     90{
     91        return (index < zone->count);
     92}
     93
     94NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
     95{
     96        return (frame - zone->frames);
     97}
     98
    7699/** Initialize frame structure.
    77100 *
     
    81104NO_TRACE static void frame_initialize(frame_t *frame)
    82105{
    83         frame->refcount = 0;
    84         frame->parent = NULL;
     106        frame->refcount = 1;
     107        frame->buddy_order = 0;
    85108}
    86109
     
    104127{
    105128        if (zones.count + 1 == ZONES_MAX) {
    106                 log(LF_OTHER, LVL_ERROR, "Maximum zone count %u exceeded!",
    107                     ZONES_MAX);
     129                printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
    108130                return (size_t) -1;
    109131        }
     
    125147                            (!iswithin(zones.info[i].base, zones.info[i].count,
    126148                            base, count))) {
    127                                 log(LF_OTHER, LVL_WARN,
    128                                     "Zone (%p, %p) overlaps "
    129                                     "with previous zone (%p %p)!",
     149                                printf("Zone (%p, %p) overlaps "
     150                                    "with previous zone (%p %p)!\n",
    130151                                    (void *) PFN2ADDR(base), (void *) PFN2ADDR(count),
    131152                                    (void *) PFN2ADDR(zones.info[i].base),
     
    140161       
    141162        /* Move other zones up */
    142         for (size_t j = zones.count; j > i; j--)
     163        size_t j;
     164        for (j = zones.count; j > i; j--) {
    143165                zones.info[j] = zones.info[j - 1];
     166                if (zones.info[j].buddy_system != NULL)
     167                        zones.info[j].buddy_system->data =
     168                            (void *) &zones.info[j];
     169        }
    144170       
    145171        zones.count++;
     
    211237}
    212238
    213 /** @return True if zone can allocate specified number of frames */
    214 NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count,
    215     pfn_t constraint)
    216 {
    217         /*
    218          * The function bitmap_allocate_range() does not modify
    219          * the bitmap if the last argument is NULL.
    220          */
    221        
     239/** @return True if zone can allocate specified order */
     240NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order)
     241{
    222242        return ((zone->flags & ZONE_AVAILABLE) &&
    223             bitmap_allocate_range(&zone->bitmap, count, zone->base,
    224             FRAME_LOWPRIO, constraint, NULL));
    225 }
    226 
    227 /** Find a zone that can allocate specified number of frames
    228  *
    229  * This function searches among all zones. Assume interrupts are
    230  * disabled and zones lock is locked.
    231  *
    232  * @param count      Number of free frames we are trying to find.
    233  * @param flags      Required flags of the zone.
    234  * @param constraint Indication of bits that cannot be set in the
    235  *                   physical frame number of the first allocated frame.
    236  * @param hint       Preferred zone.
    237  *
    238  * @return Zone that can allocate specified number of frames.
    239  * @return -1 if no zone can satisfy the request.
    240  *
    241  */
    242 NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags,
    243     pfn_t constraint, size_t hint)
    244 {
    245         for (size_t pos = 0; pos < zones.count; pos++) {
    246                 size_t i = (pos + hint) % zones.count;
    247                
    248                 /* Check whether the zone meets the search criteria. */
    249                 if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
    250                         continue;
    251                
    252                 /* Check if the zone can satisfy the allocation request. */
    253                 if (zone_can_alloc(&zones.info[i], count, constraint))
    254                         return i;
    255         }
    256        
    257         return (size_t) -1;
    258 }
    259 
    260 /** Check if frame range  priority memory
    261  *
    262  * @param pfn   Starting frame.
    263  * @param count Number of frames.
    264  *
    265  * @return True if the range contains only priority memory.
    266  *
    267  */
    268 NO_TRACE static bool is_high_priority(pfn_t base, size_t count)
    269 {
    270         return (base + count <= FRAME_LOWPRIO);
    271 }
    272 
    273 /** Find a zone that can allocate specified number of frames
    274  *
    275  * This function ignores zones that contain only high-priority
    276  * memory. Assume interrupts are disabled and zones lock is locked.
    277  *
    278  * @param count      Number of free frames we are trying to find.
    279  * @param flags      Required flags of the zone.
    280  * @param constraint Indication of bits that cannot be set in the
    281  *                   physical frame number of the first allocated frame.
    282  * @param hint       Preferred zone.
    283  *
    284  * @return Zone that can allocate specified number of frames.
    285  * @return -1 if no low-priority zone can satisfy the request.
    286  *
    287  */
    288 NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags,
    289     pfn_t constraint, size_t hint)
    290 {       
    291         for (size_t pos = 0; pos < zones.count; pos++) {
    292                 size_t i = (pos + hint) % zones.count;
    293                
    294                 /* Skip zones containing only high-priority memory. */
    295                 if (is_high_priority(zones.info[i].base, zones.info[i].count))
    296                         continue;
    297                
    298                 /* Check whether the zone meets the search criteria. */
    299                 if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
    300                         continue;
    301                
    302                 /* Check if the zone can satisfy the allocation request. */
    303                 if (zone_can_alloc(&zones.info[i], count, constraint))
    304                         return i;
    305         }
    306        
    307         return (size_t) -1;
    308 }
    309 
    310 /** Find a zone that can allocate specified number of frames
     243            buddy_system_can_alloc(zone->buddy_system, order));
     244}
     245
     246/** Find a zone that can allocate order frames.
    311247 *
    312248 * Assume interrupts are disabled and zones lock is
    313249 * locked.
    314250 *
    315  * @param count      Number of free frames we are trying to find.
    316  * @param flags      Required flags of the target zone.
    317  * @param constraint Indication of bits that cannot be set in the
    318  *                   physical frame number of the first allocated frame.
    319  * @param hint       Preferred zone.
    320  *
    321  * @return Zone that can allocate specified number of frames.
    322  * @return -1 if no zone can satisfy the request.
    323  *
    324  */
    325 NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags,
    326     pfn_t constraint, size_t hint)
     251 * @param order Size (2^order) of free space we are trying to find.
     252 * @param flags Required flags of the target zone.
     253 * @param hind  Preferred zone.
     254 *
     255 */
     256NO_TRACE static size_t find_free_zone(uint8_t order, zone_flags_t flags,
     257    size_t hint)
    327258{
    328259        if (hint >= zones.count)
    329260                hint = 0;
    330261       
    331         /*
    332          * Prefer zones with low-priority memory over
    333          * zones with high-priority memory.
    334          */
    335        
    336         size_t znum = find_free_zone_lowprio(count, flags, constraint, hint);
    337         if (znum != (size_t) -1)
    338                 return znum;
    339        
    340         /* Take all zones into account */
    341         return find_free_zone_all(count, flags, constraint, hint);
    342 }
     262        size_t i = hint;
     263        do {
     264                /*
     265                 * Check whether the zone meets the search criteria.
     266                 */
     267                if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
     268                        /*
     269                         * Check if the zone has 2^order frames area available.
     270                         */
     271                        if (zone_can_alloc(&zones.info[i], order))
     272                                return i;
     273                }
     274               
     275                i++;
     276                if (i >= zones.count)
     277                        i = 0;
     278               
     279        } while (i != hint);
     280       
     281        return (size_t) -1;
     282}
     283
     284/**************************/
     285/* Buddy system functions */
     286/**************************/
     287
     288/** Buddy system find_block implementation.
     289 *
     290 * Find block that is parent of current list.
     291 * That means go to lower addresses, until such block is found
     292 *
     293 * @param order Order of parent must be different then this
     294 *              parameter!!
     295 *
     296 */
     297NO_TRACE static link_t *zone_buddy_find_block(buddy_system_t *buddy,
     298    link_t *child, uint8_t order)
     299{
     300        frame_t *frame = list_get_instance(child, frame_t, buddy_link);
     301        zone_t *zone = (zone_t *) buddy->data;
     302       
     303        size_t index = frame_index(zone, frame);
     304        do {
     305                if (zone->frames[index].buddy_order != order)
     306                        return &zone->frames[index].buddy_link;
     307        } while (index-- > 0);
     308       
     309        return NULL;
     310}
     311
     312/** Buddy system find_buddy implementation.
     313 *
     314 * @param buddy Buddy system.
     315 * @param block Block for which buddy should be found.
     316 *
     317 * @return Buddy for given block if found.
     318 *
     319 */
     320NO_TRACE static link_t *zone_buddy_find_buddy(buddy_system_t *buddy,
     321    link_t *block)
     322{
     323        frame_t *frame = list_get_instance(block, frame_t, buddy_link);
     324        zone_t *zone = (zone_t *) buddy->data;
     325        ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
     326            frame->buddy_order));
     327       
     328        bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
     329       
     330        size_t index;
     331        if (is_left) {
     332                index = (frame_index(zone, frame)) +
     333                    (1 << frame->buddy_order);
     334        } else {  /* is_right */
     335                index = (frame_index(zone, frame)) -
     336                    (1 << frame->buddy_order);
     337        }
     338       
     339        if (frame_index_valid(zone, index)) {
     340                if ((zone->frames[index].buddy_order == frame->buddy_order) &&
     341                    (zone->frames[index].refcount == 0)) {
     342                        return &zone->frames[index].buddy_link;
     343                }
     344        }
     345       
     346        return NULL;
     347}
     348
     349/** Buddy system bisect implementation.
     350 *
     351 * @param buddy Buddy system.
     352 * @param block Block to bisect.
     353 *
     354 * @return Right block.
     355 *
     356 */
     357NO_TRACE static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block)
     358{
     359        frame_t *frame_l = list_get_instance(block, frame_t, buddy_link);
     360        frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
     361       
     362        return &frame_r->buddy_link;
     363}
     364
     365/** Buddy system coalesce implementation.
     366 *
     367 * @param buddy   Buddy system.
     368 * @param block_1 First block.
     369 * @param block_2 First block's buddy.
     370 *
     371 * @return Coalesced block (actually block that represents lower
     372 *         address).
     373 *
     374 */
     375NO_TRACE static link_t *zone_buddy_coalesce(buddy_system_t *buddy,
     376    link_t *block_1, link_t *block_2)
     377{
     378        frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link);
     379        frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link);
     380       
     381        return ((frame1 < frame2) ? block_1 : block_2);
     382}
     383
     384/** Buddy system set_order implementation.
     385 *
     386 * @param buddy Buddy system.
     387 * @param block Buddy system block.
     388 * @param order Order to set.
     389 *
     390 */
     391NO_TRACE static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
     392    uint8_t order)
     393{
     394        list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
     395}
     396
     397/** Buddy system get_order implementation.
     398 *
     399 * @param buddy Buddy system.
     400 * @param block Buddy system block.
     401 *
     402 * @return Order of block.
     403 *
     404 */
     405NO_TRACE static uint8_t zone_buddy_get_order(buddy_system_t *buddy,
     406    link_t *block)
     407{
     408        return list_get_instance(block, frame_t, buddy_link)->buddy_order;
     409}
     410
     411/** Buddy system mark_busy implementation.
     412 *
     413 * @param buddy Buddy system.
     414 * @param block Buddy system block.
     415 *
     416 */
     417NO_TRACE static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t *block)
     418{
     419        list_get_instance(block, frame_t, buddy_link)->refcount = 1;
     420}
     421
     422/** Buddy system mark_available implementation.
     423 *
     424 * @param buddy Buddy system.
     425 * @param block Buddy system block.
     426 *
     427 */
     428NO_TRACE static void zone_buddy_mark_available(buddy_system_t *buddy,
     429    link_t *block)
     430{
     431        list_get_instance(block, frame_t, buddy_link)->refcount = 0;
     432}
     433
     434static buddy_system_operations_t zone_buddy_system_operations = {
     435        .find_buddy = zone_buddy_find_buddy,
     436        .bisect = zone_buddy_bisect,
     437        .coalesce = zone_buddy_coalesce,
     438        .set_order = zone_buddy_set_order,
     439        .get_order = zone_buddy_get_order,
     440        .mark_busy = zone_buddy_mark_busy,
     441        .mark_available = zone_buddy_mark_available,
     442        .find_block = zone_buddy_find_block
     443};
    343444
    344445/******************/
     
    346447/******************/
    347448
    348 /** Return frame from zone. */
    349 NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index)
    350 {
    351         ASSERT(index < zone->count);
    352        
    353         return &zone->frames[index];
    354 }
    355 
    356449/** Allocate frame in particular zone.
    357450 *
     
    359452 * Panics if allocation is impossible.
    360453 *
    361  * @param zone       Zone to allocate from.
    362  * @param count      Number of frames to allocate
    363  * @param constraint Indication of bits that cannot be set in the
    364  *                   physical frame number of the first allocated frame.
     454 * @param zone  Zone to allocate from.
     455 * @param order Allocate exactly 2^order frames.
    365456 *
    366457 * @return Frame index in zone.
    367458 *
    368459 */
    369 NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count,
    370     pfn_t constraint)
     460NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
    371461{
    372462        ASSERT(zone->flags & ZONE_AVAILABLE);
    373463       
    374         /* Allocate frames from zone */
    375         size_t index = (size_t) -1;
    376         int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
    377             FRAME_LOWPRIO, constraint, &index);
    378        
    379         ASSERT(avail);
    380         ASSERT(index != (size_t) -1);
    381        
    382         /* Update frame reference count */
    383         for (size_t i = 0; i < count; i++) {
    384                 frame_t *frame = zone_get_frame(zone, index + i);
    385                
    386                 ASSERT(frame->refcount == 0);
    387                 frame->refcount = 1;
    388         }
     464        /* Allocate frames from zone buddy system */
     465        link_t *link = buddy_system_alloc(zone->buddy_system, order);
     466       
     467        ASSERT(link);
    389468       
    390469        /* Update zone information. */
    391         zone->free_count -= count;
    392         zone->busy_count += count;
    393        
    394         return index;
     470        zone->free_count -= (1 << order);
     471        zone->busy_count += (1 << order);
     472       
     473        /* Frame will be actually a first frame of the block. */
     474        frame_t *frame = list_get_instance(link, frame_t, buddy_link);
     475       
     476        /* Get frame address */
     477        return make_frame_index(zone, frame);
    395478}
    396479
     
    399482 * Assume zone is locked and is available for deallocation.
    400483 *
    401  * @param zone  Pointer to zone from which the frame is to be freed.
    402  * @param index Frame index relative to zone.
    403  *
    404  * @return Number of freed frames.
    405  *
    406  */
    407 NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)
     484 * @param zone      Pointer to zone from which the frame is to be freed.
     485 * @param frame_idx Frame index relative to zone.
     486 *
     487 * @return          Number of freed frames.
     488 *
     489 */
     490NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
    408491{
    409492        ASSERT(zone->flags & ZONE_AVAILABLE);
    410493       
    411         frame_t *frame = zone_get_frame(zone, index);
    412        
    413         ASSERT(frame->refcount > 0);
     494        frame_t *frame = &zone->frames[frame_idx];
     495        size_t size = 0;
     496       
     497        ASSERT(frame->refcount);
    414498       
    415499        if (!--frame->refcount) {
    416                 bitmap_set(&zone->bitmap, index, 0);
    417                
     500                size = 1 << frame->buddy_order;
     501                buddy_system_free(zone->buddy_system, &frame->buddy_link);             
    418502                /* Update zone information. */
    419                 zone->free_count++;
    420                 zone->busy_count--;
    421                
    422                 return 1;
    423         }
    424        
    425         return 0;
     503                zone->free_count += size;
     504                zone->busy_count -= size;
     505        }
     506       
     507        return size;
     508}
     509
     510/** Return frame from zone. */
     511NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx)
     512{
     513        ASSERT(frame_idx < zone->count);
     514        return &zone->frames[frame_idx];
    426515}
    427516
    428517/** Mark frame in zone unavailable to allocation. */
    429 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
     518NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
    430519{
    431520        ASSERT(zone->flags & ZONE_AVAILABLE);
    432521       
    433         frame_t *frame = zone_get_frame(zone, index);
    434         if (frame->refcount > 0)
     522        frame_t *frame = zone_get_frame(zone, frame_idx);
     523        if (frame->refcount)
    435524                return;
    436525       
    437         frame->refcount = 1;
    438         bitmap_set_range(&zone->bitmap, index, 1);
    439        
     526        link_t *link __attribute__ ((unused));
     527       
     528        link = buddy_system_alloc_block(zone->buddy_system,
     529            &frame->buddy_link);
     530       
     531        ASSERT(link);
    440532        zone->free_count--;
    441533        reserve_force_alloc(1);
     
    444536/** Merge two zones.
    445537 *
     538 * Expect buddy to point to space at least zone_conf_size large.
    446539 * Assume z1 & z2 are locked and compatible and zones lock is
    447540 * locked.
    448541 *
    449  * @param z1       First zone to merge.
    450  * @param z2       Second zone to merge.
    451  * @param old_z1   Original data of the first zone.
    452  * @param confdata Merged zone configuration data.
     542 * @param z1     First zone to merge.
     543 * @param z2     Second zone to merge.
     544 * @param old_z1 Original date of the first zone.
     545 * @param buddy  Merged zone buddy.
    453546 *
    454547 */
    455548NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1,
    456     void *confdata)
     549    buddy_system_t *buddy)
    457550{
    458551        ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
     
    469562        zones.info[z1].free_count += zones.info[z2].free_count;
    470563        zones.info[z1].busy_count += zones.info[z2].busy_count;
    471        
    472         bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count,
    473             confdata + (sizeof(frame_t) * zones.info[z1].count));
    474         bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count);
    475        
    476         zones.info[z1].frames = (frame_t *) confdata;
    477        
    478         /*
    479          * Copy frames and bits from both zones to preserve parents, etc.
     564        zones.info[z1].buddy_system = buddy;
     565       
     566        uint8_t order = fnzb(zones.info[z1].count);
     567        buddy_system_create(zones.info[z1].buddy_system, order,
     568            &zone_buddy_system_operations, (void *) &zones.info[z1]);
     569       
     570        zones.info[z1].frames =
     571            (frame_t *) ((uint8_t *) zones.info[z1].buddy_system
     572            + buddy_conf_size(order));
     573       
     574        /* This marks all frames busy */
     575        size_t i;
     576        for (i = 0; i < zones.info[z1].count; i++)
     577                frame_initialize(&zones.info[z1].frames[i]);
     578       
     579        /* Copy frames from both zones to preserve full frame orders,
     580         * parents etc. Set all free frames with refcount = 0 to 1, because
     581         * we add all free frames to buddy allocator later again, clearing
     582         * order to 0. Don't set busy frames with refcount = 0, as they
     583         * will not be reallocated during merge and it would make later
     584         * problems with allocation/free.
    480585         */
    481        
    482         for (size_t i = 0; i < old_z1->count; i++) {
    483                 bitmap_set(&zones.info[z1].bitmap, i,
    484                     bitmap_get(&old_z1->bitmap, i));
     586        for (i = 0; i < old_z1->count; i++)
    485587                zones.info[z1].frames[i] = old_z1->frames[i];
    486         }
    487        
    488         for (size_t i = 0; i < zones.info[z2].count; i++) {
    489                 bitmap_set(&zones.info[z1].bitmap, base_diff + i,
    490                     bitmap_get(&zones.info[z2].bitmap, i));
    491                 zones.info[z1].frames[base_diff + i] =
    492                     zones.info[z2].frames[i];
     588       
     589        for (i = 0; i < zones.info[z2].count; i++)
     590                zones.info[z1].frames[base_diff + i]
     591                    = zones.info[z2].frames[i];
     592       
     593        i = 0;
     594        while (i < zones.info[z1].count) {
     595                if (zones.info[z1].frames[i].refcount) {
     596                        /* Skip busy frames */
     597                        i += 1 << zones.info[z1].frames[i].buddy_order;
     598                } else {
     599                        /* Free frames, set refcount = 1
     600                         * (all free frames have refcount == 0, we need not
     601                         * to check the order)
     602                         */
     603                        zones.info[z1].frames[i].refcount = 1;
     604                        zones.info[z1].frames[i].buddy_order = 0;
     605                        i++;
     606                }
     607        }
     608       
     609        /* Add free blocks from the original zone z1 */
     610        while (zone_can_alloc(old_z1, 0)) {
     611                /* Allocate from the original zone */
     612                pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
     613               
     614                /* Free the frame from the merged zone */
     615                frame_t *frame = &zones.info[z1].frames[frame_idx];
     616                frame->refcount = 0;
     617                buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
     618        }
     619       
     620        /* Add free blocks from the original zone z2 */
     621        while (zone_can_alloc(&zones.info[z2], 0)) {
     622                /* Allocate from the original zone */
     623                pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
     624               
     625                /* Free the frame from the merged zone */
     626                frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
     627                frame->refcount = 0;
     628                buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
    493629        }
    494630}
     
    513649        size_t cframes = SIZE2FRAMES(zone_conf_size(count));
    514650       
    515         if ((pfn < zones.info[znum].base) ||
    516             (pfn >= zones.info[znum].base + zones.info[znum].count))
     651        if ((pfn < zones.info[znum].base)
     652            || (pfn >= zones.info[znum].base + zones.info[znum].count))
    517653                return;
    518654       
    519         for (size_t i = 0; i < cframes; i++)
     655        frame_t *frame __attribute__ ((unused));
     656
     657        frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
     658        ASSERT(!frame->buddy_order);
     659       
     660        size_t i;
     661        for (i = 0; i < cframes; i++) {
     662                zones.info[znum].busy_count++;
    520663                (void) zone_frame_free(&zones.info[znum],
    521664                    pfn - zones.info[znum].base + i);
     665        }
     666}
     667
     668/** Reduce allocated block to count of order 0 frames.
     669 *
     670 * The allocated block needs 2^order frames. Reduce all frames
     671 * in the block to order 0 and free the unneeded frames. This means that
     672 * when freeing the previously allocated block starting with frame_idx,
     673 * you have to free every frame.
     674 *
     675 * @param znum      Zone.
     676 * @param frame_idx Index the first frame of the block.
     677 * @param count     Allocated frames in block.
     678 *
     679 */
     680NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx,
     681    size_t count)
     682{
     683        ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
     684        ASSERT(frame_idx + count < zones.info[znum].count);
     685       
     686        uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
     687        ASSERT((size_t) (1 << order) >= count);
     688       
     689        /* Reduce all blocks to order 0 */
     690        size_t i;
     691        for (i = 0; i < (size_t) (1 << order); i++) {
     692                frame_t *frame = &zones.info[znum].frames[i + frame_idx];
     693                frame->buddy_order = 0;
     694                if (!frame->refcount)
     695                        frame->refcount = 1;
     696                ASSERT(frame->refcount == 1);
     697        }
     698       
     699        /* Free unneeded frames */
     700        for (i = count; i < (size_t) (1 << order); i++)
     701                (void) zone_frame_free(&zones.info[znum], i + frame_idx);
    522702}
    523703
     
    539719        bool ret = true;
    540720       
    541         /*
    542          * We can join only 2 zones with none existing inbetween,
     721        /* We can join only 2 zones with none existing inbetween,
    543722         * the zones have to be available and with the same
    544723         * set of flags
     
    554733            + zones.info[z2].count));
    555734       
     735        uint8_t order;
     736        if (cframes == 1)
     737                order = 0;
     738        else
     739                order = fnzb(cframes - 1) + 1;
     740       
    556741        /* Allocate merged zone data inside one of the zones */
    557742        pfn_t pfn;
    558         if (zone_can_alloc(&zones.info[z1], cframes, 0)) {
    559                 pfn = zones.info[z1].base +
    560                     zone_frame_alloc(&zones.info[z1], cframes, 0);
    561         } else if (zone_can_alloc(&zones.info[z2], cframes, 0)) {
    562                 pfn = zones.info[z2].base +
    563                     zone_frame_alloc(&zones.info[z2], cframes, 0);
     743        if (zone_can_alloc(&zones.info[z1], order)) {
     744                pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
     745        } else if (zone_can_alloc(&zones.info[z2], order)) {
     746                pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
    564747        } else {
    565748                ret = false;
     
    569752        /* Preserve original data from z1 */
    570753        zone_t old_z1 = zones.info[z1];
     754        old_z1.buddy_system->data = (void *) &old_z1;
    571755       
    572756        /* Do zone merging */
    573         zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn)));
     757        buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
     758        zone_merge_internal(z1, z2, &old_z1, buddy);
     759       
     760        /* Free unneeded config frames */
     761        zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
    574762       
    575763        /* Subtract zone information from busy frames */
     
    584772       
    585773        /* Move zones down */
    586         for (size_t i = z2 + 1; i < zones.count; i++)
     774        size_t i;
     775        for (i = z2 + 1; i < zones.count; i++) {
    587776                zones.info[i - 1] = zones.info[i];
     777                if (zones.info[i - 1].buddy_system != NULL)
     778                        zones.info[i - 1].buddy_system->data =
     779                            (void *) &zones.info[i - 1];
     780        }
    588781       
    589782        zones.count--;
     
    604797void zone_merge_all(void)
    605798{
    606         size_t i = 1;
    607        
     799        size_t i = 0;
    608800        while (i < zones.count) {
    609                 if (!zone_merge(i - 1, i))
     801                if (!zone_merge(i, i + 1))
    610802                        i++;
    611803        }
     
    614806/** Create new frame zone.
    615807 *
    616  * @param zone     Zone to construct.
    617  * @param start    Physical address of the first frame within the zone.
    618  * @param count    Count of frames in zone.
    619  * @param flags    Zone flags.
    620  * @param confdata Configuration data of the zone.
     808 * @param zone  Zone to construct.
     809 * @param buddy Address of buddy system configuration information.
     810 * @param start Physical address of the first frame within the zone.
     811 * @param count Count of frames in zone.
     812 * @param flags Zone flags.
    621813 *
    622814 * @return Initialized zone.
    623815 *
    624816 */
    625 NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,
    626     zone_flags_t flags, void *confdata)
     817NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy,
     818    pfn_t start, size_t count, zone_flags_t flags)
    627819{
    628820        zone->base = start;
     
    631823        zone->free_count = count;
    632824        zone->busy_count = 0;
     825        zone->buddy_system = buddy;
    633826       
    634827        if (flags & ZONE_AVAILABLE) {
    635828                /*
    636                  * Initialize frame bitmap (located after the array of
    637                  * frame_t structures in the configuration space).
     829                 * Compute order for buddy system and initialize
    638830                 */
    639                
    640                 bitmap_initialize(&zone->bitmap, count, confdata +
    641                     (sizeof(frame_t) * count));
    642                 bitmap_clear_range(&zone->bitmap, 0, count);
    643                
    644                 /*
    645                  * Initialize the array of frame_t structures.
    646                  */
    647                
    648                 zone->frames = (frame_t *) confdata;
    649                
    650                 for (size_t i = 0; i < count; i++)
     831                uint8_t order = fnzb(count);
     832                buddy_system_create(zone->buddy_system, order,
     833                    &zone_buddy_system_operations, (void *) zone);
     834               
     835                /* Allocate frames _after_ the confframe */
     836               
     837                /* Check sizes */
     838                zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
     839                    buddy_conf_size(order));
     840               
     841                size_t i;
     842                for (i = 0; i < count; i++)
    651843                        frame_initialize(&zone->frames[i]);
    652         } else {
    653                 bitmap_initialize(&zone->bitmap, 0, NULL);
     844               
     845                /* Stuffing frames */
     846                for (i = 0; i < count; i++) {
     847                        zone->frames[i].refcount = 0;
     848                        buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
     849                }
     850        } else
    654851                zone->frames = NULL;
    655         }
    656852}
    657853
     
    665861size_t zone_conf_size(size_t count)
    666862{
    667         return (count * sizeof(frame_t) + bitmap_size(count));
     863        return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
    668864}
    669865
     
    671867pfn_t zone_external_conf_alloc(size_t count)
    672868{
    673         size_t frames = SIZE2FRAMES(zone_conf_size(count));
    674        
    675         return ADDR2PFN((uintptr_t)
    676             frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0));
     869        size_t size = zone_conf_size(count);
     870        size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1);
     871
     872        return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH,
     873            FRAME_LOWMEM | FRAME_ATOMIC));
    677874}
    678875
     
    682879 * @param count     Size of zone in frames.
    683880 * @param confframe Where configuration frames are supposed to be.
    684  *                  Automatically checks that we will not disturb the
     881 *                  Automatically checks, that we will not disturb the
    685882 *                  kernel and possibly init. If confframe is given
    686883 *                  _outside_ this zone, it is expected, that the area is
     
    699896       
    700897        if (flags & ZONE_AVAILABLE) {  /* Create available zone */
    701                 /*
    702                  * Theoretically we could have NULL here, practically make sure
     898                /* Theoretically we could have NULL here, practically make sure
    703899                 * nobody tries to do that. If some platform requires, remove
    704900                 * the assert
    705901                 */
    706902                ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
    707                
     903
    708904                /* Update the known end of physical memory. */
    709905                config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
    710906               
    711                 /*
    712                  * If confframe is supposed to be inside our zone, then make sure
     907                /* If confframe is supposed to be inside our zone, then make sure
    713908                 * it does not span kernel & init
    714909                 */
    715910                size_t confcount = SIZE2FRAMES(zone_conf_size(count));
    716                
    717911                if ((confframe >= start) && (confframe < start + count)) {
    718912                        for (; confframe < start + count; confframe++) {
     
    727921                               
    728922                                bool overlap = false;
    729                                 for (size_t i = 0; i < init.cnt; i++) {
     923                                size_t i;
     924                                for (i = 0; i < init.cnt; i++)
    730925                                        if (overlaps(addr, PFN2ADDR(confcount),
    731926                                            init.tasks[i].paddr,
     
    734929                                                break;
    735930                                        }
    736                                 }
    737                                
    738931                                if (overlap)
    739932                                        continue;
     
    752945                }
    753946               
    754                 void *confdata = (void *) PA2KA(PFN2ADDR(confframe));
    755                 zone_construct(&zones.info[znum], start, count, flags, confdata);
     947                buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
     948                zone_construct(&zones.info[znum], buddy, start, count, flags);
    756949               
    757950                /* If confdata in zone, mark as unavailable */
    758951                if ((confframe >= start) && (confframe < start + count)) {
    759                         for (size_t i = confframe; i < confframe + confcount; i++)
     952                        size_t i;
     953                        for (i = confframe; i < confframe + confcount; i++)
    760954                                zone_mark_unavailable(&zones.info[znum],
    761955                                    i - zones.info[znum].base);
     
    773967                return (size_t) -1;
    774968        }
    775        
    776         zone_construct(&zones.info[znum], start, count, flags, NULL);
     969        zone_construct(&zones.info[znum], NULL, start, count, flags);
    777970       
    778971        irq_spinlock_unlock(&zones.lock, true);
     
    8161009}
    8171010
    818 /** Allocate frames of physical memory.
    819  *
    820  * @param count      Number of continuous frames to allocate.
    821  * @param flags      Flags for host zone selection and address processing.
    822  * @param constraint Indication of physical address bits that cannot be
    823  *                   set in the address of the first allocated frame.
    824  * @param pzone      Preferred zone.
     1011/** Allocate power-of-two frames of physical memory.
     1012 *
     1013 * @param order Allocate exactly 2^order frames.
     1014 * @param flags Flags for host zone selection and address processing.
     1015 * @param pzone Preferred zone.
    8251016 *
    8261017 * @return Physical address of the allocated frame.
    8271018 *
    8281019 */
    829 uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags,
    830     uintptr_t constraint, size_t *pzone)
    831 {
    832         ASSERT(count > 0);
    833        
     1020void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
     1021{
     1022        size_t size = ((size_t) 1) << order;
    8341023        size_t hint = pzone ? (*pzone) : 0;
    835         pfn_t frame_constraint = ADDR2PFN(constraint);
    8361024       
    8371025        /*
    8381026         * If not told otherwise, we must first reserve the memory.
    8391027         */
    840         if (!(flags & FRAME_NO_RESERVE))
    841                 reserve_force_alloc(count);
    842        
     1028        if (!(flags & FRAME_NO_RESERVE)) 
     1029                reserve_force_alloc(size);
     1030
    8431031loop:
    8441032        irq_spinlock_lock(&zones.lock, true);
     
    8471035         * First, find suitable frame zone.
    8481036         */
    849         size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
    850             frame_constraint, hint);
    851        
    852         /*
    853          * If no memory, reclaim some slab memory,
    854          * if it does not help, reclaim all.
    855          */
     1037        size_t znum = find_free_zone(order,
     1038            FRAME_TO_ZONE_FLAGS(flags), hint);
     1039       
     1040        /* If no memory, reclaim some slab memory,
     1041           if it does not help, reclaim all */
    8561042        if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
    8571043                irq_spinlock_unlock(&zones.lock, true);
     
    8601046               
    8611047                if (freed > 0)
    862                         znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
    863                             frame_constraint, hint);
     1048                        znum = find_free_zone(order,
     1049                            FRAME_TO_ZONE_FLAGS(flags), hint);
    8641050               
    8651051                if (znum == (size_t) -1) {
     
    8691055                       
    8701056                        if (freed > 0)
    871                                 znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
    872                                     frame_constraint, hint);
     1057                                znum = find_free_zone(order,
     1058                                    FRAME_TO_ZONE_FLAGS(flags), hint);
    8731059                }
    8741060        }
     
    8771063                if (flags & FRAME_ATOMIC) {
    8781064                        irq_spinlock_unlock(&zones.lock, true);
    879                        
    8801065                        if (!(flags & FRAME_NO_RESERVE))
    881                                 reserve_free(count);
    882                        
    883                         return 0;
     1066                                reserve_free(size);
     1067                        return NULL;
    8841068                }
    8851069               
     1070#ifdef CONFIG_DEBUG
    8861071                size_t avail = frame_total_free_get_internal();
     1072#endif
    8871073               
    8881074                irq_spinlock_unlock(&zones.lock, true);
    8891075               
    8901076                if (!THREAD)
    891                         panic("Cannot wait for %zu frames to become available "
    892                             "(%zu available).", count, avail);
     1077                        panic("Cannot wait for memory to become available.");
    8931078               
    8941079                /*
     
    8971082               
    8981083#ifdef CONFIG_DEBUG
    899                 log(LF_OTHER, LVL_DEBUG,
    900                     "Thread %" PRIu64 " waiting for %zu frames "
    901                     "%zu available.", THREAD->tid, count, avail);
     1084                printf("Thread %" PRIu64 " waiting for %zu frames, "
     1085                    "%zu available.\n", THREAD->tid, size, avail);
    9021086#endif
    9031087               
    9041088                /*
    905                  * Since the mem_avail_mtx is an active mutex, we need to
    906                  * disable interrupts to prevent deadlock with TLB shootdown.
     1089                 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
     1090                 * to prevent deadlock with TLB shootdown.
    9071091                 */
    9081092                ipl_t ipl = interrupts_disable();
     
    9101094               
    9111095                if (mem_avail_req > 0)
    912                         mem_avail_req = min(mem_avail_req, count);
     1096                        mem_avail_req = min(mem_avail_req, size);
    9131097                else
    914                         mem_avail_req = count;
    915                
     1098                        mem_avail_req = size;
    9161099                size_t gen = mem_avail_gen;
    9171100               
     
    9231106               
    9241107#ifdef CONFIG_DEBUG
    925                 log(LF_OTHER, LVL_DEBUG, "Thread %" PRIu64 " woken up.",
    926                     THREAD->tid);
     1108                printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
    9271109#endif
    9281110               
     
    9301112        }
    9311113       
    932         pfn_t pfn = zone_frame_alloc(&zones.info[znum], count,
    933             frame_constraint) + zones.info[znum].base;
     1114        pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
     1115            + zones.info[znum].base;
    9341116       
    9351117        irq_spinlock_unlock(&zones.lock, true);
     
    9381120                *pzone = znum;
    9391121       
    940         return PFN2ADDR(pfn);
    941 }
    942 
    943 uintptr_t frame_alloc(size_t count, frame_flags_t flags, uintptr_t constraint)
    944 {
    945         return frame_alloc_generic(count, flags, constraint, NULL);
    946 }
    947 
    948 /** Free frames of physical memory.
    949  *
    950  * Find respective frame structures for supplied physical frames.
    951  * Decrement each frame reference count. If it drops to zero, mark
    952  * the frames as available.
    953  *
    954  * @param start Physical Address of the first frame to be freed.
    955  * @param count Number of frames to free.
     1122        if (flags & FRAME_KA)
     1123                return (void *) PA2KA(PFN2ADDR(pfn));
     1124       
     1125        return (void *) PFN2ADDR(pfn);
     1126}
     1127
     1128void *frame_alloc(uint8_t order, frame_flags_t flags)
     1129{
     1130        return frame_alloc_generic(order, flags, NULL);
     1131}
     1132
     1133void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
     1134{
     1135        return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
     1136}
     1137
     1138/** Free a frame.
     1139 *
     1140 * Find respective frame structure for supplied physical frame address.
     1141 * Decrement frame reference count. If it drops to zero, move the frame
     1142 * structure to free list.
     1143 *
     1144 * @param frame Physical Address of of the frame to be freed.
    9561145 * @param flags Flags to control memory reservation.
    9571146 *
    9581147 */
    959 void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)
    960 {
    961         size_t freed = 0;
     1148void frame_free_generic(uintptr_t frame, frame_flags_t flags)
     1149{
     1150        size_t size;
    9621151       
    9631152        irq_spinlock_lock(&zones.lock, true);
    9641153       
    965         for (size_t i = 0; i < count; i++) {
    966                 /*
    967                  * First, find host frame zone for addr.
    968                  */
    969                 pfn_t pfn = ADDR2PFN(start) + i;
    970                 size_t znum = find_zone(pfn, 1, 0);
    971                
    972                 ASSERT(znum != (size_t) -1);
    973                
    974                 freed += zone_frame_free(&zones.info[znum],
    975                     pfn - zones.info[znum].base);
    976         }
     1154        /*
     1155         * First, find host frame zone for addr.
     1156         */
     1157        pfn_t pfn = ADDR2PFN(frame);
     1158        size_t znum = find_zone(pfn, 1, 0);
     1159
     1160        ASSERT(znum != (size_t) -1);
     1161       
     1162        size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
    9771163       
    9781164        irq_spinlock_unlock(&zones.lock, true);
     
    9801166        /*
    9811167         * Signal that some memory has been freed.
    982          * Since the mem_avail_mtx is an active mutex,
    983          * we need to disable interruptsto prevent deadlock
    984          * with TLB shootdown.
    9851168         */
    986        
     1169
     1170       
     1171        /*
     1172         * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
     1173         * to prevent deadlock with TLB shootdown.
     1174         */
    9871175        ipl_t ipl = interrupts_disable();
    9881176        mutex_lock(&mem_avail_mtx);
    989        
    9901177        if (mem_avail_req > 0)
    991                 mem_avail_req -= min(mem_avail_req, freed);
     1178                mem_avail_req -= min(mem_avail_req, size);
    9921179       
    9931180        if (mem_avail_req == 0) {
     
    9951182                condvar_broadcast(&mem_avail_cv);
    9961183        }
    997        
    9981184        mutex_unlock(&mem_avail_mtx);
    9991185        interrupts_restore(ipl);
    10001186       
    10011187        if (!(flags & FRAME_NO_RESERVE))
    1002                 reserve_free(freed);
    1003 }
    1004 
    1005 void frame_free(uintptr_t frame, size_t count)
    1006 {
    1007         frame_free_generic(frame, count, 0);
    1008 }
    1009 
    1010 void frame_free_noreserve(uintptr_t frame, size_t count)
    1011 {
    1012         frame_free_generic(frame, count, FRAME_NO_RESERVE);
     1188                reserve_free(size);
     1189}
     1190
     1191void frame_free(uintptr_t frame)
     1192{
     1193        frame_free_generic(frame, 0);
     1194}
     1195
     1196void frame_free_noreserve(uintptr_t frame)
     1197{
     1198        frame_free_generic(frame, FRAME_NO_RESERVE);
    10131199}
    10141200
     
    10441230        irq_spinlock_lock(&zones.lock, true);
    10451231       
    1046         for (size_t i = 0; i < count; i++) {
     1232        size_t i;
     1233        for (i = 0; i < count; i++) {
    10471234                size_t znum = find_zone(start + i, 1, 0);
    1048                
    10491235                if (znum == (size_t) -1)  /* PFN not found */
    10501236                        continue;
     
    10711257        /* Tell the architecture to create some memory */
    10721258        frame_low_arch_init();
    1073        
    10741259        if (config.cpu_active == 1) {
    10751260                frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
     
    10781263                    SIZE2FRAMES(config.stack_size));
    10791264               
    1080                 for (size_t i = 0; i < init.cnt; i++)
    1081                         frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr),
     1265                size_t i;
     1266                for (i = 0; i < init.cnt; i++) {
     1267                        pfn_t pfn = ADDR2PFN(init.tasks[i].paddr);
     1268                        frame_mark_unavailable(pfn,
    10821269                            SIZE2FRAMES(init.tasks[i].size));
     1270                }
    10831271               
    10841272                if (ballocs.size)
     
    10861274                            SIZE2FRAMES(ballocs.size));
    10871275               
    1088                 /*
    1089                  * Blacklist first frame, as allocating NULL would
     1276                /* Black list first frame, as allocating NULL would
    10901277                 * fail in some places
    10911278                 */
    10921279                frame_mark_unavailable(0, 1);
    10931280        }
    1094        
    10951281        frame_high_arch_init();
    10961282}
     
    10981284/** Adjust bounds of physical memory region according to low/high memory split.
    10991285 *
    1100  * @param low[in]      If true, the adjustment is performed to make the region
    1101  *                     fit in the low memory. Otherwise the adjustment is
    1102  *                     performed to make the region fit in the high memory.
    1103  * @param basep[inout] Pointer to a variable which contains the region's base
    1104  *                     address and which may receive the adjusted base address.
    1105  * @param sizep[inout] Pointer to a variable which contains the region's size
    1106  *                     and which may receive the adjusted size.
    1107  *
    1108  * @return True if the region still exists even after the adjustment.
    1109  * @return False otherwise.
    1110  *
     1286 * @param low[in]       If true, the adjustment is performed to make the region
     1287 *                      fit in the low memory. Otherwise the adjustment is
     1288 *                      performed to make the region fit in the high memory.
     1289 * @param basep[inout]  Pointer to a variable which contains the region's base
     1290 *                      address and which may receive the adjusted base address.
     1291 * @param sizep[inout]  Pointer to a variable which contains the region's size
     1292 *                      and which may receive the adjusted size.
     1293 * @retun               True if the region still exists even after the
     1294 *                      adjustment, false otherwise.
    11111295 */
    11121296bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
    11131297{
    11141298        uintptr_t limit = KA2PA(config.identity_base) + config.identity_size;
    1115        
     1299
    11161300        if (low) {
    11171301                if (*basep > limit)
    11181302                        return false;
    1119                
    11201303                if (*basep + *sizep > limit)
    11211304                        *sizep = limit - *basep;
     
    11231306                if (*basep + *sizep <= limit)
    11241307                        return false;
    1125                
    11261308                if (*basep <= limit) {
    11271309                        *sizep -= limit - *basep;
     
    11291311                }
    11301312        }
    1131        
    11321313        return true;
    11331314}
     
    11411322       
    11421323        uint64_t total = 0;
    1143        
    1144         for (size_t i = 0; i < zones.count; i++)
     1324        size_t i;
     1325        for (i = 0; i < zones.count; i++)
    11451326                total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    11461327       
     
    11651346        *free = 0;
    11661347       
    1167         for (size_t i = 0; i < zones.count; i++) {
     1348        size_t i;
     1349        for (i = 0; i < zones.count; i++) {
    11681350                *total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    11691351               
     
    11931375        /*
    11941376         * Because printing may require allocation of memory, we may not hold
    1195          * the frame allocator locks when printing zone statistics. Therefore,
     1377         * the frame allocator locks when printing zone statistics.  Therefore,
    11961378         * we simply gather the statistics under the protection of the locks and
    11971379         * print the statistics when the locks have been released.
     
    12021384         */
    12031385       
    1204         size_t free_lowmem = 0;
    1205         size_t free_highmem = 0;
    1206         size_t free_highprio = 0;
    1207        
    1208         for (size_t i = 0;; i++) {
     1386        size_t i;
     1387        for (i = 0;; i++) {
    12091388                irq_spinlock_lock(&zones.lock, true);
    12101389               
     
    12141393                }
    12151394               
    1216                 pfn_t fbase = zones.info[i].base;
    1217                 uintptr_t base = PFN2ADDR(fbase);
     1395                uintptr_t base = PFN2ADDR(zones.info[i].base);
    12181396                size_t count = zones.info[i].count;
    12191397                zone_flags_t flags = zones.info[i].flags;
     
    12211399                size_t busy_count = zones.info[i].busy_count;
    12221400               
     1401                irq_spinlock_unlock(&zones.lock, true);
     1402               
    12231403                bool available = ((flags & ZONE_AVAILABLE) != 0);
    1224                 bool lowmem = ((flags & ZONE_LOWMEM) != 0);
    1225                 bool highmem = ((flags & ZONE_HIGHMEM) != 0);
    1226                 bool highprio = is_high_priority(fbase, count);
    1227                
    1228                 if (available) {
    1229                         if (lowmem)
    1230                                 free_lowmem += free_count;
    1231                        
    1232                         if (highmem)
    1233                                 free_highmem += free_count;
    1234                        
    1235                         if (highprio) {
    1236                                 free_highprio += free_count;
    1237                         } else {
    1238                                 /*
    1239                                  * Walk all frames of the zone and examine
    1240                                  * all high priority memory to get accurate
    1241                                  * statistics.
    1242                                  */
    1243                                
    1244                                 for (size_t index = 0; index < count; index++) {
    1245                                         if (is_high_priority(fbase + index, 0)) {
    1246                                                 if (!bitmap_get(&zones.info[i].bitmap, index))
    1247                                                         free_highprio++;
    1248                                         } else
    1249                                                 break;
    1250                                 }
    1251                         }
    1252                 }
    1253                
    1254                 irq_spinlock_unlock(&zones.lock, true);
    12551404               
    12561405                printf("%-4zu", i);
     
    12771426                printf("\n");
    12781427        }
    1279        
    1280         printf("\n");
    1281        
    1282         uint64_t size;
    1283         const char *size_suffix;
    1284        
    1285         bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
    1286             false);
    1287         printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
    1288             free_lowmem, size, size_suffix);
    1289        
    1290         bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
    1291             false);
    1292         printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
    1293             free_highmem, size, size_suffix);
    1294        
    1295         bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
    1296             false);
    1297         printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
    1298             free_highprio, size, size_suffix);
    12991428}
    13001429
     
    13091438        size_t znum = (size_t) -1;
    13101439       
    1311         for (size_t i = 0; i < zones.count; i++) {
     1440        size_t i;
     1441        for (i = 0; i < zones.count; i++) {
    13121442                if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
    13131443                        znum = i;
     
    13221452        }
    13231453       
    1324         size_t free_lowmem = 0;
    1325         size_t free_highmem = 0;
    1326         size_t free_highprio = 0;
    1327        
    1328         pfn_t fbase = zones.info[znum].base;
    1329         uintptr_t base = PFN2ADDR(fbase);
    1330         zone_flags_t flags = zones.info[znum].flags;
    1331         size_t count = zones.info[znum].count;
    1332         size_t free_count = zones.info[znum].free_count;
    1333         size_t busy_count = zones.info[znum].busy_count;
     1454        uintptr_t base = PFN2ADDR(zones.info[i].base);
     1455        zone_flags_t flags = zones.info[i].flags;
     1456        size_t count = zones.info[i].count;
     1457        size_t free_count = zones.info[i].free_count;
     1458        size_t busy_count = zones.info[i].busy_count;
     1459       
     1460        irq_spinlock_unlock(&zones.lock, true);
    13341461       
    13351462        bool available = ((flags & ZONE_AVAILABLE) != 0);
    1336         bool lowmem = ((flags & ZONE_LOWMEM) != 0);
    1337         bool highmem = ((flags & ZONE_HIGHMEM) != 0);
    1338         bool highprio = is_high_priority(fbase, count);
    1339        
    1340         if (available) {
    1341                 if (lowmem)
    1342                         free_lowmem = free_count;
    1343                
    1344                 if (highmem)
    1345                         free_highmem = free_count;
    1346                
    1347                 if (highprio) {
    1348                         free_highprio = free_count;
    1349                 } else {
    1350                         /*
    1351                          * Walk all frames of the zone and examine
    1352                          * all high priority memory to get accurate
    1353                          * statistics.
    1354                          */
    1355                        
    1356                         for (size_t index = 0; index < count; index++) {
    1357                                 if (is_high_priority(fbase + index, 0)) {
    1358                                         if (!bitmap_get(&zones.info[znum].bitmap, index))
    1359                                                 free_highprio++;
    1360                                 } else
    1361                                         break;
    1362                         }
    1363                 }
    1364         }
    1365        
    1366         irq_spinlock_unlock(&zones.lock, true);
    13671463       
    13681464        uint64_t size;
    13691465        const char *size_suffix;
    1370        
    13711466        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
    13721467       
    1373         printf("Zone number:             %zu\n", znum);
    1374         printf("Zone base address:       %p\n", (void *) base);
    1375         printf("Zone size:               %zu frames (%" PRIu64 " %s)\n", count,
     1468        printf("Zone number:       %zu\n", znum);
     1469        printf("Zone base address: %p\n", (void *) base);
     1470        printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
    13761471            size, size_suffix);
    1377         printf("Zone flags:              %c%c%c%c%c\n",
     1472        printf("Zone flags:        %c%c%c%c%c\n",
    13781473            available ? 'A' : '-',
    13791474            (flags & ZONE_RESERVED) ? 'R' : '-',
     
    13851480                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
    13861481                    false);
    1387                 printf("Allocated space:         %zu frames (%" PRIu64 " %s)\n",
     1482                printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
    13881483                    busy_count, size, size_suffix);
    1389                
    13901484                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
    13911485                    false);
    1392                 printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
     1486                printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
    13931487                    free_count, size, size_suffix);
    1394                
    1395                 bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
    1396                     false);
    1397                 printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
    1398                     free_lowmem, size, size_suffix);
    1399                
    1400                 bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
    1401                     false);
    1402                 printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
    1403                     free_highmem, size, size_suffix);
    1404                
    1405                 bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
    1406                     false);
    1407                 printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
    1408                     free_highprio, size, size_suffix);
    14091488        }
    14101489}
Note: See TracChangeset for help on using the changeset viewer.