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 cache_color_cycle; 45 SlabList empty; 46 SlabList partial; 47 SlabList full; 48 size_t total_objects; // total number of objects 49 size_t used_count; // used objects 50 size_t empty_count; // empty slabs 51 size_t pressure; 52 size_t min_object_reserve; 53 // minimum number of free objects 54 55 size_t slab_size; 56 size_t usage; 57 size_t maximum; 58 uint32 flags; 59 60 ResizeRequest* resize_request; 61 62 ObjectCacheResizeEntry* resize_entry_can_wait; 63 ObjectCacheResizeEntry* resize_entry_dont_wait; 64 65 DoublyLinkedListLink<ObjectCache> maintenance_link; 66 bool maintenance_pending; 67 bool maintenance_in_progress; 68 bool maintenance_resize; 69 bool maintenance_delete; 70 71 void* cookie; 72 object_cache_constructor constructor; 73 object_cache_destructor destructor; 74 object_cache_reclaimer reclaimer; 75 76 object_depot depot; 77 78 public: 79 virtual ~ObjectCache(); 80 81 status_t Init(const char* name, size_t objectSize, 82 size_t alignment, size_t maximum, 83 size_t magazineCapacity, 84 size_t maxMagazineCount, uint32 flags, 85 void* cookie, 86 object_cache_constructor constructor, 87 object_cache_destructor destructor, 88 object_cache_reclaimer reclaimer); 89 virtual void Delete() = 0; 90 91 virtual slab* CreateSlab(uint32 flags) = 0; 92 virtual void ReturnSlab(slab* slab, uint32 flags) = 0; 93 virtual slab* ObjectSlab(void* object) const = 0; 94 95 slab* InitSlab(slab* slab, void* pages, 96 size_t byteCount, uint32 flags); 97 void UninitSlab(slab* slab); 98 99 void ReturnObjectToSlab(slab* source, void* object, 100 uint32 flags); 101 102 bool Lock() { return mutex_lock(&lock) == B_OK; } 103 void Unlock() { mutex_unlock(&lock); } 104 105 status_t AllocatePages(void** pages, uint32 flags); 106 void FreePages(void* pages); 107 status_t EarlyAllocatePages(void** pages, uint32 flags); 108 void EarlyFreePages(void* pages); 109 }; 110 111 112 static inline void* 113 link_to_object(object_link* link, size_t objectSize) 114 { 115 return ((uint8*)link) - (objectSize - sizeof(object_link)); 116 } 117 118 119 static inline object_link* 120 object_to_link(void* object, size_t objectSize) 121 { 122 return (object_link*)(((uint8*)object) 123 + (objectSize - sizeof(object_link))); 124 } 125 126 127 static inline void* 128 lower_boundary(const void* object, size_t byteCount) 129 { 130 return (void*)((addr_t)object & ~(byteCount - 1)); 131 } 132 133 134 static inline bool 135 check_cache_quota(ObjectCache* cache) 136 { 137 if (cache->maximum == 0) 138 return true; 139 140 return (cache->usage + cache->slab_size) <= cache->maximum; 141 } 142 143 144 #endif // OBJECT_CACHE_H 145