Changeset 5158549 in mainline


Ignore:
Timestamp:
2006-02-05T01:19:16Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e22f561
Parents:
e72b0a3
Message:

Still better locking - does not hold global spinlock when
destroying cache.

Location:
generic
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • generic/include/mm/slab.h

    re72b0a3 r5158549  
    8282        atomic_t allocated_objs;
    8383        atomic_t cached_objs;
     84        atomic_t magazine_counter; /*<< How many magazines in magazines list */
    8485
    8586        /* Slabs */
  • generic/src/mm/slab.c

    re72b0a3 r5158549  
    308308
    309309/**
     310 * Finds a full magazine in cache, takes it from list
     311 * and returns it
     312 *
     313 * @param first If true, return first, else last mag
     314 */
     315static slab_magazine_t * get_mag_from_cache(slab_cache_t *cache,
     316                                            int first)
     317{
     318        slab_magazine_t *mag = NULL;
     319        link_t *cur;
     320
     321        spinlock_lock(&cache->maglock);
     322        if (!list_empty(&cache->magazines)) {
     323                if (first)
     324                        cur = cache->magazines.next;
     325                else
     326                        cur = cache->magazines.prev;
     327                mag = list_get_instance(cur, slab_magazine_t, link);
     328                list_remove(&mag->link);
     329                atomic_dec(&cache->magazine_counter);
     330        }
     331        spinlock_unlock(&cache->maglock);
     332        return mag;
     333}
     334
     335/** Prepend magazine to magazine list in cache */
     336static void put_mag_to_cache(slab_cache_t *cache, slab_magazine_t *mag)
     337{
     338        spinlock_lock(&cache->maglock);
     339
     340        list_prepend(&mag->link, &cache->magazines);
     341        atomic_inc(&cache->magazine_counter);
     342       
     343        spinlock_unlock(&cache->maglock);
     344}
     345
     346/**
    310347 * Free all objects in magazine and free memory associated with magazine
    311348 *
     
    350387        }
    351388        /* Local magazines are empty, import one from magazine list */
    352         spinlock_lock(&cache->maglock);
    353         if (list_empty(&cache->magazines)) {
    354                 spinlock_unlock(&cache->maglock);
     389        newmag = get_mag_from_cache(cache, 1);
     390        if (!newmag)
    355391                return NULL;
    356         }
    357         newmag = list_get_instance(cache->magazines.next,
    358                                    slab_magazine_t,
    359                                    link);
    360         list_remove(&newmag->link);
    361         spinlock_unlock(&cache->maglock);
    362392
    363393        if (lastmag)
    364                 slab_free(&mag_cache, lastmag);
     394                magazine_destroy(cache, lastmag);
     395
    365396        cache->mag_cache[CPU->id].last = cmag;
    366397        cache->mag_cache[CPU->id].current = newmag;
     
    435466
    436467        /* Flush last to magazine list */
    437         if (lastmag) {
    438                 spinlock_lock(&cache->maglock);
    439                 list_prepend(&lastmag->link, &cache->magazines);
    440                 spinlock_unlock(&cache->maglock);
    441         }
     468        if (lastmag)
     469                put_mag_to_cache(cache, lastmag);
     470
    442471        /* Move current as last, save new as current */
    443472        cache->mag_cache[CPU->id].last = cmag; 
     
    589618        int i;
    590619        slab_magazine_t *mag;
    591         link_t *cur;
    592620        count_t frames = 0;
     621        int magcount;
    593622       
    594623        if (cache->flags & SLAB_CACHE_NOMAGAZINE)
    595624                return 0; /* Nothing to do */
    596        
    597         /* First lock all cpu caches, then the complete cache lock */
     625
     626        /* We count up to original magazine count to avoid
     627         * endless loop
     628         */
     629        magcount = atomic_get(&cache->magazine_counter);
     630        while (magcount-- && (mag=get_mag_from_cache(cache,0))) {
     631                frames += magazine_destroy(cache,mag);
     632                if (!(flags & SLAB_RECLAIM_ALL) && frames)
     633                        break;
     634        }
     635       
    598636        if (flags & SLAB_RECLAIM_ALL) {
    599                 for (i=0; i < config.cpu_count; i++)
    600                         spinlock_lock(&cache->mag_cache[i].lock);
    601         }
    602         spinlock_lock(&cache->maglock);
    603        
    604         if (flags & SLAB_RECLAIM_ALL) {
    605                 /* Aggressive memfree */
     637                /* Free cpu-bound magazines */
    606638                /* Destroy CPU magazines */
    607639                for (i=0; i<config.cpu_count; i++) {
     640                        spinlock_lock(&cache->mag_cache[i].lock);
     641
    608642                        mag = cache->mag_cache[i].current;
    609643                        if (mag)
     
    615649                                frames += magazine_destroy(cache, mag);
    616650                        cache->mag_cache[i].last = NULL;
     651
     652                        spinlock_unlock(&cache->mag_cache[i].lock);
    617653                }
    618654        }
    619         /* We can release the cache locks now */
    620         if (flags & SLAB_RECLAIM_ALL) {
    621                 for (i=0; i < config.cpu_count; i++)
    622                         spinlock_unlock(&cache->mag_cache[i].lock);
    623         }
    624         /* Destroy full magazines */
    625         cur=cache->magazines.prev;
    626 
    627         while (cur != &cache->magazines) {
    628                 mag = list_get_instance(cur, slab_magazine_t, link);
    629                
    630                 cur = cur->prev;
    631                 list_remove(&mag->link);
    632                 frames += magazine_destroy(cache,mag);
    633                 /* If we do not do full reclaim, break
    634                  * as soon as something is freed */
    635                 if (!(flags & SLAB_RECLAIM_ALL) && frames)
    636                         break;
    637         }
    638        
    639         spinlock_unlock(&cache->maglock);
    640        
     655
    641656        return frames;
    642657}
     
    645660void slab_cache_destroy(slab_cache_t *cache)
    646661{
     662        ipl_t ipl;
     663
     664        /* First remove cache from link, so that we don't need
     665         * to disable interrupts later
     666         */
     667
     668        ipl = interrupts_disable();
     669        spinlock_lock(&slab_cache_lock);
     670
     671        list_remove(&cache->link);
     672
     673        spinlock_unlock(&slab_cache_lock);
     674        interrupts_restore(ipl);
     675
    647676        /* Do not lock anything, we assume the software is correct and
    648677         * does not touch the cache when it decides to destroy it */
     
    656685                panic("Destroying cache that is not empty.");
    657686
    658         spinlock_lock(&slab_cache_lock);
    659         list_remove(&cache->link);
    660         spinlock_unlock(&slab_cache_lock);
    661 
    662687        slab_free(&slab_cache_cache, cache);
    663688}
     
    675700        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    676701                result = magazine_obj_get(cache);
    677 
    678702        if (!result)
    679703                result = slab_obj_create(cache, flags);
     
    721745        /* TODO: Add assert, that interrupts are disabled, otherwise
    722746         * memory allocation from interrupts can deadlock.
     747         * - cache_destroy can call this with interrupts enabled :-/
    723748         */
    724749
     
    815840void kfree(void *obj)
    816841{
    817         slab_t *slab = obj2slab(obj);
    818        
     842        slab_t *slab;
     843
     844        if (!obj) return;
     845
     846        slab = obj2slab(obj);
    819847        _slab_free(slab->cache, obj, slab);
    820848}
Note: See TracChangeset for help on using the changeset viewer.