1 /* 2 * Copyright 2008-2010, Axel Dörfler. All Rights Reserved. 3 * Copyright 2007, Hugo Santos. All Rights Reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 #ifndef OBJECT_CACHE_H 8 #define OBJECT_CACHE_H 9 10 11 #include <condition_variable.h> 12 #include <lock.h> 13 #include <slab/ObjectDepot.h> 14 #include <slab/Slab.h> 15 #include <util/DoublyLinkedList.h> 16 17 18 struct ResizeRequest; 19 20 21 struct object_link { 22 struct object_link* next; 23 }; 24 25 struct slab : DoublyLinkedListLinkImpl<slab> { 26 void* pages; 27 size_t size; // total number of objects 28 size_t count; // free objects 29 size_t offset; 30 object_link* free; 31 }; 32 33 typedef DoublyLinkedList<slab> SlabList; 34 35 struct ObjectCacheResizeEntry { 36 ConditionVariable condition; 37 thread_id thread; 38 }; 39 40 struct ObjectCache : DoublyLinkedListLinkImpl<ObjectCache> { 41 char name[32]; 42 mutex lock; 43 size_t object_size; 44 size_t alignment; 45 size_t cache_color_cycle; 46 SlabList empty; 47 SlabList partial; 48 SlabList full; 49 size_t total_objects; // total number of objects 50 size_t used_count; // used objects 51 size_t empty_count; // empty slabs 52 size_t pressure; 53 size_t min_object_reserve; 54 // minimum number of free objects 55 56 size_t slab_size; 57 size_t usage; 58 size_t maximum; 59 uint32 flags; 60 61 ResizeRequest* resize_request; 62 63 ObjectCacheResizeEntry* resize_entry_can_wait; 64 ObjectCacheResizeEntry* resize_entry_dont_wait; 65 66 DoublyLinkedListLink<ObjectCache> maintenance_link; 67 bool maintenance_pending; 68 bool maintenance_in_progress; 69 bool maintenance_resize; 70 bool maintenance_delete; 71 72 void* cookie; 73 object_cache_constructor constructor; 74 object_cache_destructor destructor; 75 object_cache_reclaimer reclaimer; 76 77 object_depot depot; 78 79 public: 80 virtual ~ObjectCache(); 81 82 status_t Init(const char* name, size_t objectSize, 83 size_t alignment, size_t maximum, 84 size_t magazineCapacity, 85 size_t maxMagazineCount, uint32 flags, 86 void* cookie, 87 object_cache_constructor constructor, 88 object_cache_destructor destructor, 89 object_cache_reclaimer reclaimer); 90 virtual void Delete() = 0; 91 92 virtual slab* CreateSlab(uint32 flags) = 0; 93 virtual void ReturnSlab(slab* slab, uint32 flags) = 0; 94 virtual slab* ObjectSlab(void* object) const = 0; 95 96 slab* InitSlab(slab* slab, void* pages, 97 size_t byteCount, uint32 flags); 98 void UninitSlab(slab* slab); 99 100 void ReturnObjectToSlab(slab* source, void* object, 101 uint32 flags); 102 103 bool Lock() { return mutex_lock(&lock) == B_OK; } 104 void Unlock() { mutex_unlock(&lock); } 105 106 status_t AllocatePages(void** pages, uint32 flags); 107 void FreePages(void* pages); 108 status_t EarlyAllocatePages(void** pages, uint32 flags); 109 void EarlyFreePages(void* pages); 110 }; 111 112 113 static inline void* 114 link_to_object(object_link* link, size_t objectSize) 115 { 116 return ((uint8*)link) - (objectSize - sizeof(object_link)); 117 } 118 119 120 static inline object_link* 121 object_to_link(void* object, size_t objectSize) 122 { 123 return (object_link*)(((uint8*)object) 124 + (objectSize - sizeof(object_link))); 125 } 126 127 128 static inline void* 129 lower_boundary(const void* object, size_t byteCount) 130 { 131 return (void*)((addr_t)object & ~(byteCount - 1)); 132 } 133 134 135 static inline bool 136 check_cache_quota(ObjectCache* cache) 137 { 138 if (cache->maximum == 0) 139 return true; 140 141 return (cache->usage + cache->slab_size) <= cache->maximum; 142 } 143 144 145 #endif // OBJECT_CACHE_H 146