void object_depot_destroy(object_depot* depot, uint32 flags) { object_depot_make_empty(depot, flags); slab_internal_free(depot->stores, flags); rw_lock_destroy(&depot->outer_lock); }
static void object_cache_low_memory(void* dummy, uint32 resources, int32 level) { if (level == B_NO_LOW_RESOURCE) return; MutexLocker cacheListLocker(sObjectCacheListLock); // Append the first cache to the end of the queue. We assume that it is // one of the caches that will never be deleted and thus we use it as a // marker. ObjectCache* firstCache = sObjectCaches.RemoveHead(); sObjectCaches.Add(firstCache); cacheListLocker.Unlock(); ObjectCache* cache; do { cacheListLocker.Lock(); cache = sObjectCaches.RemoveHead(); sObjectCaches.Add(cache); MutexLocker maintenanceLocker(sMaintenanceLock); if (cache->maintenance_pending || cache->maintenance_in_progress) { // We don't want to mess with caches in maintenance. continue; } cache->maintenance_pending = true; cache->maintenance_in_progress = true; maintenanceLocker.Unlock(); cacheListLocker.Unlock(); // We are calling the reclaimer without the object cache lock // to give the owner a chance to return objects to the slabs. if (cache->reclaimer) cache->reclaimer(cache->cookie, level); if ((cache->flags & CACHE_NO_DEPOT) == 0) object_depot_make_empty(&cache->depot, 0); MutexLocker cacheLocker(cache->lock); size_t minimumAllowed; switch (level) { case B_LOW_RESOURCE_NOTE: minimumAllowed = cache->pressure / 2 + 1; cache->pressure -= cache->pressure / 8; break; case B_LOW_RESOURCE_WARNING: cache->pressure /= 2; minimumAllowed = 0; break; default: cache->pressure = 0; minimumAllowed = 0; break; } while (cache->empty_count > minimumAllowed) { // make sure we respect the cache's minimum object reserve size_t objectsPerSlab = cache->empty.Head()->size; size_t freeObjects = cache->total_objects - cache->used_count; if (freeObjects < cache->min_object_reserve + objectsPerSlab) break; cache->ReturnSlab(cache->empty.RemoveHead(), 0); cache->empty_count--; } cacheLocker.Unlock(); // Check whether in the meantime someone has really requested // maintenance for the cache. maintenanceLocker.Lock(); if (cache->maintenance_delete) { delete_object_cache_internal(cache); continue; } cache->maintenance_in_progress = false; if (cache->maintenance_resize) sMaintenanceQueue.Add(cache); else cache->maintenance_pending = false; } while (cache != firstCache); }