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