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