xref: /haiku/src/system/kernel/slab/ObjectDepot.cpp (revision a84e14ca84d32e9469c91372d71556488bd3d48b)
1a8806e5eSIngo Weinhold /*
2453a2bddSIngo Weinhold  * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
354f3267eSAxel Dörfler  * Copyright 2008-2010, Axel Dörfler. All Rights Reserved.
4a8806e5eSIngo Weinhold  * Copyright 2007, Hugo Santos. All Rights Reserved.
5a8806e5eSIngo Weinhold  *
6a8806e5eSIngo Weinhold  * Distributed under the terms of the MIT License.
7a8806e5eSIngo Weinhold  */
8a8806e5eSIngo Weinhold 
9a8806e5eSIngo Weinhold 
10a8806e5eSIngo Weinhold #include <slab/ObjectDepot.h>
11a8806e5eSIngo Weinhold 
12a8806e5eSIngo Weinhold #include <algorithm>
13a8806e5eSIngo Weinhold 
14453a2bddSIngo Weinhold #include <int.h>
15bb439b87SIngo Weinhold #include <slab/Slab.h>
16453a2bddSIngo Weinhold #include <smp.h>
17a8806e5eSIngo Weinhold #include <util/AutoLock.h>
18a8806e5eSIngo Weinhold 
19*e1c6140eSIngo Weinhold #include "slab_debug.h"
20a8806e5eSIngo Weinhold #include "slab_private.h"
21a8806e5eSIngo Weinhold 
22a8806e5eSIngo Weinhold 
23825566f8SIngo Weinhold struct DepotMagazine {
24825566f8SIngo Weinhold 			DepotMagazine*		next;
25825566f8SIngo Weinhold 			uint16				current_round;
26825566f8SIngo Weinhold 			uint16				round_count;
27a8806e5eSIngo Weinhold 			void*				rounds[0];
28825566f8SIngo Weinhold 
29825566f8SIngo Weinhold public:
30825566f8SIngo Weinhold 	inline	bool				IsEmpty() const;
31825566f8SIngo Weinhold 	inline	bool				IsFull() const;
32825566f8SIngo Weinhold 
33825566f8SIngo Weinhold 	inline	void*				Pop();
34825566f8SIngo Weinhold 	inline	bool				Push(void* object);
3572156a40SMichael Lotz 
3672156a40SMichael Lotz #if PARANOID_KERNEL_FREE
3772156a40SMichael Lotz 			bool				ContainsObject(void* object) const;
3872156a40SMichael Lotz #endif
39a8806e5eSIngo Weinhold };
40a8806e5eSIngo Weinhold 
41a8806e5eSIngo Weinhold 
42a8806e5eSIngo Weinhold struct depot_cpu_store {
43825566f8SIngo Weinhold 	DepotMagazine*	loaded;
44825566f8SIngo Weinhold 	DepotMagazine*	previous;
45a8806e5eSIngo Weinhold };
46a8806e5eSIngo Weinhold 
47a8806e5eSIngo Weinhold 
RANGE_MARKER_FUNCTION_BEGIN(SlabObjectDepot)48*e1c6140eSIngo Weinhold RANGE_MARKER_FUNCTION_BEGIN(SlabObjectDepot)
49*e1c6140eSIngo Weinhold 
50*e1c6140eSIngo Weinhold 
51825566f8SIngo Weinhold bool
52825566f8SIngo Weinhold DepotMagazine::IsEmpty() const
53a8806e5eSIngo Weinhold {
54825566f8SIngo Weinhold 	return current_round == 0;
55a8806e5eSIngo Weinhold }
56a8806e5eSIngo Weinhold 
57a8806e5eSIngo Weinhold 
58825566f8SIngo Weinhold bool
IsFull() const59825566f8SIngo Weinhold DepotMagazine::IsFull() const
60a8806e5eSIngo Weinhold {
61825566f8SIngo Weinhold 	return current_round == round_count;
62a8806e5eSIngo Weinhold }
63a8806e5eSIngo Weinhold 
64a8806e5eSIngo Weinhold 
65825566f8SIngo Weinhold void*
Pop()66825566f8SIngo Weinhold DepotMagazine::Pop()
67a8806e5eSIngo Weinhold {
68825566f8SIngo Weinhold 	return rounds[--current_round];
69a8806e5eSIngo Weinhold }
70a8806e5eSIngo Weinhold 
71a8806e5eSIngo Weinhold 
72825566f8SIngo Weinhold bool
Push(void * object)73825566f8SIngo Weinhold DepotMagazine::Push(void* object)
74a8806e5eSIngo Weinhold {
75825566f8SIngo Weinhold 	if (IsFull())
76a8806e5eSIngo Weinhold 		return false;
77825566f8SIngo Weinhold 
78825566f8SIngo Weinhold 	rounds[current_round++] = object;
79a8806e5eSIngo Weinhold 	return true;
80a8806e5eSIngo Weinhold }
81a8806e5eSIngo Weinhold 
82a8806e5eSIngo Weinhold 
8372156a40SMichael Lotz #if PARANOID_KERNEL_FREE
8472156a40SMichael Lotz 
8572156a40SMichael Lotz bool
ContainsObject(void * object) const8672156a40SMichael Lotz DepotMagazine::ContainsObject(void* object) const
8772156a40SMichael Lotz {
8872156a40SMichael Lotz 	for (uint16 i = 0; i < current_round; i++) {
8972156a40SMichael Lotz 		if (rounds[i] == object)
9072156a40SMichael Lotz 			return true;
9172156a40SMichael Lotz 	}
9272156a40SMichael Lotz 
9372156a40SMichael Lotz 	return false;
9472156a40SMichael Lotz }
9572156a40SMichael Lotz 
9672156a40SMichael Lotz #endif // PARANOID_KERNEL_FREE
9772156a40SMichael Lotz 
9872156a40SMichael Lotz 
9954f3267eSAxel Dörfler // #pragma mark -
10054f3267eSAxel Dörfler 
10154f3267eSAxel Dörfler 
102825566f8SIngo Weinhold static DepotMagazine*
alloc_magazine(object_depot * depot,uint32 flags)103ff59ce68SAxel Dörfler alloc_magazine(object_depot* depot, uint32 flags)
104a8806e5eSIngo Weinhold {
105825566f8SIngo Weinhold 	DepotMagazine* magazine = (DepotMagazine*)slab_internal_alloc(
106ff59ce68SAxel Dörfler 		sizeof(DepotMagazine) + depot->magazine_capacity * sizeof(void*),
107ff59ce68SAxel Dörfler 		flags);
108a8806e5eSIngo Weinhold 	if (magazine) {
109a8806e5eSIngo Weinhold 		magazine->next = NULL;
110a8806e5eSIngo Weinhold 		magazine->current_round = 0;
111ff59ce68SAxel Dörfler 		magazine->round_count = depot->magazine_capacity;
112a8806e5eSIngo Weinhold 	}
113a8806e5eSIngo Weinhold 
114a8806e5eSIngo Weinhold 	return magazine;
115a8806e5eSIngo Weinhold }
116a8806e5eSIngo Weinhold 
117a8806e5eSIngo Weinhold 
118a8806e5eSIngo Weinhold static void
free_magazine(DepotMagazine * magazine,uint32 flags)11986c794e5SIngo Weinhold free_magazine(DepotMagazine* magazine, uint32 flags)
120a8806e5eSIngo Weinhold {
12186c794e5SIngo Weinhold 	slab_internal_free(magazine, flags);
122a8806e5eSIngo Weinhold }
123a8806e5eSIngo Weinhold 
124a8806e5eSIngo Weinhold 
125a8806e5eSIngo Weinhold static void
empty_magazine(object_depot * depot,DepotMagazine * magazine,uint32 flags)12686c794e5SIngo Weinhold empty_magazine(object_depot* depot, DepotMagazine* magazine, uint32 flags)
127a8806e5eSIngo Weinhold {
128a8806e5eSIngo Weinhold 	for (uint16 i = 0; i < magazine->current_round; i++)
12986c794e5SIngo Weinhold 		depot->return_object(depot, depot->cookie, magazine->rounds[i], flags);
13086c794e5SIngo Weinhold 	free_magazine(magazine, flags);
131a8806e5eSIngo Weinhold }
132a8806e5eSIngo Weinhold 
133a8806e5eSIngo Weinhold 
134a8806e5eSIngo Weinhold static bool
exchange_with_full(object_depot * depot,DepotMagazine * & magazine)135825566f8SIngo Weinhold exchange_with_full(object_depot* depot, DepotMagazine*& magazine)
136a8806e5eSIngo Weinhold {
137ff59ce68SAxel Dörfler 	ASSERT(magazine->IsEmpty());
138ff59ce68SAxel Dörfler 
139453a2bddSIngo Weinhold 	SpinLocker _(depot->inner_lock);
140a8806e5eSIngo Weinhold 
141a8806e5eSIngo Weinhold 	if (depot->full == NULL)
142a8806e5eSIngo Weinhold 		return false;
143a8806e5eSIngo Weinhold 
144a8806e5eSIngo Weinhold 	depot->full_count--;
145a8806e5eSIngo Weinhold 	depot->empty_count++;
146a8806e5eSIngo Weinhold 
147a8806e5eSIngo Weinhold 	_push(depot->empty, magazine);
148a8806e5eSIngo Weinhold 	magazine = _pop(depot->full);
149a8806e5eSIngo Weinhold 	return true;
150a8806e5eSIngo Weinhold }
151a8806e5eSIngo Weinhold 
152a8806e5eSIngo Weinhold 
153a8806e5eSIngo Weinhold static bool
exchange_with_empty(object_depot * depot,DepotMagazine * & magazine,DepotMagazine * & freeMagazine)154ff59ce68SAxel Dörfler exchange_with_empty(object_depot* depot, DepotMagazine*& magazine,
155ff59ce68SAxel Dörfler 	DepotMagazine*& freeMagazine)
156a8806e5eSIngo Weinhold {
157ff59ce68SAxel Dörfler 	ASSERT(magazine == NULL || magazine->IsFull());
158ff59ce68SAxel Dörfler 
159453a2bddSIngo Weinhold 	SpinLocker _(depot->inner_lock);
160a8806e5eSIngo Weinhold 
161a8806e5eSIngo Weinhold 	if (depot->empty == NULL)
162a8806e5eSIngo Weinhold 		return false;
163453a2bddSIngo Weinhold 
164a8806e5eSIngo Weinhold 	depot->empty_count--;
165a8806e5eSIngo Weinhold 
166ff59ce68SAxel Dörfler 	if (magazine != NULL) {
167ff59ce68SAxel Dörfler 		if (depot->full_count < depot->max_count) {
168a8806e5eSIngo Weinhold 			_push(depot->full, magazine);
169a8806e5eSIngo Weinhold 			depot->full_count++;
1702a196c63SIngo Weinhold 			freeMagazine = NULL;
171ff59ce68SAxel Dörfler 		} else
172ff59ce68SAxel Dörfler 			freeMagazine = magazine;
173a8806e5eSIngo Weinhold 	}
174a8806e5eSIngo Weinhold 
175a8806e5eSIngo Weinhold 	magazine = _pop(depot->empty);
176a8806e5eSIngo Weinhold 	return true;
177a8806e5eSIngo Weinhold }
178a8806e5eSIngo Weinhold 
179a8806e5eSIngo Weinhold 
180453a2bddSIngo Weinhold static void
push_empty_magazine(object_depot * depot,DepotMagazine * magazine)181453a2bddSIngo Weinhold push_empty_magazine(object_depot* depot, DepotMagazine* magazine)
182453a2bddSIngo Weinhold {
183453a2bddSIngo Weinhold 	SpinLocker _(depot->inner_lock);
184453a2bddSIngo Weinhold 
185453a2bddSIngo Weinhold 	_push(depot->empty, magazine);
18654f3267eSAxel Dörfler 	depot->empty_count++;
187453a2bddSIngo Weinhold }
188453a2bddSIngo Weinhold 
189453a2bddSIngo Weinhold 
190a8806e5eSIngo Weinhold static inline depot_cpu_store*
object_depot_cpu(object_depot * depot)191a8806e5eSIngo Weinhold object_depot_cpu(object_depot* depot)
192a8806e5eSIngo Weinhold {
193a8806e5eSIngo Weinhold 	return &depot->stores[smp_get_current_cpu()];
194a8806e5eSIngo Weinhold }
195a8806e5eSIngo Weinhold 
196a8806e5eSIngo Weinhold 
197453a2bddSIngo Weinhold // #pragma mark - public API
198453a2bddSIngo Weinhold 
199453a2bddSIngo Weinhold 
200453a2bddSIngo Weinhold status_t
object_depot_init(object_depot * depot,size_t capacity,size_t maxCount,uint32 flags,void * cookie,void (* return_object)(object_depot * depot,void * cookie,void * object,uint32 flags))201ff59ce68SAxel Dörfler object_depot_init(object_depot* depot, size_t capacity, size_t maxCount,
202ff59ce68SAxel Dörfler 	uint32 flags, void* cookie, void (*return_object)(object_depot* depot,
203ff59ce68SAxel Dörfler 		void* cookie, void* object, uint32 flags))
204a8806e5eSIngo Weinhold {
205453a2bddSIngo Weinhold 	depot->full = NULL;
206453a2bddSIngo Weinhold 	depot->empty = NULL;
207453a2bddSIngo Weinhold 	depot->full_count = depot->empty_count = 0;
208ff59ce68SAxel Dörfler 	depot->max_count = maxCount;
209ff59ce68SAxel Dörfler 	depot->magazine_capacity = capacity;
210453a2bddSIngo Weinhold 
211453a2bddSIngo Weinhold 	rw_lock_init(&depot->outer_lock, "object depot");
212453a2bddSIngo Weinhold 	B_INITIALIZE_SPINLOCK(&depot->inner_lock);
213453a2bddSIngo Weinhold 
214453a2bddSIngo Weinhold 	int cpuCount = smp_get_num_cpus();
215453a2bddSIngo Weinhold 	depot->stores = (depot_cpu_store*)slab_internal_alloc(
216453a2bddSIngo Weinhold 		sizeof(depot_cpu_store) * cpuCount, flags);
217453a2bddSIngo Weinhold 	if (depot->stores == NULL) {
218453a2bddSIngo Weinhold 		rw_lock_destroy(&depot->outer_lock);
219453a2bddSIngo Weinhold 		return B_NO_MEMORY;
220453a2bddSIngo Weinhold 	}
221453a2bddSIngo Weinhold 
222453a2bddSIngo Weinhold 	for (int i = 0; i < cpuCount; i++) {
223453a2bddSIngo Weinhold 		depot->stores[i].loaded = NULL;
224453a2bddSIngo Weinhold 		depot->stores[i].previous = NULL;
225453a2bddSIngo Weinhold 	}
226453a2bddSIngo Weinhold 
227453a2bddSIngo Weinhold 	depot->cookie = cookie;
228453a2bddSIngo Weinhold 	depot->return_object = return_object;
229453a2bddSIngo Weinhold 
230453a2bddSIngo Weinhold 	return B_OK;
231453a2bddSIngo Weinhold }
232453a2bddSIngo Weinhold 
233453a2bddSIngo Weinhold 
234453a2bddSIngo Weinhold void
object_depot_destroy(object_depot * depot,uint32 flags)23586c794e5SIngo Weinhold object_depot_destroy(object_depot* depot, uint32 flags)
236453a2bddSIngo Weinhold {
23786c794e5SIngo Weinhold 	object_depot_make_empty(depot, flags);
238453a2bddSIngo Weinhold 
23986c794e5SIngo Weinhold 	slab_internal_free(depot->stores, flags);
240453a2bddSIngo Weinhold 
241453a2bddSIngo Weinhold 	rw_lock_destroy(&depot->outer_lock);
242453a2bddSIngo Weinhold }
243453a2bddSIngo Weinhold 
244453a2bddSIngo Weinhold 
245453a2bddSIngo Weinhold void*
object_depot_obtain(object_depot * depot)246453a2bddSIngo Weinhold object_depot_obtain(object_depot* depot)
247453a2bddSIngo Weinhold {
248453a2bddSIngo Weinhold 	ReadLocker readLocker(depot->outer_lock);
249453a2bddSIngo Weinhold 	InterruptsLocker interruptsLocker;
250453a2bddSIngo Weinhold 
251453a2bddSIngo Weinhold 	depot_cpu_store* store = object_depot_cpu(depot);
252a8806e5eSIngo Weinhold 
253a8806e5eSIngo Weinhold 	// To better understand both the Alloc() and Free() logic refer to
254a8806e5eSIngo Weinhold 	// Bonwick's ``Magazines and Vmem'' [in 2001 USENIX proceedings]
255a8806e5eSIngo Weinhold 
256a8806e5eSIngo Weinhold 	// In a nutshell, we try to get an object from the loaded magazine
257a8806e5eSIngo Weinhold 	// if it's not empty, or from the previous magazine if it's full
258a8806e5eSIngo Weinhold 	// and finally from the Slab if the magazine depot has no full magazines.
259a8806e5eSIngo Weinhold 
260a8806e5eSIngo Weinhold 	if (store->loaded == NULL)
261a8806e5eSIngo Weinhold 		return NULL;
262a8806e5eSIngo Weinhold 
263a8806e5eSIngo Weinhold 	while (true) {
264825566f8SIngo Weinhold 		if (!store->loaded->IsEmpty())
265825566f8SIngo Weinhold 			return store->loaded->Pop();
266a8806e5eSIngo Weinhold 
267825566f8SIngo Weinhold 		if (store->previous
268825566f8SIngo Weinhold 			&& (store->previous->IsFull()
269825566f8SIngo Weinhold 				|| exchange_with_full(depot, store->previous))) {
270a8806e5eSIngo Weinhold 			std::swap(store->previous, store->loaded);
271825566f8SIngo Weinhold 		} else
272a8806e5eSIngo Weinhold 			return NULL;
273a8806e5eSIngo Weinhold 	}
274a8806e5eSIngo Weinhold }
275a8806e5eSIngo Weinhold 
276a8806e5eSIngo Weinhold 
277464d9f12SIngo Weinhold void
object_depot_store(object_depot * depot,void * object,uint32 flags)27886c794e5SIngo Weinhold object_depot_store(object_depot* depot, void* object, uint32 flags)
279a8806e5eSIngo Weinhold {
280453a2bddSIngo Weinhold 	ReadLocker readLocker(depot->outer_lock);
281453a2bddSIngo Weinhold 	InterruptsLocker interruptsLocker;
282453a2bddSIngo Weinhold 
283453a2bddSIngo Weinhold 	depot_cpu_store* store = object_depot_cpu(depot);
284a8806e5eSIngo Weinhold 
285a8806e5eSIngo Weinhold 	// We try to add the object to the loaded magazine if we have one
286a8806e5eSIngo Weinhold 	// and it's not full, or to the previous one if it is empty. If
287a8806e5eSIngo Weinhold 	// the magazine depot doesn't provide us with a new empty magazine
288a8806e5eSIngo Weinhold 	// we return the object directly to the slab.
289a8806e5eSIngo Weinhold 
290a8806e5eSIngo Weinhold 	while (true) {
291ff59ce68SAxel Dörfler 		if (store->loaded != NULL && store->loaded->Push(object))
292464d9f12SIngo Weinhold 			return;
293a8806e5eSIngo Weinhold 
2942a196c63SIngo Weinhold 		DepotMagazine* freeMagazine = NULL;
295ff59ce68SAxel Dörfler 		if ((store->previous != NULL && store->previous->IsEmpty())
296ff59ce68SAxel Dörfler 			|| exchange_with_empty(depot, store->previous, freeMagazine)) {
297a8806e5eSIngo Weinhold 			std::swap(store->loaded, store->previous);
298ff59ce68SAxel Dörfler 
299ff59ce68SAxel Dörfler 			if (freeMagazine != NULL) {
300ff59ce68SAxel Dörfler 				// Free the magazine that didn't have space in the list
301ff59ce68SAxel Dörfler 				interruptsLocker.Unlock();
302ff59ce68SAxel Dörfler 				readLocker.Unlock();
303ff59ce68SAxel Dörfler 
304ff59ce68SAxel Dörfler 				empty_magazine(depot, freeMagazine, flags);
305ff59ce68SAxel Dörfler 
306ff59ce68SAxel Dörfler 				readLocker.Lock();
307ff59ce68SAxel Dörfler 				interruptsLocker.Lock();
308ff59ce68SAxel Dörfler 
309ff59ce68SAxel Dörfler 				store = object_depot_cpu(depot);
310ff59ce68SAxel Dörfler 			}
311453a2bddSIngo Weinhold 		} else {
312453a2bddSIngo Weinhold 			// allocate a new empty magazine
313453a2bddSIngo Weinhold 			interruptsLocker.Unlock();
314453a2bddSIngo Weinhold 			readLocker.Unlock();
315453a2bddSIngo Weinhold 
316ff59ce68SAxel Dörfler 			DepotMagazine* magazine = alloc_magazine(depot, flags);
317462dd94aSIngo Weinhold 			if (magazine == NULL) {
318462dd94aSIngo Weinhold 				depot->return_object(depot, depot->cookie, object, flags);
319464d9f12SIngo Weinhold 				return;
320462dd94aSIngo Weinhold 			}
321453a2bddSIngo Weinhold 
322453a2bddSIngo Weinhold 			readLocker.Lock();
323453a2bddSIngo Weinhold 			interruptsLocker.Lock();
324453a2bddSIngo Weinhold 
325453a2bddSIngo Weinhold 			push_empty_magazine(depot, magazine);
326453a2bddSIngo Weinhold 			store = object_depot_cpu(depot);
327a8806e5eSIngo Weinhold 		}
328a8806e5eSIngo Weinhold 	}
329a8806e5eSIngo Weinhold }
330a8806e5eSIngo Weinhold 
331a8806e5eSIngo Weinhold 
332a8806e5eSIngo Weinhold void
object_depot_make_empty(object_depot * depot,uint32 flags)33386c794e5SIngo Weinhold object_depot_make_empty(object_depot* depot, uint32 flags)
334a8806e5eSIngo Weinhold {
335453a2bddSIngo Weinhold 	WriteLocker writeLocker(depot->outer_lock);
336453a2bddSIngo Weinhold 
337453a2bddSIngo Weinhold 	// collect the store magazines
338453a2bddSIngo Weinhold 
339453a2bddSIngo Weinhold 	DepotMagazine* storeMagazines = NULL;
340453a2bddSIngo Weinhold 
341bcf73b3aSIngo Weinhold 	int cpuCount = smp_get_num_cpus();
342bcf73b3aSIngo Weinhold 	for (int i = 0; i < cpuCount; i++) {
343453a2bddSIngo Weinhold 		depot_cpu_store& store = depot->stores[i];
344a8806e5eSIngo Weinhold 
345453a2bddSIngo Weinhold 		if (store.loaded) {
346453a2bddSIngo Weinhold 			_push(storeMagazines, store.loaded);
347453a2bddSIngo Weinhold 			store.loaded = NULL;
348a8806e5eSIngo Weinhold 		}
349a8806e5eSIngo Weinhold 
350453a2bddSIngo Weinhold 		if (store.previous) {
351453a2bddSIngo Weinhold 			_push(storeMagazines, store.previous);
352453a2bddSIngo Weinhold 			store.previous = NULL;
353453a2bddSIngo Weinhold 		}
354453a2bddSIngo Weinhold 	}
355a8806e5eSIngo Weinhold 
356453a2bddSIngo Weinhold 	// detach the depot's full and empty magazines
357a8806e5eSIngo Weinhold 
358453a2bddSIngo Weinhold 	DepotMagazine* fullMagazines = depot->full;
359453a2bddSIngo Weinhold 	depot->full = NULL;
360453a2bddSIngo Weinhold 
361453a2bddSIngo Weinhold 	DepotMagazine* emptyMagazines = depot->empty;
362453a2bddSIngo Weinhold 	depot->empty = NULL;
363453a2bddSIngo Weinhold 
364453a2bddSIngo Weinhold 	writeLocker.Unlock();
365453a2bddSIngo Weinhold 
366453a2bddSIngo Weinhold 	// free all magazines
367453a2bddSIngo Weinhold 
368453a2bddSIngo Weinhold 	while (storeMagazines != NULL)
36986c794e5SIngo Weinhold 		empty_magazine(depot, _pop(storeMagazines), flags);
370453a2bddSIngo Weinhold 
371453a2bddSIngo Weinhold 	while (fullMagazines != NULL)
37286c794e5SIngo Weinhold 		empty_magazine(depot, _pop(fullMagazines), flags);
373453a2bddSIngo Weinhold 
374453a2bddSIngo Weinhold 	while (emptyMagazines)
37586c794e5SIngo Weinhold 		free_magazine(_pop(emptyMagazines), flags);
376a8806e5eSIngo Weinhold }
37754f3267eSAxel Dörfler 
37854f3267eSAxel Dörfler 
37972156a40SMichael Lotz #if PARANOID_KERNEL_FREE
38072156a40SMichael Lotz 
38172156a40SMichael Lotz bool
object_depot_contains_object(object_depot * depot,void * object)38272156a40SMichael Lotz object_depot_contains_object(object_depot* depot, void* object)
38372156a40SMichael Lotz {
38472156a40SMichael Lotz 	WriteLocker writeLocker(depot->outer_lock);
38572156a40SMichael Lotz 
38672156a40SMichael Lotz 	int cpuCount = smp_get_num_cpus();
38772156a40SMichael Lotz 	for (int i = 0; i < cpuCount; i++) {
38872156a40SMichael Lotz 		depot_cpu_store& store = depot->stores[i];
38972156a40SMichael Lotz 
39072156a40SMichael Lotz 		if (store.loaded != NULL && !store.loaded->IsEmpty()) {
39172156a40SMichael Lotz 			if (store.loaded->ContainsObject(object))
39272156a40SMichael Lotz 				return true;
39372156a40SMichael Lotz 		}
39472156a40SMichael Lotz 
39572156a40SMichael Lotz 		if (store.previous != NULL && !store.previous->IsEmpty()) {
39672156a40SMichael Lotz 			if (store.previous->ContainsObject(object))
39772156a40SMichael Lotz 				return true;
39872156a40SMichael Lotz 		}
39972156a40SMichael Lotz 	}
40072156a40SMichael Lotz 
40172156a40SMichael Lotz 	for (DepotMagazine* magazine = depot->full; magazine != NULL;
40272156a40SMichael Lotz 			magazine = magazine->next) {
40372156a40SMichael Lotz 		if (magazine->ContainsObject(object))
40472156a40SMichael Lotz 			return true;
40572156a40SMichael Lotz 	}
40672156a40SMichael Lotz 
40772156a40SMichael Lotz 	return false;
40872156a40SMichael Lotz }
40972156a40SMichael Lotz 
41072156a40SMichael Lotz #endif // PARANOID_KERNEL_FREE
41172156a40SMichael Lotz 
41272156a40SMichael Lotz 
41354f3267eSAxel Dörfler // #pragma mark - private kernel API
41454f3267eSAxel Dörfler 
41554f3267eSAxel Dörfler 
41654f3267eSAxel Dörfler void
dump_object_depot(object_depot * depot)41754f3267eSAxel Dörfler dump_object_depot(object_depot* depot)
41854f3267eSAxel Dörfler {
41954f3267eSAxel Dörfler 	kprintf("  full:     %p, count %lu\n", depot->full, depot->full_count);
42054f3267eSAxel Dörfler 	kprintf("  empty:    %p, count %lu\n", depot->empty, depot->empty_count);
4216426413dSAxel Dörfler 	kprintf("  max full: %lu\n", depot->max_count);
4226426413dSAxel Dörfler 	kprintf("  capacity: %lu\n", depot->magazine_capacity);
42354f3267eSAxel Dörfler 	kprintf("  stores:\n");
42454f3267eSAxel Dörfler 
42554f3267eSAxel Dörfler 	int cpuCount = smp_get_num_cpus();
42654f3267eSAxel Dörfler 
42754f3267eSAxel Dörfler 	for (int i = 0; i < cpuCount; i++) {
42854f3267eSAxel Dörfler 		kprintf("  [%d] loaded:   %p\n", i, depot->stores[i].loaded);
42954f3267eSAxel Dörfler 		kprintf("      previous: %p\n", depot->stores[i].previous);
43054f3267eSAxel Dörfler 	}
43154f3267eSAxel Dörfler }
43254f3267eSAxel Dörfler 
43354f3267eSAxel Dörfler 
43454f3267eSAxel Dörfler int
dump_object_depot(int argCount,char ** args)43554f3267eSAxel Dörfler dump_object_depot(int argCount, char** args)
43654f3267eSAxel Dörfler {
43754f3267eSAxel Dörfler 	if (argCount != 2)
43854f3267eSAxel Dörfler 		kprintf("usage: %s [address]\n", args[0]);
43954f3267eSAxel Dörfler 	else
44054f3267eSAxel Dörfler 		dump_object_depot((object_depot*)parse_expression(args[1]));
44154f3267eSAxel Dörfler 
44254f3267eSAxel Dörfler 	return 0;
44354f3267eSAxel Dörfler }
44454f3267eSAxel Dörfler 
44554f3267eSAxel Dörfler 
44654f3267eSAxel Dörfler int
dump_depot_magazine(int argCount,char ** args)44754f3267eSAxel Dörfler dump_depot_magazine(int argCount, char** args)
44854f3267eSAxel Dörfler {
44954f3267eSAxel Dörfler 	if (argCount != 2) {
45054f3267eSAxel Dörfler 		kprintf("usage: %s [address]\n", args[0]);
45154f3267eSAxel Dörfler 		return 0;
45254f3267eSAxel Dörfler 	}
45354f3267eSAxel Dörfler 
45454f3267eSAxel Dörfler 	DepotMagazine* magazine = (DepotMagazine*)parse_expression(args[1]);
45554f3267eSAxel Dörfler 
45654f3267eSAxel Dörfler 	kprintf("next:          %p\n", magazine->next);
45754f3267eSAxel Dörfler 	kprintf("current_round: %u\n", magazine->current_round);
45854f3267eSAxel Dörfler 	kprintf("round_count:   %u\n", magazine->round_count);
45954f3267eSAxel Dörfler 
46054f3267eSAxel Dörfler 	for (uint16 i = 0; i < magazine->current_round; i++)
46154f3267eSAxel Dörfler 		kprintf("  [%i] %p\n", i, magazine->rounds[i]);
46254f3267eSAxel Dörfler 
46354f3267eSAxel Dörfler 	return 0;
46454f3267eSAxel Dörfler }
465*e1c6140eSIngo Weinhold 
466*e1c6140eSIngo Weinhold 
467*e1c6140eSIngo Weinhold RANGE_MARKER_FUNCTION_END(SlabObjectDepot)
468