Ignore:
File:
1 edited

Legend:

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

    rab6f2507 r98000fb  
    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 
    137 static const char *malloc_names[] =  {
     132static char *malloc_names[] =  {
    138133        "malloc-16",
    139134        "malloc-32",
     
    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 NO_TRACE static slab_t *slab_space_alloc(slab_cache_t *cache,
    180     unsigned int flags)
    181 {
    182        
    183        
     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;
    184180        size_t zone = 0;
    185181       
    186         void *data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
     182        data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
    187183        if (!data) {
    188184                return NULL;
    189185        }
    190        
    191         slab_t *slab;
    192         size_t fsize;
    193        
    194186        if (!(cache->flags & SLAB_CACHE_SLINSIDE)) {
    195187                slab = slab_alloc(slab_extern_cache, flags);
     
    204196       
    205197        /* Fill in slab structures */
    206         size_t i;
    207         for (i = 0; i < ((size_t) 1 << cache->order); i++)
     198        for (i = 0; i < ((unsigned int) 1 << cache->order); i++)
    208199                frame_set_parent(ADDR2PFN(KA2PA(data)) + i, slab, zone);
    209        
     200
    210201        slab->start = data;
    211202        slab->available = cache->objects;
    212203        slab->nextavail = 0;
    213204        slab->cache = cache;
    214        
     205
    215206        for (i = 0; i < cache->objects; i++)
    216                 *((size_t *) (slab->start + i * cache->size)) = i + 1;
    217        
     207                *((int *) (slab->start + i*cache->size)) = i + 1;
     208
    218209        atomic_inc(&cache->allocated_slabs);
    219210        return slab;
    220211}
    221212
    222 /** Deallocate space associated with slab
     213/**
     214 * Deallocate space associated with slab
    223215 *
    224216 * @return number of freed frames
    225  *
    226  */
    227 NO_TRACE static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
     217 */
     218static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
    228219{
    229220        frame_free(KA2PA(slab->start));
    230         if (!(cache->flags & SLAB_CACHE_SLINSIDE))
     221        if (! (cache->flags & SLAB_CACHE_SLINSIDE))
    231222                slab_free(slab_extern_cache, slab);
    232        
     223
    233224        atomic_dec(&cache->allocated_slabs);
    234225       
    235         return (1 << cache->order);
     226        return 1 << cache->order;
    236227}
    237228
    238229/** Map object to slab structure */
    239 NO_TRACE static slab_t *obj2slab(void *obj)
     230static slab_t * obj2slab(void *obj)
    240231{
    241232        return (slab_t *) frame_get_parent(ADDR2PFN(KA2PA(obj)), 0);
    242233}
    243234
    244 /******************/
     235/**************************************/
    245236/* Slab functions */
    246 /******************/
    247 
    248 /** Return object to slab and call a destructor
     237
     238
     239/**
     240 * Return object to slab and call a destructor
    249241 *
    250242 * @param slab If the caller knows directly slab of the object, otherwise NULL
    251243 *
    252244 * @return Number of freed pages
    253  *
    254  */
    255 NO_TRACE static size_t slab_obj_destroy(slab_cache_t *cache, void *obj,
    256     slab_t *slab)
    257 {
     245 */
     246static size_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
     247{
     248        int freed = 0;
     249
    258250        if (!slab)
    259251                slab = obj2slab(obj);
    260        
     252
    261253        ASSERT(slab->cache == cache);
    262        
    263         size_t freed = 0;
    264        
     254
    265255        if (cache->destructor)
    266256                freed = cache->destructor(obj);
     
    268258        spinlock_lock(&cache->slablock);
    269259        ASSERT(slab->available < cache->objects);
    270        
    271         *((size_t *) obj) = slab->nextavail;
     260
     261        *((int *)obj) = slab->nextavail;
    272262        slab->nextavail = (obj - slab->start) / cache->size;
    273263        slab->available++;
    274        
     264
    275265        /* Move it to correct list */
    276266        if (slab->available == cache->objects) {
     
    278268                list_remove(&slab->link);
    279269                spinlock_unlock(&cache->slablock);
    280                
     270
    281271                return freed + slab_space_free(cache, slab);
     272
    282273        } else if (slab->available == 1) {
    283274                /* It was in full, move to partial */
     
    285276                list_prepend(&slab->link, &cache->partial_slabs);
    286277        }
    287        
    288278        spinlock_unlock(&cache->slablock);
    289279        return freed;
    290280}
    291281
    292 /** Take new object from slab or create new if needed
     282/**
     283 * Take new object from slab or create new if needed
    293284 *
    294285 * @return Object address or null
    295  *
    296  */
    297 NO_TRACE static void *slab_obj_create(slab_cache_t *cache, unsigned int flags)
    298 {
     286 */
     287static void *slab_obj_create(slab_cache_t *cache, int flags)
     288{
     289        slab_t *slab;
     290        void *obj;
     291
    299292        spinlock_lock(&cache->slablock);
    300        
    301         slab_t *slab;
    302        
     293
    303294        if (list_empty(&cache->partial_slabs)) {
    304                 /*
    305                  * Allow recursion and reclaiming
     295                /* Allow recursion and reclaiming
    306296                 * - this should work, as the slab control structures
    307297                 *   are small and do not need to allocate with anything
    308298                 *   other than frame_alloc when they are allocating,
    309299                 *   that's why we should get recursion at most 1-level deep
    310                  *
    311300                 */
    312301                spinlock_unlock(&cache->slablock);
     
    314303                if (!slab)
    315304                        return NULL;
    316                
    317305                spinlock_lock(&cache->slablock);
    318306        } else {
     
    321309                list_remove(&slab->link);
    322310        }
    323        
    324         void *obj = slab->start + slab->nextavail * cache->size;
    325         slab->nextavail = *((size_t *) obj);
     311        obj = slab->start + slab->nextavail * cache->size;
     312        slab->nextavail = *((int *)obj);
    326313        slab->available--;
    327        
     314
    328315        if (!slab->available)
    329316                list_prepend(&slab->link, &cache->full_slabs);
    330317        else
    331318                list_prepend(&slab->link, &cache->partial_slabs);
    332        
     319
    333320        spinlock_unlock(&cache->slablock);
    334        
    335         if ((cache->constructor) && (cache->constructor(obj, flags))) {
     321
     322        if (cache->constructor && cache->constructor(obj, flags)) {
    336323                /* Bad, bad, construction failed */
    337324                slab_obj_destroy(cache, obj, slab);
    338325                return NULL;
    339326        }
    340        
    341327        return obj;
    342328}
    343329
    344 /****************************/
     330/**************************************/
    345331/* CPU-Cache slab functions */
    346 /****************************/
    347 
    348 /** Find a full magazine in cache, take it from list and return it
    349  *
    350  * @param first If true, return first, else last mag.
    351  *
    352  */
    353 NO_TRACE static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache,
    354     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)
    355340{
    356341        slab_magazine_t *mag = NULL;
    357342        link_t *cur;
    358        
     343
    359344        spinlock_lock(&cache->maglock);
    360345        if (!list_empty(&cache->magazines)) {
     
    363348                else
    364349                        cur = cache->magazines.prev;
    365                
    366350                mag = list_get_instance(cur, slab_magazine_t, link);
    367351                list_remove(&mag->link);
    368352                atomic_dec(&cache->magazine_counter);
    369353        }
    370        
    371354        spinlock_unlock(&cache->maglock);
    372355        return mag;
    373356}
    374357
    375 /** Prepend magazine to magazine list in cache
    376  *
    377  */
    378 NO_TRACE static void put_mag_to_cache(slab_cache_t *cache,
    379     slab_magazine_t *mag)
     358/** Prepend magazine to magazine list in cache */
     359static void put_mag_to_cache(slab_cache_t *cache, slab_magazine_t *mag)
    380360{
    381361        spinlock_lock(&cache->maglock);
    382        
     362
    383363        list_prepend(&mag->link, &cache->magazines);
    384364        atomic_inc(&cache->magazine_counter);
     
    387367}
    388368
    389 /** Free all objects in magazine and free memory associated with magazine
     369/**
     370 * Free all objects in magazine and free memory associated with magazine
    390371 *
    391372 * @return Number of freed pages
    392  *
    393  */
    394 NO_TRACE static size_t magazine_destroy(slab_cache_t *cache,
    395     slab_magazine_t *mag)
    396 {
    397         size_t i;
     373 */
     374static size_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
     375{
     376        unsigned int i;
    398377        size_t frames = 0;
    399        
     378
    400379        for (i = 0; i < mag->busy; i++) {
    401380                frames += slab_obj_destroy(cache, mag->objs[i], NULL);
     
    404383       
    405384        slab_free(&mag_cache, mag);
    406        
     385
    407386        return frames;
    408387}
    409388
    410 /** Find full magazine, set it as current and return it
    411  *
    412  */
    413 NO_TRACE static slab_magazine_t *get_full_current_mag(slab_cache_t *cache)
    414 {
    415         slab_magazine_t *cmag = cache->mag_cache[CPU->id].current;
    416         slab_magazine_t *lastmag = cache->mag_cache[CPU->id].last;
    417        
    418         ASSERT(spinlock_locked(&cache->mag_cache[CPU->id].lock));
    419        
     389/**
     390 * Find full magazine, set it as current and return it
     391 *
     392 * Assume cpu_magazine lock is held
     393 */
     394static slab_magazine_t *get_full_current_mag(slab_cache_t *cache)
     395{
     396        slab_magazine_t *cmag, *lastmag, *newmag;
     397
     398        cmag = cache->mag_cache[CPU->id].current;
     399        lastmag = cache->mag_cache[CPU->id].last;
    420400        if (cmag) { /* First try local CPU magazines */
    421401                if (cmag->busy)
    422402                        return cmag;
    423                
    424                 if ((lastmag) && (lastmag->busy)) {
     403
     404                if (lastmag && lastmag->busy) {
    425405                        cache->mag_cache[CPU->id].current = lastmag;
    426406                        cache->mag_cache[CPU->id].last = cmag;
     
    428408                }
    429409        }
    430        
    431410        /* Local magazines are empty, import one from magazine list */
    432         slab_magazine_t *newmag = get_mag_from_cache(cache, 1);
     411        newmag = get_mag_from_cache(cache, 1);
    433412        if (!newmag)
    434413                return NULL;
    435        
     414
    436415        if (lastmag)
    437416                magazine_destroy(cache, lastmag);
    438        
     417
    439418        cache->mag_cache[CPU->id].last = cmag;
    440419        cache->mag_cache[CPU->id].current = newmag;
    441        
    442420        return newmag;
    443421}
    444422
    445 /** Try to find object in CPU-cache magazines
     423/**
     424 * Try to find object in CPU-cache magazines
    446425 *
    447426 * @return Pointer to object or NULL if not available
    448  *
    449  */
    450 NO_TRACE static void *magazine_obj_get(slab_cache_t *cache)
    451 {
     427 */
     428static void *magazine_obj_get(slab_cache_t *cache)
     429{
     430        slab_magazine_t *mag;
     431        void *obj;
     432
    452433        if (!CPU)
    453434                return NULL;
    454        
     435
    455436        spinlock_lock(&cache->mag_cache[CPU->id].lock);
    456        
    457         slab_magazine_t *mag = get_full_current_mag(cache);
     437
     438        mag = get_full_current_mag(cache);
    458439        if (!mag) {
    459440                spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    460441                return NULL;
    461442        }
    462        
    463         void *obj = mag->objs[--mag->busy];
     443        obj = mag->objs[--mag->busy];
    464444        spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    465        
    466445        atomic_dec(&cache->cached_objs);
    467446       
     
    469448}
    470449
    471 /** Assure that the current magazine is empty, return pointer to it,
    472  * or NULL if no empty magazine is available and cannot be allocated
    473  *
    474  * We have 2 magazines bound to processor.
    475  * First try the current.
    476  * If full, try the last.
    477  * If full, put to magazines list.
    478  *
    479  */
    480 NO_TRACE static slab_magazine_t *make_empty_current_mag(slab_cache_t *cache)
    481 {
    482         slab_magazine_t *cmag = cache->mag_cache[CPU->id].current;
    483         slab_magazine_t *lastmag = cache->mag_cache[CPU->id].last;
    484        
    485         ASSERT(spinlock_locked(&cache->mag_cache[CPU->id].lock));
    486        
     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
     461 *
     462 */
     463static slab_magazine_t *make_empty_current_mag(slab_cache_t *cache)
     464{
     465        slab_magazine_t *cmag,*lastmag,*newmag;
     466
     467        cmag = cache->mag_cache[CPU->id].current;
     468        lastmag = cache->mag_cache[CPU->id].last;
     469
    487470        if (cmag) {
    488471                if (cmag->busy < cmag->size)
    489472                        return cmag;
    490                
    491                 if ((lastmag) && (lastmag->busy < lastmag->size)) {
     473                if (lastmag && lastmag->busy < lastmag->size) {
    492474                        cache->mag_cache[CPU->id].last = cmag;
    493475                        cache->mag_cache[CPU->id].current = lastmag;
     
    495477                }
    496478        }
    497        
    498479        /* current | last are full | nonexistent, allocate new */
    499        
    500         /*
    501          * We do not want to sleep just because of caching,
    502          * especially we do not want reclaiming to start, as
    503          * this would deadlock.
    504          *
    505          */
    506         slab_magazine_t *newmag = slab_alloc(&mag_cache,
    507             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);
    508484        if (!newmag)
    509485                return NULL;
    510        
    511486        newmag->size = SLAB_MAG_SIZE;
    512487        newmag->busy = 0;
    513        
     488
    514489        /* Flush last to magazine list */
    515490        if (lastmag)
    516491                put_mag_to_cache(cache, lastmag);
    517        
     492
    518493        /* Move current as last, save new as current */
    519         cache->mag_cache[CPU->id].last = cmag;
    520         cache->mag_cache[CPU->id].current = newmag;
    521        
     494        cache->mag_cache[CPU->id].last = cmag; 
     495        cache->mag_cache[CPU->id].current = newmag;     
     496
    522497        return newmag;
    523498}
    524499
    525 /** Put object into CPU-cache magazine
    526  *
    527  * @return 0 on success, -1 on no memory
    528  *
    529  */
    530 NO_TRACE static int magazine_obj_put(slab_cache_t *cache, void *obj)
    531 {
     500/**
     501 * Put object into CPU-cache magazine
     502 *
     503 * @return 0 - success, -1 - could not get memory
     504 */
     505static int magazine_obj_put(slab_cache_t *cache, void *obj)
     506{
     507        slab_magazine_t *mag;
     508
    532509        if (!CPU)
    533510                return -1;
    534        
     511
    535512        spinlock_lock(&cache->mag_cache[CPU->id].lock);
    536        
    537         slab_magazine_t *mag = make_empty_current_mag(cache);
     513
     514        mag = make_empty_current_mag(cache);
    538515        if (!mag) {
    539516                spinlock_unlock(&cache->mag_cache[CPU->id].lock);
     
    542519       
    543520        mag->objs[mag->busy++] = obj;
    544        
     521
    545522        spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    546        
    547523        atomic_inc(&cache->cached_objs);
    548        
    549524        return 0;
    550525}
    551526
    552 /************************/
     527
     528/**************************************/
    553529/* Slab cache functions */
    554 /************************/
    555 
    556 /** Return number of objects that fit in certain cache size
    557  *
    558  */
    559 NO_TRACE 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)
    560533{
    561534        if (cache->flags & SLAB_CACHE_SLINSIDE)
    562                 return ((PAGE_SIZE << cache->order)
    563                     - sizeof(slab_t)) / cache->size;
    564         else
     535                return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) /
     536                    cache->size;
     537        else 
    565538                return (PAGE_SIZE << cache->order) / cache->size;
    566539}
    567540
    568 /** Return wasted space in slab
    569  *
    570  */
    571 NO_TRACE static size_t badness(slab_cache_t *cache)
    572 {
    573         size_t objects = comp_objects(cache);
    574         size_t ssize = PAGE_SIZE << cache->order;
    575        
     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;
    576549        if (cache->flags & SLAB_CACHE_SLINSIDE)
    577550                ssize -= sizeof(slab_t);
    578        
    579551        return ssize - objects * cache->size;
    580552}
    581553
    582 /** Initialize mag_cache structure in slab cache
    583  *
    584  */
    585 NO_TRACE static bool make_magcache(slab_cache_t *cache)
    586 {
     554/**
     555 * Initialize mag_cache structure in slab cache
     556 */
     557static void make_magcache(slab_cache_t *cache)
     558{
     559        unsigned int i;
     560       
    587561        ASSERT(_slab_initialized >= 2);
    588        
     562
    589563        cache->mag_cache = malloc(sizeof(slab_mag_cache_t) * config.cpu_count,
    590             FRAME_ATOMIC);
    591         if (!cache->mag_cache)
    592                 return false;
    593        
    594         size_t i;
     564            0);
    595565        for (i = 0; i < config.cpu_count; i++) {
    596566                memsetb(&cache->mag_cache[i], sizeof(cache->mag_cache[i]), 0);
    597567                spinlock_initialize(&cache->mag_cache[i].lock,
    598                     "slab.cache.mag_cache[].lock");
    599         }
    600        
    601         return true;
    602 }
    603 
    604 /** Initialize allocated memory as a slab cache
    605  *
    606  */
    607 NO_TRACE static void _slab_cache_create(slab_cache_t *cache, const char *name,
    608     size_t size, size_t align, int (*constructor)(void *obj,
    609     unsigned int kmflag), size_t (*destructor)(void *obj), unsigned int flags)
    610 {
     568                    "slab_maglock_cpu");
     569        }
     570}
     571
     572/** Initialize allocated memory as a slab cache */
     573static void
     574_slab_cache_create(slab_cache_t *cache, char *name, size_t size, size_t align,
     575    int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
     576    int flags)
     577{
     578        int pages;
     579        ipl_t ipl;
     580
    611581        memsetb(cache, sizeof(*cache), 0);
    612582        cache->name = name;
    613        
    614         if (align < sizeof(sysarg_t))
    615                 align = sizeof(sysarg_t);
    616        
     583
     584        if (align < sizeof(unative_t))
     585                align = sizeof(unative_t);
    617586        size = ALIGN_UP(size, align);
    618        
     587               
    619588        cache->size = size;
     589
    620590        cache->constructor = constructor;
    621591        cache->destructor = destructor;
    622592        cache->flags = flags;
    623        
     593
    624594        list_initialize(&cache->full_slabs);
    625595        list_initialize(&cache->partial_slabs);
    626596        list_initialize(&cache->magazines);
    627        
    628         spinlock_initialize(&cache->slablock, "slab.cache.slablock");
    629         spinlock_initialize(&cache->maglock, "slab.cache.maglock");
    630        
     597        spinlock_initialize(&cache->slablock, "slab_lock");
     598        spinlock_initialize(&cache->maglock, "slab_maglock");
    631599        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    632                 (void) make_magcache(cache);
    633        
     600                make_magcache(cache);
     601
    634602        /* Compute slab sizes, object counts in slabs etc. */
    635603        if (cache->size < SLAB_INSIDE_SIZE)
    636604                cache->flags |= SLAB_CACHE_SLINSIDE;
    637        
     605
    638606        /* Minimum slab order */
    639         size_t pages = SIZE2FRAMES(cache->size);
    640        
     607        pages = SIZE2FRAMES(cache->size);
    641608        /* We need the 2^order >= pages */
    642609        if (pages == 1)
     
    644611        else
    645612                cache->order = fnzb(pages - 1) + 1;
    646        
    647         while (badness(cache) > SLAB_MAX_BADNESS(cache))
     613
     614        while (badness(cache) > SLAB_MAX_BADNESS(cache)) {
    648615                cache->order += 1;
    649        
     616        }
    650617        cache->objects = comp_objects(cache);
    651        
    652618        /* If info fits in, put it inside */
    653619        if (badness(cache) > sizeof(slab_t))
    654620                cache->flags |= SLAB_CACHE_SLINSIDE;
    655        
     621
    656622        /* Add cache to cache list */
    657         irq_spinlock_lock(&slab_cache_lock, true);
     623        ipl = interrupts_disable();
     624        spinlock_lock(&slab_cache_lock);
     625
    658626        list_append(&cache->link, &slab_cache_list);
    659         irq_spinlock_unlock(&slab_cache_lock, true);
    660 }
    661 
    662 /** Create slab cache
    663  *
    664  */
    665 slab_cache_t *slab_cache_create(const char *name, size_t size, size_t align,
    666     int (*constructor)(void *obj, unsigned int kmflag),
    667     size_t (*destructor)(void *obj), unsigned int flags)
    668 {
    669         slab_cache_t *cache = slab_alloc(&slab_cache_cache, 0);
     627
     628        spinlock_unlock(&slab_cache_lock);
     629        interrupts_restore(ipl);
     630}
     631
     632/** Create slab cache  */
     633slab_cache_t *
     634slab_cache_create(char *name, size_t size, size_t align,
     635    int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
     636    int flags)
     637{
     638        slab_cache_t *cache;
     639
     640        cache = slab_alloc(&slab_cache_cache, 0);
    670641        _slab_cache_create(cache, name, size, align, constructor, destructor,
    671642            flags);
    672        
    673643        return cache;
    674644}
    675645
    676 /** Reclaim space occupied by objects that are already free
     646/**
     647 * Reclaim space occupied by objects that are already free
    677648 *
    678649 * @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing
    679  *
    680650 * @return Number of freed pages
    681  *
    682  */
    683 NO_TRACE static size_t _slab_reclaim(slab_cache_t *cache, unsigned int flags)
    684 {
     651 */
     652static size_t _slab_reclaim(slab_cache_t *cache, int flags)
     653{
     654        unsigned int i;
     655        slab_magazine_t *mag;
     656        size_t frames = 0;
     657        int magcount;
     658       
    685659        if (cache->flags & SLAB_CACHE_NOMAGAZINE)
    686660                return 0; /* Nothing to do */
    687        
    688         /*
    689          * We count up to original magazine count to avoid
    690          * endless loop
     661
     662        /* We count up to original magazine count to avoid
     663         * endless loop
    691664         */
    692         atomic_count_t magcount = atomic_get(&cache->magazine_counter);
    693        
    694         slab_magazine_t *mag;
    695         size_t frames = 0;
    696        
    697         while ((magcount--) && (mag = get_mag_from_cache(cache, 0))) {
    698                 frames += magazine_destroy(cache, mag);
    699                 if ((!(flags & SLAB_RECLAIM_ALL)) && (frames))
     665        magcount = atomic_get(&cache->magazine_counter);
     666        while (magcount-- && (mag=get_mag_from_cache(cache, 0))) {
     667                frames += magazine_destroy(cache,mag);
     668                if (!(flags & SLAB_RECLAIM_ALL) && frames)
    700669                        break;
    701670        }
     
    704673                /* Free cpu-bound magazines */
    705674                /* Destroy CPU magazines */
    706                 size_t i;
    707675                for (i = 0; i < config.cpu_count; i++) {
    708676                        spinlock_lock(&cache->mag_cache[i].lock);
    709                        
     677
    710678                        mag = cache->mag_cache[i].current;
    711679                        if (mag)
     
    717685                                frames += magazine_destroy(cache, mag);
    718686                        cache->mag_cache[i].last = NULL;
    719                        
     687
    720688                        spinlock_unlock(&cache->mag_cache[i].lock);
    721689                }
    722690        }
    723        
     691
    724692        return frames;
    725693}
    726694
    727 /** Check that there are no slabs and remove cache from system
    728  *
    729  */
     695/** Check that there are no slabs and remove cache from system  */
    730696void slab_cache_destroy(slab_cache_t *cache)
    731697{
    732         /*
    733          * First remove cache from link, so that we don't need
     698        ipl_t ipl;
     699
     700        /* First remove cache from link, so that we don't need
    734701         * to disable interrupts later
    735          *
    736702         */
    737         irq_spinlock_lock(&slab_cache_lock, true);
     703
     704        ipl = interrupts_disable();
     705        spinlock_lock(&slab_cache_lock);
     706
    738707        list_remove(&cache->link);
    739         irq_spinlock_unlock(&slab_cache_lock, true);
    740        
    741         /*
    742          * Do not lock anything, we assume the software is correct and
    743          * does not touch the cache when it decides to destroy it
    744          *
    745          */
     708
     709        spinlock_unlock(&slab_cache_lock);
     710        interrupts_restore(ipl);
     711
     712        /* Do not lock anything, we assume the software is correct and
     713         * does not touch the cache when it decides to destroy it */
    746714       
    747715        /* Destroy all magazines */
    748716        _slab_reclaim(cache, SLAB_RECLAIM_ALL);
    749        
     717
    750718        /* All slabs must be empty */
    751         if ((!list_empty(&cache->full_slabs)) ||
    752             (!list_empty(&cache->partial_slabs)))
     719        if (!list_empty(&cache->full_slabs) ||
     720            !list_empty(&cache->partial_slabs))
    753721                panic("Destroying cache that is not empty.");
    754        
     722
    755723        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    756724                free(cache->mag_cache);
    757        
    758725        slab_free(&slab_cache_cache, cache);
    759726}
    760727
    761 /** Allocate new object from cache - if no flags given, always returns memory
    762  *
    763  */
    764 void *slab_alloc(slab_cache_t *cache, unsigned int flags)
    765 {
     728/** Allocate new object from cache - if no flags given, always returns memory */
     729void *slab_alloc(slab_cache_t *cache, int flags)
     730{
     731        ipl_t ipl;
     732        void *result = NULL;
     733       
    766734        /* Disable interrupts to avoid deadlocks with interrupt handlers */
    767         ipl_t ipl = interrupts_disable();
    768        
    769         void *result = NULL;
    770        
    771         if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
     735        ipl = interrupts_disable();
     736
     737        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) {
    772738                result = magazine_obj_get(cache);
    773        
     739        }
    774740        if (!result)
    775741                result = slab_obj_create(cache, flags);
    776        
     742
    777743        interrupts_restore(ipl);
    778        
     744
    779745        if (result)
    780746                atomic_inc(&cache->allocated_objs);
    781        
     747
    782748        return result;
    783749}
    784750
    785 /** Return object to cache, use slab if known
    786  *
    787  */
    788 NO_TRACE static void _slab_free(slab_cache_t *cache, void *obj, slab_t *slab)
    789 {
    790         ipl_t ipl = interrupts_disable();
    791        
     751/** Return object to cache, use slab if known  */
     752static void _slab_free(slab_cache_t *cache, void *obj, slab_t *slab)
     753{
     754        ipl_t ipl;
     755
     756        ipl = interrupts_disable();
     757
    792758        if ((cache->flags & SLAB_CACHE_NOMAGAZINE) ||
    793             (magazine_obj_put(cache, obj)))
     759            magazine_obj_put(cache, obj)) {
    794760                slab_obj_destroy(cache, obj, slab);
    795        
     761
     762        }
    796763        interrupts_restore(ipl);
    797764        atomic_dec(&cache->allocated_objs);
    798765}
    799766
    800 /** Return slab object to cache
    801  *
    802  */
     767/** Return slab object to cache */
    803768void slab_free(slab_cache_t *cache, void *obj)
    804769{
     
    806771}
    807772
    808 /** Go through all caches and reclaim what is possible */
    809 size_t slab_reclaim(unsigned int flags)
    810 {
    811         irq_spinlock_lock(&slab_cache_lock, true);
    812        
     773/* Go through all caches and reclaim what is possible */
     774size_t slab_reclaim(int flags)
     775{
     776        slab_cache_t *cache;
     777        link_t *cur;
    813778        size_t frames = 0;
    814         link_t *cur;
     779
     780        spinlock_lock(&slab_cache_lock);
     781
     782        /* TODO: Add assert, that interrupts are disabled, otherwise
     783         * memory allocation from interrupts can deadlock.
     784         */
     785
    815786        for (cur = slab_cache_list.next; cur != &slab_cache_list;
    816787            cur = cur->next) {
    817                 slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
     788                cache = list_get_instance(cur, slab_cache_t, link);
    818789                frames += _slab_reclaim(cache, flags);
    819790        }
    820        
    821         irq_spinlock_unlock(&slab_cache_lock, true);
    822        
     791
     792        spinlock_unlock(&slab_cache_lock);
     793
    823794        return frames;
    824795}
    825796
    826 /* Print list of slabs
    827  *
    828  */
     797
     798/* Print list of slabs */
    829799void slab_print_list(void)
    830800{
    831         printf("[slab name       ] [size  ] [pages ] [obj/pg] [slabs ]"
    832             " [cached] [alloc ] [ctl]\n");
    833        
    834         size_t skip = 0;
     801        int skip = 0;
     802
     803        printf("slab name        size     pages  obj/pg slabs  cached allocated"
     804            " ctl\n");
     805        printf("---------------- -------- ------ ------ ------ ------ ---------"
     806            " ---\n");
     807
    835808        while (true) {
     809                slab_cache_t *cache;
     810                link_t *cur;
     811                ipl_t ipl;
     812                int i;
     813
    836814                /*
    837815                 * We must not hold the slab_cache_lock spinlock when printing
     
    856834                 * statistics.
    857835                 */
    858                
    859                 irq_spinlock_lock(&slab_cache_lock, true);
    860                
    861                 link_t *cur;
    862                 size_t i;
     836
     837                ipl = interrupts_disable();
     838                spinlock_lock(&slab_cache_lock);
     839
    863840                for (i = 0, cur = slab_cache_list.next;
    864                     (i < skip) && (cur != &slab_cache_list);
    865                     i++, cur = cur->next);
    866                
     841                    i < skip && cur != &slab_cache_list;
     842                    i++, cur = cur->next)
     843                        ;
     844
    867845                if (cur == &slab_cache_list) {
    868                         irq_spinlock_unlock(&slab_cache_lock, true);
     846                        spinlock_unlock(&slab_cache_lock);
     847                        interrupts_restore(ipl);
    869848                        break;
    870849                }
    871                
     850
    872851                skip++;
    873                
    874                 slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
    875                
    876                 const char *name = cache->name;
     852
     853                cache = list_get_instance(cur, slab_cache_t, link);
     854
     855                char *name = cache->name;
    877856                uint8_t order = cache->order;
    878857                size_t size = cache->size;
    879                 size_t objects = cache->objects;
     858                unsigned int objects = cache->objects;
    880859                long allocated_slabs = atomic_get(&cache->allocated_slabs);
    881860                long cached_objs = atomic_get(&cache->cached_objs);
    882861                long allocated_objs = atomic_get(&cache->allocated_objs);
    883                 unsigned int flags = cache->flags;
     862                int flags = cache->flags;
    884863               
    885                 irq_spinlock_unlock(&slab_cache_lock, true);
     864                spinlock_unlock(&slab_cache_lock);
     865                interrupts_restore(ipl);
    886866               
    887                 printf("%-18s %8zu %8u %8zu %8ld %8ld %8ld %-5s\n",
     867                printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n",
    888868                    name, size, (1 << order), objects, allocated_slabs,
    889869                    cached_objs, allocated_objs,
     
    894874void slab_cache_init(void)
    895875{
     876        int i, size;
     877
    896878        /* Initialize magazine cache */
    897879        _slab_cache_create(&mag_cache, "slab_magazine",
     
    899881            sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE |
    900882            SLAB_CACHE_SLINSIDE);
    901        
    902883        /* Initialize slab_cache cache */
    903884        _slab_cache_create(&slab_cache_cache, "slab_cache",
    904885            sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL,
    905886            SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
    906        
    907887        /* Initialize external slab cache */
    908888        slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0,
    909889            NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED);
    910        
     890
    911891        /* Initialize structures for malloc */
    912         size_t i;
    913         size_t size;
    914        
    915892        for (i = 0, size = (1 << SLAB_MIN_MALLOC_W);
    916893            i < (SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1);
     
    919896                    NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    920897        }
    921        
    922 #ifdef CONFIG_DEBUG
     898#ifdef CONFIG_DEBUG       
    923899        _slab_initialized = 1;
    924900#endif
     
    928904 *
    929905 * Kernel calls this function, when it knows the real number of
    930  * processors. Allocate slab for cpucache and enable it on all
    931  * existing slabs that are SLAB_CACHE_MAGDEFERRED
    932  *
     906 * processors.
     907 * Allocate slab for cpucache and enable it on all existing
     908 * slabs that are SLAB_CACHE_MAGDEFERRED
    933909 */
    934910void slab_enable_cpucache(void)
    935911{
     912        link_t *cur;
     913        slab_cache_t *s;
     914
    936915#ifdef CONFIG_DEBUG
    937916        _slab_initialized = 2;
    938917#endif
    939        
    940         irq_spinlock_lock(&slab_cache_lock, false);
    941        
    942         link_t *cur;
     918
     919        spinlock_lock(&slab_cache_lock);
     920       
    943921        for (cur = slab_cache_list.next; cur != &slab_cache_list;
    944             cur = cur->next) {
    945                 slab_cache_t *slab = list_get_instance(cur, slab_cache_t, link);
    946                 if ((slab->flags & SLAB_CACHE_MAGDEFERRED) !=
     922            cur = cur->next){
     923                s = list_get_instance(cur, slab_cache_t, link);
     924                if ((s->flags & SLAB_CACHE_MAGDEFERRED) !=
    947925                    SLAB_CACHE_MAGDEFERRED)
    948926                        continue;
    949                
    950                 (void) make_magcache(slab);
    951                 slab->flags &= ~SLAB_CACHE_MAGDEFERRED;
    952         }
    953        
    954         irq_spinlock_unlock(&slab_cache_lock, false);
    955 }
    956 
    957 void *malloc(size_t size, unsigned int flags)
     927                make_magcache(s);
     928                s->flags &= ~SLAB_CACHE_MAGDEFERRED;
     929        }
     930
     931        spinlock_unlock(&slab_cache_lock);
     932}
     933
     934/**************************************/
     935/* kalloc/kfree functions             */
     936void *malloc(unsigned int size, int flags)
    958937{
    959938        ASSERT(_slab_initialized);
     
    962941        if (size < (1 << SLAB_MIN_MALLOC_W))
    963942                size = (1 << SLAB_MIN_MALLOC_W);
    964        
    965         uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
    966        
     943
     944        int idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
     945
    967946        return slab_alloc(malloc_caches[idx], flags);
    968947}
    969948
    970 void *realloc(void *ptr, size_t size, unsigned int flags)
     949void *realloc(void *ptr, unsigned int size, int flags)
    971950{
    972951        ASSERT(_slab_initialized);
     
    978957                if (size < (1 << SLAB_MIN_MALLOC_W))
    979958                        size = (1 << SLAB_MIN_MALLOC_W);
    980                 uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
     959                int idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
    981960               
    982961                new_ptr = slab_alloc(malloc_caches[idx], flags);
     
    999978        if (!ptr)
    1000979                return;
    1001        
     980
    1002981        slab_t *slab = obj2slab(ptr);
    1003982        _slab_free(slab->cache, ptr, slab);
Note: See TracChangeset for help on using the changeset viewer.