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