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
19e1c6140eSIngo Weinhold#include "slab_debug.h"
20a8806e5eSIngo Weinhold#include "slab_private.h"
21a8806e5eSIngo Weinhold
22a8806e5eSIngo Weinhold
23825566f8SIngo Weinholdstruct DepotMagazine {
24825566f8SIngo Weinhold			DepotMagazine*		next;
25825566f8SIngo Weinhold			uint16				current_round;
26825566f8SIngo Weinhold			uint16				round_count;
27825566f8SIngo Weinhold			void*				rounds[0];
28825566f8SIngo Weinhold
29825566f8SIngo Weinholdpublic:
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 Weinholdstruct depot_cpu_store {
43825566f8SIngo Weinhold	DepotMagazine*	loaded;
44825566f8SIngo Weinhold	DepotMagazine*	previous;
45a8806e5eSIngo Weinhold};
46a8806e5eSIngo Weinhold
47a8806e5eSIngo Weinhold
48e1c6140eSIngo WeinholdRANGE_MARKER_FUNCTION_BEGIN(SlabObjectDepot)
49e1c6140eSIngo Weinhold
50e1c6140eSIngo Weinhold
51825566f8SIngo Weinholdbool
52825566f8SIngo WeinholdDepotMagazine::IsEmpty() const
53a8806e5eSIngo Weinhold{
54825566f8SIngo Weinhold	return current_round == 0;
55a8806e5eSIngo Weinhold}
56a8806e5eSIngo Weinhold
57a8806e5eSIngo Weinhold
58825566f8SIngo Weinholdbool
59825566f8SIngo WeinholdDepotMagazine::IsFull() const
60a8806e5eSIngo Weinhold{
61825566f8SIngo Weinhold	return current_round == round_count;
62a8806e5eSIngo Weinhold}
63a8806e5eSIngo Weinhold
64a8806e5eSIngo Weinhold
65825566f8SIngo Weinholdvoid*
66825566f8SIngo WeinholdDepotMagazine::Pop()
67a8806e5eSIngo Weinhold{
68825566f8SIngo Weinhold	return rounds[--current_round];
69a8806e5eSIngo Weinhold}
70a8806e5eSIngo Weinhold
71a8806e5eSIngo Weinhold
72825566f8SIngo Weinholdbool
73825566f8SIngo WeinholdDepotMagazine::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 Lotzbool
8672156a40SMichael LotzDepotMagazine::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 Weinholdstatic DepotMagazine*
103ff59ce68SAxel Dörfleralloc_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 Weinholdstatic void
11986c794e5SIngo Weinholdfree_magazine(DepotMagazine* magazine, uint32 flags)
120a8806e5eSIngo Weinhold{
12186c794e5SIngo Weinhold	slab_internal_free(magazine, flags);
122a8806e5eSIngo Weinhold}
123a8806e5eSIngo Weinhold
124a8806e5eSIngo Weinhold
125a8806e5eSIngo Weinholdstatic void
12686c794e5SIngo Weinholdempty_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 Weinholdstatic bool
135825566f8SIngo Weinholdexchange_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 Weinholdstatic bool
154ff59ce68SAxel Dörflerexchange_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);
160453a2bddSIngo Weinhold
161453a2bddSIngo Weinhold	if (depot->empty == NULL)
162453a2bddSIngo Weinhold		return false;
163453a2bddSIngo Weinhold
164453a2bddSIngo Weinhold	depot->empty_count--;
165a8806e5eSIngo Weinhold
166ff59ce68SAxel Dörfler	if (magazine != NULL) {
167ff59ce68SAxel Dörfler		if (depot->full_count < depot->max_count) {
168ff59ce68SAxel Dörfler			_push(depot->full, magazine);
169ff59ce68SAxel Dörfler			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 Weinholdstatic void
181453a2bddSIngo Weinholdpush_empty_magazine(object_depot* depot, DepotMagazine* magazine)
182a8806e5eSIngo Weinhold{
183453a2bddSIngo Weinhold	SpinLocker _(depot->inner_lock);
184a8806e5eSIngo Weinhold
185453a2bddSIngo Weinhold	_push(depot->empty, magazine);
18654f3267eSAxel Dörfler	depot->empty_count++;
187a8806e5eSIngo Weinhold}
188a8806e5eSIngo Weinhold
189a8806e5eSIngo Weinhold
190453a2bddSIngo Weinholdstatic inline depot_cpu_store*
191453a2bddSIngo Weinholdobject_depot_cpu(object_depot* depot)
192a8806e5eSIngo Weinhold{
193453a2bddSIngo Weinhold	return &depot->stores[smp_get_current_cpu()];
194a8806e5eSIngo Weinhold}
195a8806e5eSIngo Weinhold
196a8806e5eSIngo Weinhold
197030a4ea6SIngo Weinhold// #pragma mark - public API
198030a4ea6SIngo Weinhold
199030a4ea6SIngo Weinhold
200030a4ea6SIngo Weinholdstatus_t
201ff59ce68SAxel Dörflerobject_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))
204030a4ea6SIngo Weinhold{
205030a4ea6SIngo Weinhold	depot->full = NULL;
206030a4ea6SIngo Weinhold	depot->empty = NULL;
207030a4ea6SIngo Weinhold	depot->full_count = depot->empty_count = 0;
208ff59ce68SAxel Dörfler	depot->max_count = maxCount;
209ff59ce68SAxel Dörfler	depot->magazine_capacity = capacity;
210030a4ea6SIngo Weinhold
211453a2bddSIngo Weinhold	rw_lock_init(&depot->outer_lock, "object depot");
212453a2bddSIngo Weinhold	B_INITIALIZE_SPINLOCK(&depot->inner_lock);
213030a4ea6SIngo Weinhold
214030a4ea6SIngo Weinhold	int cpuCount = smp_get_num_cpus();
215030a4ea6SIngo Weinhold	depot->stores = (depot_cpu_store*)slab_internal_alloc(
216030a4ea6SIngo Weinhold		sizeof(depot_cpu_store) * cpuCount, flags);
217030a4ea6SIngo Weinhold	if (depot->stores == NULL) {
218453a2bddSIngo Weinhold		rw_lock_destroy(&depot->outer_lock);
219030a4ea6SIngo Weinhold		return B_NO_MEMORY;
220030a4ea6SIngo Weinhold	}
221030a4ea6SIngo Weinhold
222030a4ea6SIngo Weinhold	for (int i = 0; i < cpuCount; i++) {
223453a2bddSIngo Weinhold		depot->stores[i].loaded = NULL;
224453a2bddSIngo Weinhold		depot->stores[i].previous = NULL;
225030a4ea6SIngo Weinhold	}
226030a4ea6SIngo Weinhold
227030a4ea6SIngo Weinhold	depot->cookie = cookie;
228030a4ea6SIngo Weinhold	depot->return_object = return_object;
229030a4ea6SIngo Weinhold
230030a4ea6SIngo Weinhold	return B_OK;
231030a4ea6SIngo Weinhold}
232030a4ea6SIngo Weinhold
233030a4ea6SIngo Weinhold
234030a4ea6SIngo Weinholdvoid
23586c794e5SIngo Weinholdobject_depot_destroy(object_depot* depot, uint32 flags)
236030a4ea6SIngo Weinhold{
23786c794e5SIngo Weinhold	object_depot_make_empty(depot, flags);
238030a4ea6SIngo Weinhold
23986c794e5SIngo Weinhold	slab_internal_free(depot->stores, flags);
240030a4ea6SIngo Weinhold
241453a2bddSIngo Weinhold	rw_lock_destroy(&depot->outer_lock);
242030a4ea6SIngo Weinhold}
243030a4ea6SIngo Weinhold
244030a4ea6SIngo Weinhold
245825566f8SIngo Weinholdvoid*
246825566f8SIngo Weinholdobject_depot_obtain(object_depot* depot)
247a8806e5eSIngo Weinhold{
248453a2bddSIngo Weinhold	ReadLocker readLocker(depot->outer_lock);
249453a2bddSIngo Weinhold	InterruptsLocker interruptsLocker;
250453a2bddSIngo Weinhold
251453a2bddSIngo Weinhold	depot_cpu_store* store = object_depot_cpu(depot);
252453a2bddSIngo Weinhold
253453a2bddSIngo Weinhold	// To better understand both the Alloc() and Free() logic refer to
254453a2bddSIngo Weinhold	// Bonwick's ``Magazines and Vmem'' [in 2001 USENIX proceedings]
255453a2bddSIngo Weinhold
256453a2bddSIngo Weinhold	// In a nutshell, we try to get an object from the loaded magazine
257453a2bddSIngo Weinhold	// if it's not empty, or from the previous magazine if it's full
258453a2bddSIngo Weinhold	// and finally from the Slab if the magazine depot has no full magazines.
259453a2bddSIngo Weinhold
260453a2bddSIngo Weinhold	if (store->loaded == NULL)
261453a2bddSIngo Weinhold		return NULL;
262453a2bddSIngo Weinhold
263453a2bddSIngo Weinhold	while (true) {
264453a2bddSIngo Weinhold		if (!store->loaded->IsEmpty())
265453a2bddSIngo Weinhold			return store->loaded->Pop();
266453a2bddSIngo Weinhold
267453a2bddSIngo Weinhold		if (store->previous
268453a2bddSIngo Weinhold			&& (store->previous->IsFull()
269453a2bddSIngo Weinhold				|| exchange_with_full(depot, store->previous))) {
270453a2bddSIngo Weinhold			std::swap(store->previous, store->loaded);
271453a2bddSIngo Weinhold		} else
272453a2bddSIngo Weinhold			return NULL;
273453a2bddSIngo Weinhold	}
274a8806e5eSIngo Weinhold}
275a8806e5eSIngo Weinhold
276a8806e5eSIngo Weinhold
277464d9f12SIngo Weinholdvoid
27886c794e5SIngo Weinholdobject_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);
284453a2bddSIngo Weinhold
285453a2bddSIngo Weinhold	// We try to add the object to the loaded magazine if we have one
286453a2bddSIngo Weinhold	// and it's not full, or to the previous one if it is empty. If
287453a2bddSIngo Weinhold	// the magazine depot doesn't provide us with a new empty magazine
288453a2bddSIngo Weinhold	// we return the object directly to the slab.
289453a2bddSIngo Weinhold
290453a2bddSIngo Weinhold	while (true) {
291ff59ce68SAxel Dörfler		if (store->loaded != NULL && store->loaded->Push(object))
292464d9f12SIngo Weinhold			return;
293453a2bddSIngo 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)) {
297453a2bddSIngo 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);
327453a2bddSIngo Weinhold		}
328453a2bddSIngo Weinhold	}
329a8806e5eSIngo Weinhold}
330a8806e5eSIngo Weinhold
331a8806e5eSIngo Weinhold
332a8806e5eSIngo Weinholdvoid
33386c794e5SIngo Weinholdobject_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;
348453a2bddSIngo Weinhold		}
349a8806e5eSIngo Weinhold
350453a2bddSIngo Weinhold		if (store.previous) {
351453a2bddSIngo Weinhold			_push(storeMagazines, store.previous);
352453a2bddSIngo Weinhold			store.previous = NULL;
353453a2bddSIngo Weinhold		}
354a8806e5eSIngo Weinhold	}
355a8806e5eSIngo Weinhold
356453a2bddSIngo Weinhold	// detach the depot's full and empty magazines
357453a2bddSIngo 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);
370a8806e5eSIngo Weinhold
371453a2bddSIngo Weinhold	while (fullMagazines != NULL)
37286c794e5SIngo Weinhold		empty_magazine(depot, _pop(fullMagazines), flags);
373a8806e5eSIngo 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 Lotzbool
38272156a40SMichael Lotzobject_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örflervoid
41754f3267eSAxel Dörflerdump_object_depot(object_depot* depot)
41854f3267eSAxel Dörfler{
4196426413dSAxel Dörfler	kprintf("  full:     %p, count %lu\n", depot->full, depot->full_count);
4206426413dSAxel 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örflerint
43554f3267eSAxel Dörflerdump_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örflerint
44754f3267eSAxel Dörflerdump_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}
465e1c6140eSIngo Weinhold
466e1c6140eSIngo Weinhold
467e1c6140eSIngo WeinholdRANGE_MARKER_FUNCTION_END(SlabObjectDepot)
468