Ignore:
File:
1 edited

Legend:

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

    rd1582b50 rc626117  
    6363#include <proc/thread.h> /* THREAD */
    6464
    65 zones_t zones;
     65zones_t zones = {
     66        .count = 0,
     67        .lock = IRQ_SPINLOCK_INITIALIZER("frame.zones.lock"),
     68};
    6669
    6770/*
     
    6972 * available.
    7073 */
    71 static mutex_t mem_avail_mtx;
    72 static condvar_t mem_avail_cv;
     74static IRQ_SPINLOCK_INITIALIZE(mem_avail_lock);
     75static CONDVAR_INITIALIZE(mem_avail_cv);
    7376static size_t mem_avail_req = 0;  /**< Number of frames requested. */
    7477static size_t mem_avail_gen = 0;  /**< Generation counter. */
     
    370373{
    371374        assert(zone->flags & ZONE_AVAILABLE);
     375        assert(zone->free_count >= count);
    372376
    373377        /* Allocate frames from zone */
     
    410414
    411415        frame_t *frame = zone_get_frame(zone, index);
    412 
    413416        assert(frame->refcount > 0);
    414417
    415418        if (!--frame->refcount) {
     419                assert(zone->busy_count > 0);
     420
    416421                bitmap_set(&zone->bitmap, index, 0);
    417422
     
    432437
    433438        frame_t *frame = zone_get_frame(zone, index);
     439        assert(frame->refcount <= 1);
     440
    434441        if (frame->refcount > 0)
    435442                return;
    436443
     444        assert(zone->free_count > 0);
     445
    437446        frame->refcount = 1;
    438447        bitmap_set_range(&zone->bitmap, index, 1);
     
    440449        zone->free_count--;
    441450        reserve_force_alloc(1);
     451}
     452
     453/** Mark frame in zone available to allocation. */
     454_NO_TRACE static void zone_mark_available(zone_t *zone, size_t index)
     455{
     456        assert(zone->flags & ZONE_AVAILABLE);
     457
     458        frame_t *frame = zone_get_frame(zone, index);
     459        assert(frame->refcount == 1);
     460
     461        frame->refcount = 0;
     462        bitmap_set_range(&zone->bitmap, index, 0);
     463
     464        zone->free_count++;
    442465}
    443466
     
    465488        /* Difference between zone bases */
    466489        pfn_t base_diff = zones.info[z2].base - zones.info[z1].base;
     490        pfn_t gap = base_diff - zones.info[z1].count;
    467491
    468492        zones.info[z1].count = base_diff + zones.info[z2].count;
     
    492516                    zones.info[z2].frames[i];
    493517        }
     518
     519        /*
     520         * Mark the gap between the original zones as unavailable.
     521         */
     522
     523        for (size_t i = 0; i < gap; i++) {
     524                frame_initialize(&zones.info[z1].frames[old_z1->count + i]);
     525                zone_mark_unavailable(&zones.info[z1], old_z1->count + i);
     526        }
    494527}
    495528
     
    518551
    519552        for (size_t i = 0; i < cframes; i++)
    520                 (void) zone_frame_free(&zones.info[znum],
     553                zone_mark_available(&zones.info[znum],
    521554                    pfn - zones.info[znum].base + i);
    522555}
     
    723756
    724757                                if (overlaps(addr, PFN2ADDR(confcount),
    725                                     KA2PA(config.stack_base), config.stack_size))
     758                                    KA2PA(ballocs.base), ballocs.size))
    726759                                        continue;
    727760
     
    918951#endif
    919952
    920                 /*
    921                  * Since the mem_avail_mtx is an active mutex, we need to
    922                  * disable interrupts to prevent deadlock with TLB shootdown.
    923                  */
    924                 ipl_t ipl = interrupts_disable();
    925                 mutex_lock(&mem_avail_mtx);
     953                /* Disabled interrupts needed to prevent deadlock with TLB shootdown. */
     954                irq_spinlock_lock(&mem_avail_lock, true);
    926955
    927956                if (mem_avail_req > 0)
     
    933962
    934963                while (gen == mem_avail_gen)
    935                         condvar_wait(&mem_avail_cv, &mem_avail_mtx);
    936 
    937                 mutex_unlock(&mem_avail_mtx);
    938                 interrupts_restore(ipl);
     964                        condvar_wait(&mem_avail_cv, &mem_avail_lock);
     965
     966                irq_spinlock_unlock(&mem_avail_lock, true);
    939967
    940968#ifdef CONFIG_DEBUG
     
    9941022        irq_spinlock_unlock(&zones.lock, true);
    9951023
    996         /*
    997          * Signal that some memory has been freed.
    998          * Since the mem_avail_mtx is an active mutex,
    999          * we need to disable interruptsto prevent deadlock
    1000          * with TLB shootdown.
    1001          */
    1002 
    1003         ipl_t ipl = interrupts_disable();
    1004         mutex_lock(&mem_avail_mtx);
     1024        /* Signal that some memory has been freed. */
     1025
     1026        /* Disabled interrupts needed to prevent deadlock with TLB shootdown. */
     1027        irq_spinlock_lock(&mem_avail_lock, true);
    10051028
    10061029        if (mem_avail_req > 0)
     
    10121035        }
    10131036
    1014         mutex_unlock(&mem_avail_mtx);
    1015         interrupts_restore(ipl);
     1037        irq_spinlock_unlock(&mem_avail_lock, true);
    10161038
    10171039        if (!(flags & FRAME_NO_RESERVE))
     
    10781100void frame_init(void)
    10791101{
    1080         if (config.cpu_active == 1) {
    1081                 zones.count = 0;
    1082                 irq_spinlock_initialize(&zones.lock, "frame.zones.lock");
    1083                 mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
    1084                 condvar_initialize(&mem_avail_cv);
    1085         }
    1086 
    10871102        /* Tell the architecture to create some memory */
    10881103        frame_low_arch_init();
     
    10911106                frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
    10921107                    SIZE2FRAMES(config.kernel_size));
    1093                 frame_mark_unavailable(ADDR2PFN(KA2PA(config.stack_base)),
    1094                     SIZE2FRAMES(config.stack_size));
    10951108
    10961109                for (size_t i = 0; i < init.cnt; i++)
Note: See TracChangeset for help on using the changeset viewer.