[haiku-commits] r35601 - in haiku/trunk: headers/private/kernel/slab src/system/kernel/cache src/system/kernel/slab src/system/kernel/vm

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 24 Feb 2010 15:43:20 +0100 (CET)

Author: axeld
Date: 2010-02-24 15:43:20 +0100 (Wed, 24 Feb 2010)
New Revision: 35601
Changeset: http://dev.haiku-os.org/changeset/35601/haiku

Modified:
   haiku/trunk/headers/private/kernel/slab/ObjectDepot.h
   haiku/trunk/headers/private/kernel/slab/Slab.h
   haiku/trunk/src/system/kernel/cache/block_cache.cpp
   haiku/trunk/src/system/kernel/slab/HashedObjectCache.cpp
   haiku/trunk/src/system/kernel/slab/HashedObjectCache.h
   haiku/trunk/src/system/kernel/slab/ObjectCache.cpp
   haiku/trunk/src/system/kernel/slab/ObjectCache.h
   haiku/trunk/src/system/kernel/slab/ObjectDepot.cpp
   haiku/trunk/src/system/kernel/slab/Slab.cpp
   haiku/trunk/src/system/kernel/slab/SmallObjectCache.cpp
   haiku/trunk/src/system/kernel/slab/SmallObjectCache.h
   haiku/trunk/src/system/kernel/slab/allocator.cpp
   haiku/trunk/src/system/kernel/vm/vm.cpp
Log:
* The low resource handler now empties the cache depot's magazines; before,
  they were never freed unless the cache was destroyed (I just wondered why
  my system would bury >1G in the magazines).
* Made the magazine capacity variable per cache, ie. for larger objects, it's
  not a good idea to have 64*CPU buffers lying around in the worst case.
* Furthermore, the create_object_cache_etc()/object_depot_init() now have
  arguments for the magazine capacity as well as the maximum number of full
  unused magazines.
* By default, you might want to initialize both to zero, as then some hopefully
  usable defaults are computed. Otherwise (the only current example is the
  vm_page_mapping cache) you can just put in the values you'd want there.
  The page mapping cache uses larger values, as its objects are usually
  allocated and deleted in larger chunks.
* Beware, though, I couldn't test these changes yet as Qemu didn't like to run
  today. I'll test these changes on another machine now.


Modified: haiku/trunk/headers/private/kernel/slab/ObjectDepot.h
===================================================================
--- haiku/trunk/headers/private/kernel/slab/ObjectDepot.h       2010-02-24 
14:10:17 UTC (rev 35600)
+++ haiku/trunk/headers/private/kernel/slab/ObjectDepot.h       2010-02-24 
14:43:20 UTC (rev 35601)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2010, Axel Dörfler. All Rights Reserved.
  * Copyright 2007, Hugo Santos. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  */
@@ -19,9 +20,11 @@
        DepotMagazine*                  empty;
        size_t                                  full_count;
        size_t                                  empty_count;
+       size_t                                  max_count;
+       size_t                                  magazine_capacity;
        struct depot_cpu_store* stores;
+       void*                                   cookie;
 
-       void*   cookie;
        void (*return_object)(struct object_depot* depot, void* cookie,
                void* object, uint32 flags);
 } object_depot;
@@ -31,7 +34,8 @@
 extern "C" {
 #endif
 
-status_t object_depot_init(object_depot* depot, uint32 flags, void* cookie,
+status_t object_depot_init(object_depot* depot, size_t capacity,
+       size_t maxCount, uint32 flags, void* cookie,
        void (*returnObject)(object_depot* depot, void* cookie, void* object,
                uint32 flags));
 void object_depot_destroy(object_depot* depot, uint32 flags);
@@ -45,4 +49,5 @@
 }
 #endif
 
+
 #endif /* _SLAB_OBJECT_DEPOT_H_ */

Modified: haiku/trunk/headers/private/kernel/slab/Slab.h
===================================================================
--- haiku/trunk/headers/private/kernel/slab/Slab.h      2010-02-24 14:10:17 UTC 
(rev 35600)
+++ haiku/trunk/headers/private/kernel/slab/Slab.h      2010-02-24 14:43:20 UTC 
(rev 35601)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008, Axel Dörfler. All Rights Reserved.
+ * Copyright 2008-2010, Axel Dörfler. All Rights Reserved.
  * Copyright 2007, Hugo Santos. All Rights Reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -42,11 +42,12 @@
 extern "C" {
 #endif
 
-object_cache* create_object_cache(const char* name, size_t object_size,
+object_cache* create_object_cache(const char* name, size_t objectSize,
        size_t alignment, void* cookie, object_cache_constructor constructor,
-       object_cache_destructor);
-object_cache* create_object_cache_etc(const char* name, size_t object_size,
-       size_t alignment, size_t max_byte_usage, uint32 flags, void* cookie,
+       object_cache_destructor destructor);
+object_cache* create_object_cache_etc(const char* name, size_t objectSize,
+       size_t alignment, size_t maxByteUsage, size_t magazineCapacity,
+       size_t maxMagazineCount, uint32 flags, void* cookie,
        object_cache_constructor constructor, object_cache_destructor 
destructor,
        object_cache_reclaimer reclaimer);
 

Modified: haiku/trunk/src/system/kernel/cache/block_cache.cpp
===================================================================
--- haiku/trunk/src/system/kernel/cache/block_cache.cpp 2010-02-24 14:10:17 UTC 
(rev 35600)
+++ haiku/trunk/src/system/kernel/cache/block_cache.cpp 2010-02-24 14:43:20 UTC 
(rev 35601)
@@ -1329,7 +1329,7 @@
        mutex_init(&lock, "block cache");
 
        buffer_cache = create_object_cache_etc("block cache buffers", 
block_size,
-               8, 0, CACHE_LARGE_SLAB, NULL, NULL, NULL, NULL);
+               8, 0, 0, 0, CACHE_LARGE_SLAB, NULL, NULL, NULL, NULL);
        if (buffer_cache == NULL)
                return B_NO_MEMORY;
 
@@ -1472,7 +1472,7 @@
                if (block->is_dirty && !block->discard) {
                        if (block->busy_writing)
                                continue;
-                       
+
                        BlockWriter::WriteBlock(this, block);
                }
 
@@ -2022,7 +2022,7 @@
                (addr_t)block, block->block_number,
                (addr_t)block->current_data, (addr_t)block->original_data,
                (addr_t)block->parent_data, block->ref_count, block->accessed,
-               block->busy_reading ? 'r' : '-', block->busy_writing ? 'w' : 
'-', 
+               block->busy_reading ? 'r' : '-', block->busy_writing ? 'w' : 
'-',
                block->is_writing ? 'W' : '-', block->is_dirty ? 'D' : '-',
                block->unused ? 'U' : '-', block->discard ? 'D' : '-',
                (addr_t)block->transaction,
@@ -2587,7 +2587,7 @@
 block_cache_init(void)
 {
        sBlockCache = create_object_cache_etc("cached blocks", 
sizeof(cached_block),
-               8, 0, CACHE_LARGE_SLAB, NULL, NULL, NULL, NULL);
+               8, 0, 0, 0, CACHE_LARGE_SLAB, NULL, NULL, NULL, NULL);
        if (sBlockCache == NULL)
                return B_NO_MEMORY;
 
@@ -3299,7 +3299,7 @@
        }
 
        hash_close(cache->hash, &iterator, false);
-       
+
        status_t status = writer.Write();
 
        locker.Unlock();

Modified: haiku/trunk/src/system/kernel/slab/HashedObjectCache.cpp
===================================================================
--- haiku/trunk/src/system/kernel/slab/HashedObjectCache.cpp    2010-02-24 
14:10:17 UTC (rev 35600)
+++ haiku/trunk/src/system/kernel/slab/HashedObjectCache.cpp    2010-02-24 
14:43:20 UTC (rev 35601)
@@ -51,7 +51,8 @@
 
 /*static*/ HashedObjectCache*
 HashedObjectCache::Create(const char* name, size_t object_size,
-       size_t alignment, size_t maximum, uint32 flags, void* cookie,
+       size_t alignment, size_t maximum, size_t magazineCapacity,
+       size_t maxMagazineCount, uint32 flags, void* cookie,
        object_cache_constructor constructor, object_cache_destructor 
destructor,
        object_cache_reclaimer reclaimer)
 {
@@ -71,8 +72,9 @@
 
        cache->hash_table.Resize(buffer, hashSize, true);
 
-       if (cache->Init(name, object_size, alignment, maximum, flags, cookie,
-                       constructor, destructor, reclaimer) != B_OK) {
+       if (cache->Init(name, object_size, alignment, maximum, magazineCapacity,
+                       maxMagazineCount, flags, cookie, constructor, 
destructor,
+                       reclaimer) != B_OK) {
                cache->Delete();
                return NULL;
        }

Modified: haiku/trunk/src/system/kernel/slab/HashedObjectCache.h
===================================================================
--- haiku/trunk/src/system/kernel/slab/HashedObjectCache.h      2010-02-24 
14:10:17 UTC (rev 35600)
+++ haiku/trunk/src/system/kernel/slab/HashedObjectCache.h      2010-02-24 
14:43:20 UTC (rev 35601)
@@ -24,6 +24,8 @@
 
        static  HashedObjectCache*      Create(const char* name, size_t 
object_size,
                                                                        size_t 
alignment, size_t maximum,
+                                                                       size_t 
magazineCapacity,
+                                                                       size_t 
maxMagazineCount,
                                                                        uint32 
flags, void* cookie,
                                                                        
object_cache_constructor constructor,
                                                                        
object_cache_destructor destructor,

Modified: haiku/trunk/src/system/kernel/slab/ObjectCache.cpp
===================================================================
--- haiku/trunk/src/system/kernel/slab/ObjectCache.cpp  2010-02-24 14:10:17 UTC 
(rev 35600)
+++ haiku/trunk/src/system/kernel/slab/ObjectCache.cpp  2010-02-24 14:43:20 UTC 
(rev 35601)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008, Axel Dörfler. All Rights Reserved.
+ * Copyright 2008-2010, Axel Dörfler. All Rights Reserved.
  * Copyright 2007, Hugo Santos. All Rights Reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -40,10 +40,10 @@
 
 
 status_t
-ObjectCache::Init(const char* name, size_t objectSize,
-       size_t alignment, size_t maximum, uint32 flags, void* cookie,
-       object_cache_constructor constructor, object_cache_destructor 
destructor,
-       object_cache_reclaimer reclaimer)
+ObjectCache::Init(const char* name, size_t objectSize, size_t alignment,
+       size_t maximum, size_t magazineCapacity, size_t maxMagazineCount,
+       uint32 flags, void* cookie, object_cache_constructor constructor,
+       object_cache_destructor destructor, object_cache_reclaimer reclaimer)
 {
        strlcpy(this->name, name, sizeof(this->name));
 
@@ -86,9 +86,17 @@
                this->flags |= CACHE_NO_DEPOT;
 
        if (!(this->flags & CACHE_NO_DEPOT)) {
-               status_t status = object_depot_init(&depot, flags, this,
-                       object_cache_return_object_wrapper);
-               if (status < B_OK) {
+               // Determine usable magazine configuration values if none had 
been given
+               if (magazineCapacity == 0) {
+                       magazineCapacity = objectSize < 256
+                               ? 32 : (objectSize < 512 ? 16 : 8);
+               }
+               if (maxMagazineCount == 0)
+                       maxMagazineCount = magazineCapacity / 2;
+
+               status_t status = object_depot_init(&depot, magazineCapacity,
+                       maxMagazineCount, flags, this, 
object_cache_return_object_wrapper);
+               if (status != B_OK) {
                        mutex_destroy(&lock);
                        return status;
                }

Modified: haiku/trunk/src/system/kernel/slab/ObjectCache.h
===================================================================
--- haiku/trunk/src/system/kernel/slab/ObjectCache.h    2010-02-24 14:10:17 UTC 
(rev 35600)
+++ haiku/trunk/src/system/kernel/slab/ObjectCache.h    2010-02-24 14:43:20 UTC 
(rev 35601)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008, Axel Dörfler. All Rights Reserved.
+ * Copyright 2008-2010, Axel Dörfler. All Rights Reserved.
  * Copyright 2007, Hugo Santos. All Rights Reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -80,7 +80,9 @@
 
                        status_t                        Init(const char* name, 
size_t objectSize,
                                                                        size_t 
alignment, size_t maximum,
-                                                                       uint32 
flags, void* cookie,
+                                                                       size_t 
magazineCapacity,
+                                                                       size_t 
maxMagazineCount, uint32 flags,
+                                                                       void* 
cookie,
                                                                        
object_cache_constructor constructor,
                                                                        
object_cache_destructor destructor,
                                                                        
object_cache_reclaimer reclaimer);

Modified: haiku/trunk/src/system/kernel/slab/ObjectDepot.cpp
===================================================================
--- haiku/trunk/src/system/kernel/slab/ObjectDepot.cpp  2010-02-24 14:10:17 UTC 
(rev 35600)
+++ haiku/trunk/src/system/kernel/slab/ObjectDepot.cpp  2010-02-24 14:43:20 UTC 
(rev 35601)
@@ -19,10 +19,6 @@
 #include "slab_private.h"
 
 
-static const int kMagazineCapacity = 32;
-       // TODO: Should be dynamically tuned per cache.
-
-
 struct DepotMagazine {
                        DepotMagazine*          next;
                        uint16                          current_round;
@@ -80,14 +76,15 @@
 
 
 static DepotMagazine*
-alloc_magazine(uint32 flags)
+alloc_magazine(object_depot* depot, uint32 flags)
 {
        DepotMagazine* magazine = (DepotMagazine*)slab_internal_alloc(
-               sizeof(DepotMagazine) + kMagazineCapacity * sizeof(void*), 
flags);
+               sizeof(DepotMagazine) + depot->magazine_capacity * 
sizeof(void*),
+               flags);
        if (magazine) {
                magazine->next = NULL;
                magazine->current_round = 0;
-               magazine->round_count = kMagazineCapacity;
+               magazine->round_count = depot->magazine_capacity;
        }
 
        return magazine;
@@ -113,6 +110,8 @@
 static bool
 exchange_with_full(object_depot* depot, DepotMagazine*& magazine)
 {
+       ASSERT(magazine->IsEmpty());
+
        SpinLocker _(depot->inner_lock);
 
        if (depot->full == NULL)
@@ -128,8 +127,11 @@
 
 
 static bool
-exchange_with_empty(object_depot* depot, DepotMagazine*& magazine)
+exchange_with_empty(object_depot* depot, DepotMagazine*& magazine,
+       DepotMagazine*& freeMagazine)
 {
+       ASSERT(magazine == NULL || magazine->IsFull());
+
        SpinLocker _(depot->inner_lock);
 
        if (depot->empty == NULL)
@@ -137,9 +139,12 @@
 
        depot->empty_count--;
 
-       if (magazine) {
-               _push(depot->full, magazine);
-               depot->full_count++;
+       if (magazine != NULL) {
+               if (depot->full_count < depot->max_count) {
+                       _push(depot->full, magazine);
+                       depot->full_count++;
+               } else
+                       freeMagazine = magazine;
        }
 
        magazine = _pop(depot->empty);
@@ -168,13 +173,15 @@
 
 
 status_t
-object_depot_init(object_depot* depot, uint32 flags, void* cookie,
-       void (*return_object)(object_depot* depot, void* cookie, void* object,
-               uint32 flags))
+object_depot_init(object_depot* depot, size_t capacity, size_t maxCount,
+       uint32 flags, void* cookie, void (*return_object)(object_depot* depot,
+               void* cookie, void* object, uint32 flags))
 {
        depot->full = NULL;
        depot->empty = NULL;
        depot->full_count = depot->empty_count = 0;
+       depot->max_count = maxCount;
+       depot->magazine_capacity = capacity;
 
        rw_lock_init(&depot->outer_lock, "object depot");
        B_INITIALIZE_SPINLOCK(&depot->inner_lock);
@@ -245,6 +252,8 @@
 int
 object_depot_store(object_depot* depot, void* object, uint32 flags)
 {
+       DepotMagazine* freeMagazine = NULL;
+
        ReadLocker readLocker(depot->outer_lock);
        InterruptsLocker interruptsLocker;
 
@@ -256,18 +265,31 @@
        // we return the object directly to the slab.
 
        while (true) {
-               if (store->loaded && store->loaded->Push(object))
+               if (store->loaded != NULL && store->loaded->Push(object))
                        return 1;
 
-               if ((store->previous && store->previous->IsEmpty())
-                       || exchange_with_empty(depot, store->previous)) {
+               if ((store->previous != NULL && store->previous->IsEmpty())
+                       || exchange_with_empty(depot, store->previous, 
freeMagazine)) {
                        std::swap(store->loaded, store->previous);
+
+                       if (freeMagazine != NULL) {
+                               // Free the magazine that didn't have space in 
the list
+                               interruptsLocker.Unlock();
+                               readLocker.Unlock();
+
+                               empty_magazine(depot, freeMagazine, flags);
+
+                               readLocker.Lock();
+                               interruptsLocker.Lock();
+
+                               store = object_depot_cpu(depot);
+                       }
                } else {
                        // allocate a new empty magazine
                        interruptsLocker.Unlock();
                        readLocker.Unlock();
 
-                       DepotMagazine* magazine = alloc_magazine(flags);
+                       DepotMagazine* magazine = alloc_magazine(depot, flags);
                        if (magazine == NULL)
                                return 0;
 

Modified: haiku/trunk/src/system/kernel/slab/Slab.cpp
===================================================================
--- haiku/trunk/src/system/kernel/slab/Slab.cpp 2010-02-24 14:10:17 UTC (rev 
35600)
+++ haiku/trunk/src/system/kernel/slab/Slab.cpp 2010-02-24 14:43:20 UTC (rev 
35601)
@@ -413,6 +413,11 @@
                if (cache->reclaimer)
                        cache->reclaimer(cache->cookie, level);
 
+               if ((cache->flags & CACHE_NO_DEPOT) == 0) {
+                       object_depot_make_empty(&cache->depot, 0);
+                               // TODO: what flags?
+               }
+
                MutexLocker cacheLocker(cache->lock);
                size_t minimumAllowed;
 
@@ -540,16 +545,16 @@
        void* cookie, object_cache_constructor constructor,
        object_cache_destructor destructor)
 {
-       return create_object_cache_etc(name, object_size, alignment, 0, 0, 
cookie,
-               constructor, destructor, NULL);
+       return create_object_cache_etc(name, object_size, alignment, 0, 0, 0, 0,
+               cookie, constructor, destructor, NULL);
 }
 
 
 object_cache*
 create_object_cache_etc(const char* name, size_t objectSize, size_t alignment,
-       size_t maximum, uint32 flags, void* cookie,
-       object_cache_constructor constructor, object_cache_destructor 
destructor,
-       object_cache_reclaimer reclaimer)
+       size_t maximum, size_t magazineCapacity, size_t maxMagazineCount,
+       uint32 flags, void* cookie, object_cache_constructor constructor,
+       object_cache_destructor destructor, object_cache_reclaimer reclaimer)
 {
        ObjectCache* cache;
 
@@ -557,10 +562,12 @@
                cache = NULL;
        } else if (objectSize <= 256) {
                cache = SmallObjectCache::Create(name, objectSize, alignment, 
maximum,
-                       flags, cookie, constructor, destructor, reclaimer);
+                       magazineCapacity, maxMagazineCount, flags, cookie, 
constructor,
+                       destructor, reclaimer);
        } else {
-               cache = HashedObjectCache::Create(name, objectSize, alignment,
-                       maximum, flags, cookie, constructor, destructor, 
reclaimer);
+               cache = HashedObjectCache::Create(name, objectSize, alignment, 
maximum,
+                       magazineCapacity, maxMagazineCount, flags, cookie, 
constructor,
+                       destructor, reclaimer);
        }
 
        if (cache != NULL) {

Modified: haiku/trunk/src/system/kernel/slab/SmallObjectCache.cpp
===================================================================
--- haiku/trunk/src/system/kernel/slab/SmallObjectCache.cpp     2010-02-24 
14:10:17 UTC (rev 35600)
+++ haiku/trunk/src/system/kernel/slab/SmallObjectCache.cpp     2010-02-24 
14:43:20 UTC (rev 35601)
@@ -21,7 +21,8 @@
 
 /*static*/ SmallObjectCache*
 SmallObjectCache::Create(const char* name, size_t object_size,
-       size_t alignment, size_t maximum, uint32 flags, void* cookie,
+       size_t alignment, size_t maximum, size_t magazineCapacity,
+       size_t maxMagazineCount, uint32 flags, void* cookie,
        object_cache_constructor constructor, object_cache_destructor 
destructor,
        object_cache_reclaimer reclaimer)
 {
@@ -31,8 +32,9 @@
 
        SmallObjectCache* cache = new(buffer) SmallObjectCache();
 
-       if (cache->Init(name, object_size, alignment, maximum, flags, cookie,
-                       constructor, destructor, reclaimer) != B_OK) {
+       if (cache->Init(name, object_size, alignment, maximum, magazineCapacity,
+                       maxMagazineCount, flags, cookie, constructor, 
destructor,
+                       reclaimer) != B_OK) {
                cache->Delete();
                return NULL;
        }

Modified: haiku/trunk/src/system/kernel/slab/SmallObjectCache.h
===================================================================
--- haiku/trunk/src/system/kernel/slab/SmallObjectCache.h       2010-02-24 
14:10:17 UTC (rev 35600)
+++ haiku/trunk/src/system/kernel/slab/SmallObjectCache.h       2010-02-24 
14:43:20 UTC (rev 35601)
@@ -14,6 +14,8 @@
 struct SmallObjectCache : ObjectCache {
        static  SmallObjectCache*       Create(const char* name, size_t 
object_size,
                                                                        size_t 
alignment, size_t maximum,
+                                                                       size_t 
magazineCapacity,
+                                                                       size_t 
maxMagazineCount,
                                                                        uint32 
flags, void* cookie,
                                                                        
object_cache_constructor constructor,
                                                                        
object_cache_destructor destructor,

Modified: haiku/trunk/src/system/kernel/slab/allocator.cpp
===================================================================
--- haiku/trunk/src/system/kernel/slab/allocator.cpp    2010-02-24 14:10:17 UTC 
(rev 35600)
+++ haiku/trunk/src/system/kernel/slab/allocator.cpp    2010-02-24 14:43:20 UTC 
(rev 35601)
@@ -180,8 +180,8 @@
                if (size > 2048)
                        flags |= CACHE_NO_DEPOT;
 
-               sBlockCaches[index] = create_object_cache_etc(name, size, 0, 0, 
flags,
-                       NULL, NULL, NULL, NULL);
+               sBlockCaches[index] = create_object_cache_etc(name, size, 0, 0, 
0, 0,
+                       flags, NULL, NULL, NULL, NULL);
                if (sBlockCaches[index] == NULL)
                        panic("allocator: failed to init block cache");
        }

Modified: haiku/trunk/src/system/kernel/vm/vm.cpp
===================================================================
--- haiku/trunk/src/system/kernel/vm/vm.cpp     2010-02-24 14:10:17 UTC (rev 
35600)
+++ haiku/trunk/src/system/kernel/vm/vm.cpp     2010-02-24 14:43:20 UTC (rev 
35601)
@@ -1,6 +1,6 @@
 /*
  * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx
- * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Copyright 2002-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * Distributed under the terms of the MIT License.
  *
  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -3395,8 +3395,8 @@
 
        // create the object cache for the page mappings
        gPageMappingsObjectCache = create_object_cache_etc("page mappings",
-               sizeof(vm_page_mapping), 0, 0, CACHE_LARGE_SLAB, NULL, NULL, 
NULL,
-               NULL);
+               sizeof(vm_page_mapping), 0, 0, 64, 128, CACHE_LARGE_SLAB, NULL, 
NULL,
+               NULL, NULL);
        if (gPageMappingsObjectCache == NULL)
                panic("failed to create page mappings object cache");
 


Other related posts: