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#include "kernel_debug_config.h" 18#include "slab_debug.h" 19 20 21struct ResizeRequest; 22 23 24struct object_link { 25 struct object_link* next; 26}; 27 28struct slab : DoublyLinkedListLinkImpl<slab> { 29 void* pages; 30 size_t size; // total number of objects 31 size_t count; // free objects 32 size_t offset; 33 object_link* free; 34#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING 35 AllocationTrackingInfo* tracking; 36#endif 37}; 38 39typedef DoublyLinkedList<slab> SlabList; 40 41struct ObjectCacheResizeEntry { 42 ConditionVariable condition; 43 thread_id thread; 44}; 45 46struct ObjectCache : DoublyLinkedListLinkImpl<ObjectCache> { 47 char name[32]; 48 mutex lock; 49 size_t object_size; 50 size_t alignment; 51 size_t cache_color_cycle; 52 SlabList empty; 53 SlabList partial; 54 SlabList full; 55 size_t total_objects; // total number of objects 56 size_t used_count; // used objects 57 size_t empty_count; // empty slabs 58 size_t pressure; 59 size_t min_object_reserve; 60 // minimum number of free objects 61 62 size_t slab_size; 63 size_t usage; 64 size_t maximum; 65 uint32 flags; 66 67 ResizeRequest* resize_request; 68 69 ObjectCacheResizeEntry* resize_entry_can_wait; 70 ObjectCacheResizeEntry* resize_entry_dont_wait; 71 72 DoublyLinkedListLink<ObjectCache> maintenance_link; 73 bool maintenance_pending; 74 bool maintenance_in_progress; 75 bool maintenance_resize; 76 bool maintenance_delete; 77 78 void* cookie; 79 object_cache_constructor constructor; 80 object_cache_destructor destructor; 81 object_cache_reclaimer reclaimer; 82 83 object_depot depot; 84 85public: 86 virtual ~ObjectCache(); 87 88 status_t Init(const char* name, size_t objectSize, 89 size_t alignment, size_t maximum, 90 size_t magazineCapacity, 91 size_t maxMagazineCount, uint32 flags, 92 void* cookie, 93 object_cache_constructor constructor, 94 object_cache_destructor destructor, 95 object_cache_reclaimer reclaimer); 96 virtual void Delete() = 0; 97 98 virtual slab* CreateSlab(uint32 flags) = 0; 99 virtual void ReturnSlab(slab* slab, uint32 flags) = 0; 100 virtual slab* ObjectSlab(void* object) const = 0; 101 102 slab* InitSlab(slab* slab, void* pages, 103 size_t byteCount, uint32 flags); 104 void UninitSlab(slab* slab); 105 106 void ReturnObjectToSlab(slab* source, void* object, 107 uint32 flags); 108 void* ObjectAtIndex(slab* source, int32 index) const; 109 110 bool Lock() { return mutex_lock(&lock) == B_OK; } 111 void Unlock() { mutex_unlock(&lock); } 112 113 status_t AllocatePages(void** pages, uint32 flags); 114 void FreePages(void* pages); 115 status_t EarlyAllocatePages(void** pages, uint32 flags); 116 void EarlyFreePages(void* pages); 117 118#if PARANOID_KERNEL_FREE 119 bool AssertObjectNotFreed(void* object); 120#endif 121 122 status_t AllocateTrackingInfos(slab* slab, 123 size_t byteCount, uint32 flags); 124 void FreeTrackingInfos(slab* slab, uint32 flags); 125 126#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING 127 AllocationTrackingInfo* 128 TrackingInfoFor(void* object) const; 129#endif 130}; 131 132 133static inline void* 134link_to_object(object_link* link, size_t objectSize) 135{ 136 return ((uint8*)link) - (objectSize - sizeof(object_link)); 137} 138 139 140static inline object_link* 141object_to_link(void* object, size_t objectSize) 142{ 143 return (object_link*)(((uint8*)object) 144 + (objectSize - sizeof(object_link))); 145} 146 147 148static inline void* 149lower_boundary(const void* object, size_t byteCount) 150{ 151 return (void*)((addr_t)object & ~(byteCount - 1)); 152} 153 154 155static inline bool 156check_cache_quota(ObjectCache* cache) 157{ 158 if (cache->maximum == 0) 159 return true; 160 161 return (cache->usage + cache->slab_size) <= cache->maximum; 162} 163 164 165#if !SLAB_OBJECT_CACHE_ALLOCATION_TRACKING 166 167inline status_t 168ObjectCache::AllocateTrackingInfos(slab* slab, size_t byteCount, uint32 flags) 169{ 170 return B_OK; 171} 172 173 174inline void 175ObjectCache::FreeTrackingInfos(slab* slab, uint32 flags) 176{ 177} 178 179#endif // !SLAB_OBJECT_CACHE_ALLOCATION_TRACKING 180 181#endif // OBJECT_CACHE_H 182