Changeset e5a015b in mainline for kernel/generic/src/mm/frame.c


Ignore:
Timestamp:
2011-04-16T20:45:36Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a7dbd49
Parents:
b2fb47f (diff), 9e953bda (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge the memory reservation feature (Phase 1) from
lp:~jakub/helenos/mm.

This merge makes the testcase from ticket #114 non-reproducible. The
testcase is now available as tester's malloc2 test. It also seems to me
that this merge makes it harder for the system to run out of memory
during kconsole 'test *' and 'tester *', even though I did see several
hangs already with this feature in place. See below for what is still
missing to make the hangs even less probable or even impossible.

In Phase 1, I am targeting just the low-hanging fruits. In particular,
only anonymous and ELF backend pages are reserved physical memory at
time of as_area_create() and as_area_resize(). Memory is unreserved on
as_area_destroy(). In all other cases, memory is reserved at the same
time as it is allocated, making those calls subject to infinite
blocking if FRAME_ATOMIC is not used.

Possible sources of memory overcommit not addressed in this merge:

  • As mentioned above, only backend pages are reserved; pages for supporting structures such as B+tree nodes, TTEs are not reserved or handled otherwise. Kernel heap allocator fragmentation is not included in the reservations either.
  • The initial amount of reservable memory is fed from zone_construct(). Zone merging is not taken into account, which can make the reservable memory tracking inaccurate.
File:
1 edited

Legend:

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

    rb2fb47f re5a015b  
    4545#include <typedefs.h>
    4646#include <mm/frame.h>
     47#include <mm/reserve.h>
    4748#include <mm/as.h>
    4849#include <panic.h>
     
    472473 * @param frame_idx Frame index relative to zone.
    473474 *
    474  */
    475 NO_TRACE static void zone_frame_free(zone_t *zone, size_t frame_idx)
     475 * @return          Number of freed frames.
     476 *
     477 */
     478NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
    476479{
    477480        ASSERT(zone_flags_available(zone->flags));
    478481       
    479482        frame_t *frame = &zone->frames[frame_idx];
    480        
    481         /* Remember frame order */
    482         uint8_t order = frame->buddy_order;
     483        size_t size = 1 << frame->buddy_order;
    483484       
    484485        ASSERT(frame->refcount);
     
    488489               
    489490                /* Update zone information. */
    490                 zone->free_count += (1 << order);
    491                 zone->busy_count -= (1 << order);
    492         }
     491                zone->free_count += size;
     492                zone->busy_count -= size;
     493        }
     494       
     495        return size;
    493496}
    494497
     
    516519        ASSERT(link);
    517520        zone->free_count--;
     521        reserve_force_alloc(1);
    518522}
    519523
     
    645649        for (i = 0; i < cframes; i++) {
    646650                zones.info[znum].busy_count++;
    647                 zone_frame_free(&zones.info[znum],
     651                (void) zone_frame_free(&zones.info[znum],
    648652                    pfn - zones.info[znum].base + i);
    649653        }
     
    683687        /* Free unneeded frames */
    684688        for (i = count; i < (size_t) (1 << order); i++)
    685                 zone_frame_free(&zones.info[znum], i + frame_idx);
     689                (void) zone_frame_free(&zones.info[znum], i + frame_idx);
    686690}
    687691
     
    695699 * not to be 2^order size. Once the allocator is running it is no longer
    696700 * possible, merged configuration data occupies more space :-/
    697  *
    698  * The function uses
    699701 *
    700702 */
     
    837839                        buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
    838840                }
     841
     842                /* "Unreserve" new frames. */
     843                reserve_free(count);
    839844        } else
    840845                zone->frames = NULL;
     
    9991004        size_t hint = pzone ? (*pzone) : 0;
    10001005       
     1006        /*
     1007         * If not told otherwise, we must first reserve the memory.
     1008         */
     1009        if (!(flags & FRAME_NO_RESERVE)) {
     1010                if (flags & FRAME_ATOMIC) {
     1011                        if (!reserve_try_alloc(size))
     1012                                return NULL;
     1013                } else {
     1014                        reserve_force_alloc(size);
     1015                }
     1016        }
     1017       
    10011018loop:
    10021019        irq_spinlock_lock(&zones.lock, true);
     
    10331050                if (flags & FRAME_ATOMIC) {
    10341051                        irq_spinlock_unlock(&zones.lock, true);
     1052                        if (!(flags & FRAME_NO_RESERVE))
     1053                                reserve_free(size);
    10351054                        return NULL;
    10361055                }
     
    10881107}
    10891108
     1109void *frame_alloc(uint8_t order, frame_flags_t flags)
     1110{
     1111        return frame_alloc_generic(order, flags, NULL);
     1112}
     1113
     1114void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
     1115{
     1116        return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
     1117}
     1118
    10901119/** Free a frame.
    10911120 *
     
    10951124 *
    10961125 * @param frame Physical Address of of the frame to be freed.
    1097  *
    1098  */
    1099 void frame_free(uintptr_t frame)
    1100 {
     1126 * @param flags Flags to control memory reservation.
     1127 *
     1128 */
     1129void frame_free_generic(uintptr_t frame, frame_flags_t flags)
     1130{
     1131        size_t size;
     1132       
    11011133        irq_spinlock_lock(&zones.lock, true);
    11021134       
     
    11061138        pfn_t pfn = ADDR2PFN(frame);
    11071139        size_t znum = find_zone(pfn, 1, 0);
     1140
    11081141       
    11091142        ASSERT(znum != (size_t) -1);
    11101143       
    1111         zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
     1144        size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
    11121145       
    11131146        irq_spinlock_unlock(&zones.lock, true);
     
    11181151        mutex_lock(&mem_avail_mtx);
    11191152        if (mem_avail_req > 0)
    1120                 mem_avail_req--;
     1153                mem_avail_req -= min(mem_avail_req, size);
    11211154       
    11221155        if (mem_avail_req == 0) {
     
    11251158        }
    11261159        mutex_unlock(&mem_avail_mtx);
     1160       
     1161        if (!(flags & FRAME_NO_RESERVE))
     1162                reserve_free(size);
     1163}
     1164
     1165void frame_free(uintptr_t frame)
     1166{
     1167        frame_free_generic(frame, 0);
     1168}
     1169
     1170void frame_free_noreserve(uintptr_t frame)
     1171{
     1172        frame_free_generic(frame, FRAME_NO_RESERVE);
    11271173}
    11281174
Note: See TracChangeset for help on using the changeset viewer.