Changeset 428aabf in mainline


Ignore:
Timestamp:
2006-02-04T15:01:56Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
55ab0f1
Parents:
10e16a7
Message:

Added more granular locking to slab allocator and thus fix
hopefully last race condition.

Location:
generic
Files:
2 edited

Legend:

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

    r10e16a7 r428aabf  
    6767        char *name;
    6868
    69         SPINLOCK_DECLARE(lock);
    7069        link_t link;
    7170        /* Configuration */
     
    8786        link_t full_slabs;     /**< List of full slabs */
    8887        link_t partial_slabs;  /**< List of partial slabs */
     88        SPINLOCK_DECLARE(slablock);
    8989        /* Magazines  */
    9090        link_t magazines;      /**< List o full magazines */
     91        SPINLOCK_DECLARE(maglock);
    9192
    9293        /** CPU cache */
  • generic/src/mm/slab.c

    r10e16a7 r428aabf  
    8686 * magazine cache.
    8787 *
     88 * - it might be good to add granularity of locks even to slab level,
     89 *   we could then try_spinlock over all partial slabs and thus improve
     90 *   scalability even on slab level
    8891 */
    8992
     
    219222 * Return object to slab and call a destructor
    220223 *
    221  * Assume the cache->lock is held;
    222  *
    223224 * @param slab If the caller knows directly slab of the object, otherwise NULL
    224225 *
     
    234235
    235236        ASSERT(slab->cache == cache);
     237
     238        spinlock_lock(&cache->slablock);
    236239
    237240        *((int *)obj) = slab->nextavail;
     
    248251                /* Free associated memory */
    249252                list_remove(&slab->link);
    250                 /* Avoid deadlock */
    251                 spinlock_unlock(&cache->lock);
     253                /* This should not produce deadlock, as
     254                 * magazine is always allocated with NO reclaim,
     255                 * keep all locks */
    252256                frames = slab_space_free(cache, slab);
    253                 spinlock_lock(&cache->lock);
    254         }
     257        }
     258
     259        spinlock_unlock(&cache->slablock);
    255260
    256261        return frames;
     
    260265 * Take new object from slab or create new if needed
    261266 *
    262  * Assume cache->lock is held.
    263  *
    264267 * @return Object address or null
    265268 */
     
    268271        slab_t *slab;
    269272        void *obj;
     273
     274        spinlock_lock(&cache->slablock);
    270275
    271276        if (list_empty(&cache->partial_slabs)) {
     
    276281                 *   that's why we should get recursion at most 1-level deep
    277282                 */
    278                 spinlock_unlock(&cache->lock);
     283                spinlock_unlock(&cache->slablock);
    279284                slab = slab_space_alloc(cache, flags);
    280                 spinlock_lock(&cache->lock);
    281                 if (!slab) {
    282                         return NULL;
    283                 }
     285                spinlock_lock(&cache->slablock);
     286                if (!slab)
     287                        goto err;
    284288        } else {
    285289                slab = list_get_instance(cache->partial_slabs.next,
     
    295299        else
    296300                list_prepend(&slab->link, &cache->partial_slabs);
     301
     302        spinlock_unlock(&cache->slablock);
    297303        return obj;
     304err:
     305        spinlock_unlock(&cache->slablock);
     306        return NULL;
    298307}
    299308
     
    303312/**
    304313 * Free all objects in magazine and free memory associated with magazine
    305  *
    306  * Assume cache->lock is held
    307314 *
    308315 * @return Number of freed pages
     
    346353        }
    347354        /* Local magazines are empty, import one from magazine list */
    348         spinlock_lock(&cache->lock);
     355        spinlock_lock(&cache->maglock);
    349356        if (list_empty(&cache->magazines)) {
    350                 spinlock_unlock(&cache->lock);
     357                spinlock_unlock(&cache->maglock);
    351358                return NULL;
    352359        }
     
    355362                                   link);
    356363        list_remove(&newmag->link);
    357         spinlock_unlock(&cache->lock);
     364        spinlock_unlock(&cache->maglock);
    358365
    359366        if (lastmag)
     
    432439        /* Flush last to magazine list */
    433440        if (lastmag) {
    434                 spinlock_lock(&cache->lock);
     441                spinlock_lock(&cache->maglock);
    435442                list_prepend(&lastmag->link, &cache->magazines);
    436                 spinlock_unlock(&cache->lock);
     443                spinlock_unlock(&cache->maglock);
    437444        }
    438445        /* Move current as last, save new as current */
     
    525532        list_initialize(&cache->partial_slabs);
    526533        list_initialize(&cache->magazines);
    527         spinlock_initialize(&cache->lock, "cachelock");
     534        spinlock_initialize(&cache->slablock, "slab_lock");
     535        spinlock_initialize(&cache->maglock, "slab_maglock");
    528536        if (! (cache->flags & SLAB_CACHE_NOMAGAZINE)) {
    529537                for (i=0; i < config.cpu_count; i++) {
     
    531539                                sizeof(cache->mag_cache[i]), 0);
    532540                        spinlock_initialize(&cache->mag_cache[i].lock,
    533                                             "cpucachelock");
     541                                            "slab_maglock_cpu");
    534542                }
    535543        }
     
    595603                        spinlock_lock(&cache->mag_cache[i].lock);
    596604        }
    597         spinlock_lock(&cache->lock);
     605        spinlock_lock(&cache->maglock);
    598606       
    599607        if (flags & SLAB_RECLAIM_ALL) {
     
    612620                }
    613621        }
     622        /* We can release the cache locks now */
     623        if (flags & SLAB_RECLAIM_ALL) {
     624                for (i=0; i < config.cpu_count; i++)
     625                        spinlock_unlock(&cache->mag_cache[i].lock);
     626        }
    614627        /* Destroy full magazines */
    615628        cur=cache->magazines.prev;
     
    627640        }
    628641       
    629         spinlock_unlock(&cache->lock);
    630         /* We can release the cache locks now */
    631         if (flags & SLAB_RECLAIM_ALL) {
    632                 for (i=0; i < config.cpu_count; i++)
    633                         spinlock_unlock(&cache->mag_cache[i].lock);
    634         }
     642        spinlock_unlock(&cache->maglock);
    635643       
    636644        return frames;
     
    671679                result = magazine_obj_get(cache);
    672680
    673         if (!result) {
    674                 spinlock_lock(&cache->lock);
     681        if (!result)
    675682                result = slab_obj_create(cache, flags);
    676                 spinlock_unlock(&cache->lock);
    677         }
    678683
    679684        interrupts_restore(ipl);
     
    694699        if ((cache->flags & SLAB_CACHE_NOMAGAZINE) \
    695700            || magazine_obj_put(cache, obj)) {
    696                 spinlock_lock(&cache->lock);
     701
    697702                slab_obj_destroy(cache, obj, slab);
    698                 spinlock_unlock(&cache->lock);
     703
    699704        }
    700705        interrupts_restore(ipl);
     
    716721
    717722        spinlock_lock(&slab_cache_lock);
     723
     724        /* TODO: Add assert, that interrupts are disabled, otherwise
     725         * memory allocation from interrupts can deadlock.
     726         */
    718727
    719728        for (cur = slab_cache_list.next;cur!=&slab_cache_list; cur=cur->next) {
Note: See TracChangeset for help on using the changeset viewer.