xref: /haiku/src/system/kernel/slab/ObjectCache.h (revision bec70b1ec815cd3a9cd254695d0779014138d8a8)
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 
21 struct ResizeRequest;
22 
23 
24 struct object_link {
25 	struct object_link* next;
26 };
27 
28 struct 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 
39 typedef DoublyLinkedList<slab> SlabList;
40 
41 struct ObjectCacheResizeEntry {
42 	ConditionVariable	condition;
43 	thread_id			thread;
44 };
45 
46 struct 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 
85 public:
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 
LockObjectCache110 			bool				Lock()	{ return mutex_lock(&lock) == B_OK; }
UnlockObjectCache111 			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 
133 static inline void*
link_to_object(object_link * link,size_t objectSize)134 link_to_object(object_link* link, size_t objectSize)
135 {
136 	return ((uint8*)link) - (objectSize - sizeof(object_link));
137 }
138 
139 
140 static inline object_link*
object_to_link(void * object,size_t objectSize)141 object_to_link(void* object, size_t objectSize)
142 {
143 	return (object_link*)(((uint8*)object)
144 		+ (objectSize - sizeof(object_link)));
145 }
146 
147 
148 static inline void*
lower_boundary(const void * object,size_t byteCount)149 lower_boundary(const void* object, size_t byteCount)
150 {
151 	return (void*)((addr_t)object & ~(byteCount - 1));
152 }
153 
154 
155 static inline bool
check_cache_quota(ObjectCache * cache)156 check_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 
167 inline status_t
AllocateTrackingInfos(slab * slab,size_t byteCount,uint32 flags)168 ObjectCache::AllocateTrackingInfos(slab* slab, size_t byteCount, uint32 flags)
169 {
170 	return B_OK;
171 }
172 
173 
174 inline void
FreeTrackingInfos(slab * slab,uint32 flags)175 ObjectCache::FreeTrackingInfos(slab* slab, uint32 flags)
176 {
177 }
178 
179 #endif // !SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
180 
181 #endif	// OBJECT_CACHE_H
182