xref: /haiku/src/system/kernel/slab/ObjectCache.h (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
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 class AllocationTrackingInfo;
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 	return (object_link*)(((uint8*)object)
145 		+ (objectSize - sizeof(object_link)));
146 }
147 
148 
149 static inline void*
150 lower_boundary(const void* object, size_t byteCount)
151 {
152 	return (void*)((addr_t)object & ~(byteCount - 1));
153 }
154 
155 
156 static inline bool
157 check_cache_quota(ObjectCache* cache)
158 {
159 	if (cache->maximum == 0)
160 		return true;
161 
162 	return (cache->usage + cache->slab_size) <= cache->maximum;
163 }
164 
165 
166 #if !SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
167 
168 inline status_t
169 ObjectCache::AllocateTrackingInfos(slab* slab, size_t byteCount, uint32 flags)
170 {
171 	return B_OK;
172 }
173 
174 
175 inline void
176 ObjectCache::FreeTrackingInfos(slab* slab, uint32 flags)
177 {
178 }
179 
180 #endif // !SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
181 
182 #endif	// OBJECT_CACHE_H
183