Ignore:
File:
1 edited

Legend:

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

    r2d3ddad r55821eea  
    3333/**
    3434 * @file
    35  * @brief Slab allocator.
     35 * @brief       Slab allocator.
    3636 *
    3737 * The slab allocator is closely modelled after OpenSolaris slab allocator.
     
    5050 *
    5151 * The slab allocator supports per-CPU caches ('magazines') to facilitate
    52  * good SMP scaling.
     52 * good SMP scaling. 
    5353 *
    5454 * When a new object is being allocated, it is first checked, if it is
     
    6565 * thrashing when somebody is allocating/deallocating 1 item at the magazine
    6666 * size boundary. LIFO order is enforced, which should avoid fragmentation
    67  * as much as possible.
    68  *
     67 * as much as possible. 
     68 * 
    6969 * Every cache contains list of full slabs and list of partially full slabs.
    7070 * Empty slabs are immediately freed (thrashing will be avoided because
    71  * of magazines).
     71 * of magazines). 
    7272 *
    7373 * The slab information structure is kept inside the data area, if possible.
     
    9595 *
    9696 * @todo
    97  * It might be good to add granularity of locks even to slab level,
     97 * it might be good to add granularity of locks even to slab level,
    9898 * we could then try_spinlock over all partial slabs and thus improve
    99  * scalability even on slab level.
    100  *
     99 * scalability even on slab level
    101100 */
    102101
     
    115114#include <macros.h>
    116115
    117 IRQ_SPINLOCK_STATIC_INITIALIZE(slab_cache_lock);
     116SPINLOCK_INITIALIZE(slab_cache_lock);
    118117static LIST_INITIALIZE(slab_cache_list);
    119118
    120119/** Magazine cache */
    121120static slab_cache_t mag_cache;
    122 
    123121/** Cache for cache descriptors */
    124122static slab_cache_t slab_cache_cache;
    125 
    126123/** Cache for external slab descriptors
    127124 * This time we want per-cpu cache, so do not make it static
     
    131128 */
    132129static slab_cache_t *slab_extern_cache;
    133 
    134130/** Caches for malloc */
    135131static slab_cache_t *malloc_caches[SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1];
    136 
    137132static const char *malloc_names[] =  {
    138133        "malloc-16",
     
    159154/** Slab descriptor */
    160155typedef struct {
    161         slab_cache_t *cache;  /**< Pointer to parent cache. */
    162         link_t link;          /**< List of full/partial slabs. */
    163         void *start;          /**< Start address of first available item. */
    164         size_t available;     /**< Count of available items in this slab. */
    165         size_t nextavail;     /**< The index of next available item. */
     156        slab_cache_t *cache;    /**< Pointer to parent cache. */
     157        link_t link;            /**< List of full/partial slabs. */
     158        void *start;            /**< Start address of first available item. */
     159        size_t available;       /**< Count of available items in this slab. */
     160        size_t nextavail;       /**< The index of next available item. */
    166161} slab_t;
    167162
    168163#ifdef CONFIG_DEBUG
    169 static unsigned int _slab_initialized = 0;
     164static int _slab_initialized = 0;
    170165#endif
    171166
    172167/**************************************/
    173168/* Slab allocation functions          */
    174 /**************************************/
    175 
    176 /** Allocate frames for slab space and initialize
    177  *
    178  */
    179 static slab_t *slab_space_alloc(slab_cache_t *cache, unsigned int flags)
    180 {
    181        
    182        
     169
     170/**
     171 * Allocate frames for slab space and initialize
     172 *
     173 */
     174static slab_t *slab_space_alloc(slab_cache_t *cache, int flags)
     175{
     176        void *data;
     177        slab_t *slab;
     178        size_t fsize;
     179        unsigned int i;
    183180        size_t zone = 0;
    184181       
    185         void *data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
     182        data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
    186183        if (!data) {
    187184                return NULL;
    188185        }
    189        
    190         slab_t *slab;
    191         size_t fsize;
    192        
    193186        if (!(cache->flags & SLAB_CACHE_SLINSIDE)) {
    194187                slab = slab_alloc(slab_extern_cache, flags);
     
    203196       
    204197        /* Fill in slab structures */
    205         size_t i;
    206         for (i = 0; i < ((size_t) 1 << cache->order); i++)
     198        for (i = 0; i < ((unsigned int) 1 << cache->order); i++)
    207199                frame_set_parent(ADDR2PFN(KA2PA(data)) + i, slab, zone);
    208        
     200
    209201        slab->start = data;
    210202        slab->available = cache->objects;
    211203        slab->nextavail = 0;
    212204        slab->cache = cache;
    213        
     205
    214206        for (i = 0; i < cache->objects; i++)
    215                 *((size_t *) (slab->start + i * cache->size)) = i + 1;
    216        
     207                *((int *) (slab->start + i*cache->size)) = i + 1;
     208
    217209        atomic_inc(&cache->allocated_slabs);
    218210        return slab;
    219211}
    220212
    221 /** Deallocate space associated with slab
     213/**
     214 * Deallocate space associated with slab
    222215 *
    223216 * @return number of freed frames
    224  *
    225217 */
    226218static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
    227219{
    228220        frame_free(KA2PA(slab->start));
    229         if (!(cache->flags & SLAB_CACHE_SLINSIDE))
     221        if (! (cache->flags & SLAB_CACHE_SLINSIDE))
    230222                slab_free(slab_extern_cache, slab);
    231        
     223
    232224        atomic_dec(&cache->allocated_slabs);
    233225       
    234         return (1 << cache->order);
     226        return 1 << cache->order;
    235227}
    236228
    237229/** Map object to slab structure */
    238 static slab_t *obj2slab(void *obj)
     230static slab_t * obj2slab(void *obj)
    239231{
    240232        return (slab_t *) frame_get_parent(ADDR2PFN(KA2PA(obj)), 0);
    241233}
    242234
    243 /******************/
     235/**************************************/
    244236/* Slab functions */
    245 /******************/
    246 
    247 /** Return object to slab and call a destructor
     237
     238
     239/**
     240 * Return object to slab and call a destructor
    248241 *
    249242 * @param slab If the caller knows directly slab of the object, otherwise NULL
    250243 *
    251244 * @return Number of freed pages
    252  *
    253245 */
    254246static size_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
    255247{
     248        int freed = 0;
     249
    256250        if (!slab)
    257251                slab = obj2slab(obj);
    258        
     252
    259253        ASSERT(slab->cache == cache);
    260        
    261         size_t freed = 0;
    262        
     254
    263255        if (cache->destructor)
    264256                freed = cache->destructor(obj);
     
    266258        spinlock_lock(&cache->slablock);
    267259        ASSERT(slab->available < cache->objects);
    268        
    269         *((size_t *) obj) = slab->nextavail;
     260
     261        *((int *)obj) = slab->nextavail;
    270262        slab->nextavail = (obj - slab->start) / cache->size;
    271263        slab->available++;
    272        
     264
    273265        /* Move it to correct list */
    274266        if (slab->available == cache->objects) {
     
    276268                list_remove(&slab->link);
    277269                spinlock_unlock(&cache->slablock);
    278                
     270
    279271                return freed + slab_space_free(cache, slab);
     272
    280273        } else if (slab->available == 1) {
    281274                /* It was in full, move to partial */
     
    283276                list_prepend(&slab->link, &cache->partial_slabs);
    284277        }
    285        
    286278        spinlock_unlock(&cache->slablock);
    287279        return freed;
    288280}
    289281
    290 /** Take new object from slab or create new if needed
     282/**
     283 * Take new object from slab or create new if needed
    291284 *
    292285 * @return Object address or null
    293  *
    294286 */
    295287static void *slab_obj_create(slab_cache_t *cache, int flags)
    296288{
     289        slab_t *slab;
     290        void *obj;
     291
    297292        spinlock_lock(&cache->slablock);
    298        
    299         slab_t *slab;
    300        
     293
    301294        if (list_empty(&cache->partial_slabs)) {
    302                 /*
    303                  * Allow recursion and reclaiming
     295                /* Allow recursion and reclaiming
    304296                 * - this should work, as the slab control structures
    305297                 *   are small and do not need to allocate with anything
    306298                 *   other than frame_alloc when they are allocating,
    307299                 *   that's why we should get recursion at most 1-level deep
    308                  *
    309300                 */
    310301                spinlock_unlock(&cache->slablock);
     
    312303                if (!slab)
    313304                        return NULL;
    314                
    315305                spinlock_lock(&cache->slablock);
    316306        } else {
     
    319309                list_remove(&slab->link);
    320310        }
    321        
    322         void *obj = slab->start + slab->nextavail * cache->size;
    323         slab->nextavail = *((size_t *) obj);
     311        obj = slab->start + slab->nextavail * cache->size;
     312        slab->nextavail = *((int *)obj);
    324313        slab->available--;
    325        
     314
    326315        if (!slab->available)
    327316                list_prepend(&slab->link, &cache->full_slabs);
    328317        else
    329318                list_prepend(&slab->link, &cache->partial_slabs);
    330        
     319
    331320        spinlock_unlock(&cache->slablock);
    332        
    333         if ((cache->constructor) && (cache->constructor(obj, flags))) {
     321
     322        if (cache->constructor && cache->constructor(obj, flags)) {
    334323                /* Bad, bad, construction failed */
    335324                slab_obj_destroy(cache, obj, slab);
    336325                return NULL;
    337326        }
    338        
    339327        return obj;
    340328}
    341329
    342 /****************************/
     330/**************************************/
    343331/* CPU-Cache slab functions */
    344 /****************************/
    345 
    346 /** Find a full magazine in cache, take it from list and return it
    347  *
    348  * @param first If true, return first, else last mag.
    349  *
    350  */
    351 static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, bool first)
     332
     333/**
     334 * Finds a full magazine in cache, takes it from list
     335 * and returns it
     336 *
     337 * @param first If true, return first, else last mag
     338 */
     339static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, int first)
    352340{
    353341        slab_magazine_t *mag = NULL;
    354342        link_t *cur;
    355        
     343
    356344        spinlock_lock(&cache->maglock);
    357345        if (!list_empty(&cache->magazines)) {
     
    360348                else
    361349                        cur = cache->magazines.prev;
    362                
    363350                mag = list_get_instance(cur, slab_magazine_t, link);
    364351                list_remove(&mag->link);
    365352                atomic_dec(&cache->magazine_counter);
    366353        }
    367        
    368354        spinlock_unlock(&cache->maglock);
    369355        return mag;
    370356}
    371357
    372 /** Prepend magazine to magazine list in cache
    373  *
    374  */
     358/** Prepend magazine to magazine list in cache */
    375359static void put_mag_to_cache(slab_cache_t *cache, slab_magazine_t *mag)
    376360{
    377361        spinlock_lock(&cache->maglock);
    378        
     362
    379363        list_prepend(&mag->link, &cache->magazines);
    380364        atomic_inc(&cache->magazine_counter);
     
    383367}
    384368
    385 /** Free all objects in magazine and free memory associated with magazine
     369/**
     370 * Free all objects in magazine and free memory associated with magazine
    386371 *
    387372 * @return Number of freed pages
    388  *
    389373 */
    390374static size_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
    391375{
    392         size_t i;
     376        unsigned int i;
    393377        size_t frames = 0;
    394        
     378
    395379        for (i = 0; i < mag->busy; i++) {
    396380                frames += slab_obj_destroy(cache, mag->objs[i], NULL);
     
    399383       
    400384        slab_free(&mag_cache, mag);
    401        
     385
    402386        return frames;
    403387}
    404388
    405 /** Find full magazine, set it as current and return it
    406  *
     389/**
     390 * Find full magazine, set it as current and return it
     391 *
     392 * Assume cpu_magazine lock is held
    407393 */
    408394static slab_magazine_t *get_full_current_mag(slab_cache_t *cache)
    409395{
    410         slab_magazine_t *cmag = cache->mag_cache[CPU->id].current;
    411         slab_magazine_t *lastmag = cache->mag_cache[CPU->id].last;
    412 
    413         ASSERT(spinlock_locked(&cache->mag_cache[CPU->id].lock));
    414        
     396        slab_magazine_t *cmag, *lastmag, *newmag;
     397
     398        cmag = cache->mag_cache[CPU->id].current;
     399        lastmag = cache->mag_cache[CPU->id].last;
    415400        if (cmag) { /* First try local CPU magazines */
    416401                if (cmag->busy)
    417402                        return cmag;
    418                
    419                 if ((lastmag) && (lastmag->busy)) {
     403
     404                if (lastmag && lastmag->busy) {
    420405                        cache->mag_cache[CPU->id].current = lastmag;
    421406                        cache->mag_cache[CPU->id].last = cmag;
     
    423408                }
    424409        }
    425        
    426410        /* Local magazines are empty, import one from magazine list */
    427         slab_magazine_t *newmag = get_mag_from_cache(cache, 1);
     411        newmag = get_mag_from_cache(cache, 1);
    428412        if (!newmag)
    429413                return NULL;
    430        
     414
    431415        if (lastmag)
    432416                magazine_destroy(cache, lastmag);
    433        
     417
    434418        cache->mag_cache[CPU->id].last = cmag;
    435419        cache->mag_cache[CPU->id].current = newmag;
    436        
    437420        return newmag;
    438421}
    439422
    440 /** Try to find object in CPU-cache magazines
     423/**
     424 * Try to find object in CPU-cache magazines
    441425 *
    442426 * @return Pointer to object or NULL if not available
    443  *
    444427 */
    445428static void *magazine_obj_get(slab_cache_t *cache)
    446429{
     430        slab_magazine_t *mag;
     431        void *obj;
     432
    447433        if (!CPU)
    448434                return NULL;
    449        
     435
    450436        spinlock_lock(&cache->mag_cache[CPU->id].lock);
    451        
    452         slab_magazine_t *mag = get_full_current_mag(cache);
     437
     438        mag = get_full_current_mag(cache);
    453439        if (!mag) {
    454440                spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    455441                return NULL;
    456442        }
    457        
    458         void *obj = mag->objs[--mag->busy];
     443        obj = mag->objs[--mag->busy];
    459444        spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    460        
    461445        atomic_dec(&cache->cached_objs);
    462446       
     
    464448}
    465449
    466 /** Assure that the current magazine is empty, return pointer to it,
    467  * or NULL if no empty magazine is available and cannot be allocated
    468  *
    469  * We have 2 magazines bound to processor.
    470  * First try the current.
    471  * If full, try the last.
    472  * If full, put to magazines list.
     450/**
     451 * Assure that the current magazine is empty, return pointer to it, or NULL if
     452 * no empty magazine is available and cannot be allocated
     453 *
     454 * Assume mag_cache[CPU->id].lock is held
     455 *
     456 * We have 2 magazines bound to processor.
     457 * First try the current.
     458 *  If full, try the last.
     459 *   If full, put to magazines list.
     460 *   allocate new, exchange last & current
    473461 *
    474462 */
    475463static slab_magazine_t *make_empty_current_mag(slab_cache_t *cache)
    476464{
    477         slab_magazine_t *cmag = cache->mag_cache[CPU->id].current;
    478         slab_magazine_t *lastmag = cache->mag_cache[CPU->id].last;
    479        
    480         ASSERT(spinlock_locked(&cache->mag_cache[CPU->id].lock));
     465        slab_magazine_t *cmag,*lastmag,*newmag;
     466
     467        cmag = cache->mag_cache[CPU->id].current;
     468        lastmag = cache->mag_cache[CPU->id].last;
    481469
    482470        if (cmag) {
    483471                if (cmag->busy < cmag->size)
    484472                        return cmag;
    485                
    486                 if ((lastmag) && (lastmag->busy < lastmag->size)) {
     473                if (lastmag && lastmag->busy < lastmag->size) {
    487474                        cache->mag_cache[CPU->id].last = cmag;
    488475                        cache->mag_cache[CPU->id].current = lastmag;
     
    490477                }
    491478        }
    492        
    493479        /* current | last are full | nonexistent, allocate new */
    494        
    495         /*
    496          * We do not want to sleep just because of caching,
    497          * especially we do not want reclaiming to start, as
    498          * this would deadlock.
    499          *
    500          */
    501         slab_magazine_t *newmag = slab_alloc(&mag_cache,
    502             FRAME_ATOMIC | FRAME_NO_RECLAIM);
     480        /* We do not want to sleep just because of caching */
     481        /* Especially we do not want reclaiming to start, as
     482         * this would deadlock */
     483        newmag = slab_alloc(&mag_cache, FRAME_ATOMIC | FRAME_NO_RECLAIM);
    503484        if (!newmag)
    504485                return NULL;
    505        
    506486        newmag->size = SLAB_MAG_SIZE;
    507487        newmag->busy = 0;
    508        
     488
    509489        /* Flush last to magazine list */
    510490        if (lastmag)
    511491                put_mag_to_cache(cache, lastmag);
    512        
     492
    513493        /* Move current as last, save new as current */
    514         cache->mag_cache[CPU->id].last = cmag;
    515         cache->mag_cache[CPU->id].current = newmag;
    516        
     494        cache->mag_cache[CPU->id].last = cmag; 
     495        cache->mag_cache[CPU->id].current = newmag;     
     496
    517497        return newmag;
    518498}
    519499
    520 /** Put object into CPU-cache magazine
    521  *
    522  * @return 0 on success, -1 on no memory
    523  *
     500/**
     501 * Put object into CPU-cache magazine
     502 *
     503 * @return 0 - success, -1 - could not get memory
    524504 */
    525505static int magazine_obj_put(slab_cache_t *cache, void *obj)
    526506{
     507        slab_magazine_t *mag;
     508
    527509        if (!CPU)
    528510                return -1;
    529        
     511
    530512        spinlock_lock(&cache->mag_cache[CPU->id].lock);
    531        
    532         slab_magazine_t *mag = make_empty_current_mag(cache);
     513
     514        mag = make_empty_current_mag(cache);
    533515        if (!mag) {
    534516                spinlock_unlock(&cache->mag_cache[CPU->id].lock);
     
    537519       
    538520        mag->objs[mag->busy++] = obj;
    539        
     521
    540522        spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    541        
    542523        atomic_inc(&cache->cached_objs);
    543        
    544524        return 0;
    545525}
    546526
    547 /************************/
     527
     528/**************************************/
    548529/* Slab cache functions */
    549 /************************/
    550 
    551 /** Return number of objects that fit in certain cache size
    552  *
    553  */
    554 static size_t comp_objects(slab_cache_t *cache)
     530
     531/** Return number of objects that fit in certain cache size */
     532static unsigned int comp_objects(slab_cache_t *cache)
    555533{
    556534        if (cache->flags & SLAB_CACHE_SLINSIDE)
    557                 return ((PAGE_SIZE << cache->order)
    558                     - sizeof(slab_t)) / cache->size;
    559         else
     535                return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) /
     536                    cache->size;
     537        else 
    560538                return (PAGE_SIZE << cache->order) / cache->size;
    561539}
    562540
    563 /** Return wasted space in slab
    564  *
    565  */
    566 static size_t badness(slab_cache_t *cache)
    567 {
    568         size_t objects = comp_objects(cache);
    569         size_t ssize = PAGE_SIZE << cache->order;
    570        
     541/** Return wasted space in slab */
     542static unsigned int badness(slab_cache_t *cache)
     543{
     544        unsigned int objects;
     545        unsigned int ssize;
     546
     547        objects = comp_objects(cache);
     548        ssize = PAGE_SIZE << cache->order;
    571549        if (cache->flags & SLAB_CACHE_SLINSIDE)
    572550                ssize -= sizeof(slab_t);
    573        
    574551        return ssize - objects * cache->size;
    575552}
    576553
    577 /** Initialize mag_cache structure in slab cache
    578  *
     554/**
     555 * Initialize mag_cache structure in slab cache
    579556 */
    580557static bool make_magcache(slab_cache_t *cache)
    581558{
     559        unsigned int i;
     560       
    582561        ASSERT(_slab_initialized >= 2);
    583        
     562
    584563        cache->mag_cache = malloc(sizeof(slab_mag_cache_t) * config.cpu_count,
    585564            FRAME_ATOMIC);
    586565        if (!cache->mag_cache)
    587566                return false;
    588        
    589         size_t i;
     567
    590568        for (i = 0; i < config.cpu_count; i++) {
    591569                memsetb(&cache->mag_cache[i], sizeof(cache->mag_cache[i]), 0);
    592570                spinlock_initialize(&cache->mag_cache[i].lock,
    593                     "slab.cache.mag_cache[].lock");
    594         }
    595        
     571                    "slab_maglock_cpu");
     572        }
    596573        return true;
    597574}
    598575
    599 /** Initialize allocated memory as a slab cache
    600  *
    601  */
     576/** Initialize allocated memory as a slab cache */
    602577static void _slab_cache_create(slab_cache_t *cache, const char *name,
    603     size_t size, size_t align, int (*constructor)(void *obj,
    604     unsigned int kmflag), size_t (*destructor)(void *obj), unsigned int flags)
    605 {
     578    size_t size, size_t align, int (*constructor)(void *obj, int kmflag),
     579    int (*destructor)(void *obj), int flags)
     580{
     581        int pages;
     582        ipl_t ipl;
     583
    606584        memsetb(cache, sizeof(*cache), 0);
    607585        cache->name = name;
    608        
     586
    609587        if (align < sizeof(unative_t))
    610588                align = sizeof(unative_t);
    611        
    612589        size = ALIGN_UP(size, align);
    613        
     590               
    614591        cache->size = size;
     592
    615593        cache->constructor = constructor;
    616594        cache->destructor = destructor;
    617595        cache->flags = flags;
    618        
     596
    619597        list_initialize(&cache->full_slabs);
    620598        list_initialize(&cache->partial_slabs);
    621599        list_initialize(&cache->magazines);
    622        
    623         spinlock_initialize(&cache->slablock, "slab.cache.slablock");
    624         spinlock_initialize(&cache->maglock, "slab.cache.maglock");
    625        
     600        spinlock_initialize(&cache->slablock, "slab_lock");
     601        spinlock_initialize(&cache->maglock, "slab_maglock");
    626602        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    627603                (void) make_magcache(cache);
    628        
     604
    629605        /* Compute slab sizes, object counts in slabs etc. */
    630606        if (cache->size < SLAB_INSIDE_SIZE)
    631607                cache->flags |= SLAB_CACHE_SLINSIDE;
    632        
     608
    633609        /* Minimum slab order */
    634         size_t pages = SIZE2FRAMES(cache->size);
    635        
     610        pages = SIZE2FRAMES(cache->size);
    636611        /* We need the 2^order >= pages */
    637612        if (pages == 1)
     
    639614        else
    640615                cache->order = fnzb(pages - 1) + 1;
    641        
    642         while (badness(cache) > SLAB_MAX_BADNESS(cache))
     616
     617        while (badness(cache) > SLAB_MAX_BADNESS(cache)) {
    643618                cache->order += 1;
    644        
     619        }
    645620        cache->objects = comp_objects(cache);
    646        
    647621        /* If info fits in, put it inside */
    648622        if (badness(cache) > sizeof(slab_t))
    649623                cache->flags |= SLAB_CACHE_SLINSIDE;
    650        
     624
    651625        /* Add cache to cache list */
    652         irq_spinlock_lock(&slab_cache_lock, true);
     626        ipl = interrupts_disable();
     627        spinlock_lock(&slab_cache_lock);
     628
    653629        list_append(&cache->link, &slab_cache_list);
    654         irq_spinlock_unlock(&slab_cache_lock, true);
    655 }
    656 
    657 /** Create slab cache
    658  *
    659  */
     630
     631        spinlock_unlock(&slab_cache_lock);
     632        interrupts_restore(ipl);
     633}
     634
     635/** Create slab cache */
    660636slab_cache_t *slab_cache_create(const char *name, size_t size, size_t align,
    661     int (*constructor)(void *obj, unsigned int kmflag),
    662     size_t (*destructor)(void *obj), unsigned int flags)
    663 {
    664         slab_cache_t *cache = slab_alloc(&slab_cache_cache, 0);
     637    int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
     638    int flags)
     639{
     640        slab_cache_t *cache;
     641
     642        cache = slab_alloc(&slab_cache_cache, 0);
    665643        _slab_cache_create(cache, name, size, align, constructor, destructor,
    666644            flags);
    667        
    668645        return cache;
    669646}
    670647
    671 /** Reclaim space occupied by objects that are already free
     648/**
     649 * Reclaim space occupied by objects that are already free
    672650 *
    673651 * @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing
    674  *
    675652 * @return Number of freed pages
    676  *
    677  */
    678 static size_t _slab_reclaim(slab_cache_t *cache, unsigned int flags)
    679 {
     653 */
     654static size_t _slab_reclaim(slab_cache_t *cache, int flags)
     655{
     656        unsigned int i;
     657        slab_magazine_t *mag;
     658        size_t frames = 0;
     659        int magcount;
     660       
    680661        if (cache->flags & SLAB_CACHE_NOMAGAZINE)
    681662                return 0; /* Nothing to do */
    682        
    683         /*
    684          * We count up to original magazine count to avoid
    685          * endless loop
     663
     664        /* We count up to original magazine count to avoid
     665         * endless loop
    686666         */
    687         atomic_count_t magcount = atomic_get(&cache->magazine_counter);
    688        
    689         slab_magazine_t *mag;
    690         size_t frames = 0;
    691        
    692         while ((magcount--) && (mag = get_mag_from_cache(cache, 0))) {
    693                 frames += magazine_destroy(cache, mag);
    694                 if ((!(flags & SLAB_RECLAIM_ALL)) && (frames))
     667        magcount = atomic_get(&cache->magazine_counter);
     668        while (magcount-- && (mag=get_mag_from_cache(cache, 0))) {
     669                frames += magazine_destroy(cache,mag);
     670                if (!(flags & SLAB_RECLAIM_ALL) && frames)
    695671                        break;
    696672        }
     
    699675                /* Free cpu-bound magazines */
    700676                /* Destroy CPU magazines */
    701                 size_t i;
    702677                for (i = 0; i < config.cpu_count; i++) {
    703678                        spinlock_lock(&cache->mag_cache[i].lock);
    704                        
     679
    705680                        mag = cache->mag_cache[i].current;
    706681                        if (mag)
     
    712687                                frames += magazine_destroy(cache, mag);
    713688                        cache->mag_cache[i].last = NULL;
    714                        
     689
    715690                        spinlock_unlock(&cache->mag_cache[i].lock);
    716691                }
    717692        }
    718        
     693
    719694        return frames;
    720695}
    721696
    722 /** Check that there are no slabs and remove cache from system
    723  *
    724  */
     697/** Check that there are no slabs and remove cache from system  */
    725698void slab_cache_destroy(slab_cache_t *cache)
    726699{
    727         /*
    728          * First remove cache from link, so that we don't need
     700        ipl_t ipl;
     701
     702        /* First remove cache from link, so that we don't need
    729703         * to disable interrupts later
    730          *
    731704         */
    732         irq_spinlock_lock(&slab_cache_lock, true);
     705
     706        ipl = interrupts_disable();
     707        spinlock_lock(&slab_cache_lock);
     708
    733709        list_remove(&cache->link);
    734         irq_spinlock_unlock(&slab_cache_lock, true);
    735        
    736         /*
    737          * Do not lock anything, we assume the software is correct and
    738          * does not touch the cache when it decides to destroy it
    739          *
    740          */
     710
     711        spinlock_unlock(&slab_cache_lock);
     712        interrupts_restore(ipl);
     713
     714        /* Do not lock anything, we assume the software is correct and
     715         * does not touch the cache when it decides to destroy it */
    741716       
    742717        /* Destroy all magazines */
    743718        _slab_reclaim(cache, SLAB_RECLAIM_ALL);
    744        
     719
    745720        /* All slabs must be empty */
    746         if ((!list_empty(&cache->full_slabs)) ||
    747             (!list_empty(&cache->partial_slabs)))
     721        if (!list_empty(&cache->full_slabs) ||
     722            !list_empty(&cache->partial_slabs))
    748723                panic("Destroying cache that is not empty.");
    749        
     724
    750725        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    751726                free(cache->mag_cache);
    752        
    753727        slab_free(&slab_cache_cache, cache);
    754728}
    755729
    756 /** Allocate new object from cache - if no flags given, always returns memory
    757  *
    758  */
    759 void *slab_alloc(slab_cache_t *cache, unsigned int flags)
    760 {
     730/** Allocate new object from cache - if no flags given, always returns memory */
     731void *slab_alloc(slab_cache_t *cache, int flags)
     732{
     733        ipl_t ipl;
     734        void *result = NULL;
     735       
    761736        /* Disable interrupts to avoid deadlocks with interrupt handlers */
    762         ipl_t ipl = interrupts_disable();
    763        
    764         void *result = NULL;
    765        
    766         if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
     737        ipl = interrupts_disable();
     738
     739        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) {
    767740                result = magazine_obj_get(cache);
    768        
     741        }
    769742        if (!result)
    770743                result = slab_obj_create(cache, flags);
    771        
     744
    772745        interrupts_restore(ipl);
    773        
     746
    774747        if (result)
    775748                atomic_inc(&cache->allocated_objs);
    776        
     749
    777750        return result;
    778751}
    779752
    780 /** Return object to cache, use slab if known
    781  *
    782  */
     753/** Return object to cache, use slab if known  */
    783754static void _slab_free(slab_cache_t *cache, void *obj, slab_t *slab)
    784755{
    785         ipl_t ipl = interrupts_disable();
    786        
     756        ipl_t ipl;
     757
     758        ipl = interrupts_disable();
     759
    787760        if ((cache->flags & SLAB_CACHE_NOMAGAZINE) ||
    788             (magazine_obj_put(cache, obj)))
     761            magazine_obj_put(cache, obj)) {
    789762                slab_obj_destroy(cache, obj, slab);
    790        
     763
     764        }
    791765        interrupts_restore(ipl);
    792766        atomic_dec(&cache->allocated_objs);
    793767}
    794768
    795 /** Return slab object to cache
    796  *
    797  */
     769/** Return slab object to cache */
    798770void slab_free(slab_cache_t *cache, void *obj)
    799771{
     
    801773}
    802774
    803 /** Go through all caches and reclaim what is possible
    804  *
    805  * Interrupts must be disabled before calling this function,
    806  * otherwise  memory allocation from interrupts can deadlock.
    807  *
    808  */
    809 size_t slab_reclaim(unsigned int flags)
    810 {
    811         irq_spinlock_lock(&slab_cache_lock, false);
    812        
     775/* Go through all caches and reclaim what is possible */
     776size_t slab_reclaim(int flags)
     777{
     778        slab_cache_t *cache;
     779        link_t *cur;
    813780        size_t frames = 0;
    814         link_t *cur;
     781
     782        spinlock_lock(&slab_cache_lock);
     783
     784        /* TODO: Add assert, that interrupts are disabled, otherwise
     785         * memory allocation from interrupts can deadlock.
     786         */
     787
    815788        for (cur = slab_cache_list.next; cur != &slab_cache_list;
    816789            cur = cur->next) {
    817                 slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
     790                cache = list_get_instance(cur, slab_cache_t, link);
    818791                frames += _slab_reclaim(cache, flags);
    819792        }
    820        
    821         irq_spinlock_unlock(&slab_cache_lock, false);
    822        
     793
     794        spinlock_unlock(&slab_cache_lock);
     795
    823796        return frames;
    824797}
    825798
    826 /* Print list of slabs
    827  *
    828  */
     799
     800/* Print list of slabs */
    829801void slab_print_list(void)
    830802{
    831         printf("slab name        size     pages  obj/pg   slabs  cached allocated"
     803        int skip = 0;
     804
     805        printf("slab name        size     pages  obj/pg slabs  cached allocated"
    832806            " ctl\n");
    833         printf("---------------- -------- ------ -------- ------ ------ ---------"
     807        printf("---------------- -------- ------ ------ ------ ------ ---------"
    834808            " ---\n");
    835        
    836         size_t skip = 0;
     809
    837810        while (true) {
     811                slab_cache_t *cache;
     812                link_t *cur;
     813                ipl_t ipl;
     814                int i;
     815
    838816                /*
    839817                 * We must not hold the slab_cache_lock spinlock when printing
     
    858836                 * statistics.
    859837                 */
    860                
    861                 irq_spinlock_lock(&slab_cache_lock, true);
    862                
    863                 link_t *cur;
    864                 size_t i;
     838
     839                ipl = interrupts_disable();
     840                spinlock_lock(&slab_cache_lock);
     841
    865842                for (i = 0, cur = slab_cache_list.next;
    866                     (i < skip) && (cur != &slab_cache_list);
    867                     i++, cur = cur->next);
    868                
     843                    i < skip && cur != &slab_cache_list;
     844                    i++, cur = cur->next)
     845                        ;
     846
    869847                if (cur == &slab_cache_list) {
    870                         irq_spinlock_unlock(&slab_cache_lock, true);
     848                        spinlock_unlock(&slab_cache_lock);
     849                        interrupts_restore(ipl);
    871850                        break;
    872851                }
    873                
     852
    874853                skip++;
    875                
    876                 slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
    877                
     854
     855                cache = list_get_instance(cur, slab_cache_t, link);
     856
    878857                const char *name = cache->name;
    879858                uint8_t order = cache->order;
    880859                size_t size = cache->size;
    881                 size_t objects = cache->objects;
     860                unsigned int objects = cache->objects;
    882861                long allocated_slabs = atomic_get(&cache->allocated_slabs);
    883862                long cached_objs = atomic_get(&cache->cached_objs);
    884863                long allocated_objs = atomic_get(&cache->allocated_objs);
    885                 unsigned int flags = cache->flags;
     864                int flags = cache->flags;
    886865               
    887                 irq_spinlock_unlock(&slab_cache_lock, true);
     866                spinlock_unlock(&slab_cache_lock);
     867                interrupts_restore(ipl);
    888868               
    889                 printf("%-16s %8" PRIs " %6u %8" PRIs " %6ld %6ld %9ld %-3s\n",
     869                printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n",
    890870                    name, size, (1 << order), objects, allocated_slabs,
    891871                    cached_objs, allocated_objs,
     
    896876void slab_cache_init(void)
    897877{
     878        int i, size;
     879
    898880        /* Initialize magazine cache */
    899881        _slab_cache_create(&mag_cache, "slab_magazine",
     
    901883            sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE |
    902884            SLAB_CACHE_SLINSIDE);
    903        
    904885        /* Initialize slab_cache cache */
    905886        _slab_cache_create(&slab_cache_cache, "slab_cache",
    906887            sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL,
    907888            SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
    908        
    909889        /* Initialize external slab cache */
    910890        slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0,
    911891            NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED);
    912        
     892
    913893        /* Initialize structures for malloc */
    914         size_t i;
    915         size_t size;
    916        
    917894        for (i = 0, size = (1 << SLAB_MIN_MALLOC_W);
    918895            i < (SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1);
     
    921898                    NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    922899        }
    923        
    924900#ifdef CONFIG_DEBUG
    925901        _slab_initialized = 1;
     
    930906 *
    931907 * Kernel calls this function, when it knows the real number of
    932  * processors. Allocate slab for cpucache and enable it on all
    933  * existing slabs that are SLAB_CACHE_MAGDEFERRED
    934  *
     908 * processors.
     909 * Allocate slab for cpucache and enable it on all existing
     910 * slabs that are SLAB_CACHE_MAGDEFERRED
    935911 */
    936912void slab_enable_cpucache(void)
    937913{
     914        link_t *cur;
     915        slab_cache_t *s;
     916
    938917#ifdef CONFIG_DEBUG
    939918        _slab_initialized = 2;
    940919#endif
    941        
    942         irq_spinlock_lock(&slab_cache_lock, false);
    943        
    944         link_t *cur;
     920
     921        spinlock_lock(&slab_cache_lock);
     922       
    945923        for (cur = slab_cache_list.next; cur != &slab_cache_list;
    946             cur = cur->next) {
    947                 slab_cache_t *slab = list_get_instance(cur, slab_cache_t, link);
    948                 if ((slab->flags & SLAB_CACHE_MAGDEFERRED) !=
     924            cur = cur->next){
     925                s = list_get_instance(cur, slab_cache_t, link);
     926                if ((s->flags & SLAB_CACHE_MAGDEFERRED) !=
    949927                    SLAB_CACHE_MAGDEFERRED)
    950928                        continue;
    951                
    952                 (void) make_magcache(slab);
    953                 slab->flags &= ~SLAB_CACHE_MAGDEFERRED;
    954         }
    955        
    956         irq_spinlock_unlock(&slab_cache_lock, false);
    957 }
    958 
    959 void *malloc(size_t size, unsigned int flags)
     929                (void) make_magcache(s);
     930                s->flags &= ~SLAB_CACHE_MAGDEFERRED;
     931        }
     932
     933        spinlock_unlock(&slab_cache_lock);
     934}
     935
     936/**************************************/
     937/* kalloc/kfree functions             */
     938void *malloc(unsigned int size, int flags)
    960939{
    961940        ASSERT(_slab_initialized);
     
    964943        if (size < (1 << SLAB_MIN_MALLOC_W))
    965944                size = (1 << SLAB_MIN_MALLOC_W);
    966        
    967         uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
    968        
     945
     946        int idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
     947
    969948        return slab_alloc(malloc_caches[idx], flags);
    970949}
    971950
    972 void *realloc(void *ptr, size_t size, unsigned int flags)
     951void *realloc(void *ptr, unsigned int size, int flags)
    973952{
    974953        ASSERT(_slab_initialized);
     
    980959                if (size < (1 << SLAB_MIN_MALLOC_W))
    981960                        size = (1 << SLAB_MIN_MALLOC_W);
    982                 uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
     961                int idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
    983962               
    984963                new_ptr = slab_alloc(malloc_caches[idx], flags);
     
    1001980        if (!ptr)
    1002981                return;
    1003        
     982
    1004983        slab_t *slab = obj2slab(ptr);
    1005984        _slab_free(slab->cache, ptr, slab);
Note: See TracChangeset for help on using the changeset viewer.