xref: /haiku/src/system/kernel/slab/ObjectDepot.cpp (revision ff59ce680df5d2032ea5a11c666688269225f033)
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 
19a8806e5eSIngo Weinhold #include "slab_private.h"
20a8806e5eSIngo Weinhold 
21a8806e5eSIngo Weinhold 
22825566f8SIngo Weinhold struct DepotMagazine {
23825566f8SIngo Weinhold 			DepotMagazine*		next;
24825566f8SIngo Weinhold 			uint16				current_round;
25825566f8SIngo Weinhold 			uint16				round_count;
26a8806e5eSIngo Weinhold 			void*				rounds[0];
27825566f8SIngo Weinhold 
28825566f8SIngo Weinhold public:
29825566f8SIngo Weinhold 	inline	bool				IsEmpty() const;
30825566f8SIngo Weinhold 	inline	bool				IsFull() const;
31825566f8SIngo Weinhold 
32825566f8SIngo Weinhold 	inline	void*				Pop();
33825566f8SIngo Weinhold 	inline	bool				Push(void* object);
34a8806e5eSIngo Weinhold };
35a8806e5eSIngo Weinhold 
36a8806e5eSIngo Weinhold 
37a8806e5eSIngo Weinhold struct depot_cpu_store {
38825566f8SIngo Weinhold 	DepotMagazine*	loaded;
39825566f8SIngo Weinhold 	DepotMagazine*	previous;
40a8806e5eSIngo Weinhold };
41a8806e5eSIngo Weinhold 
42a8806e5eSIngo Weinhold 
43825566f8SIngo Weinhold bool
44825566f8SIngo Weinhold DepotMagazine::IsEmpty() const
45a8806e5eSIngo Weinhold {
46825566f8SIngo Weinhold 	return current_round == 0;
47a8806e5eSIngo Weinhold }
48a8806e5eSIngo Weinhold 
49a8806e5eSIngo Weinhold 
50825566f8SIngo Weinhold bool
51825566f8SIngo Weinhold DepotMagazine::IsFull() const
52a8806e5eSIngo Weinhold {
53825566f8SIngo Weinhold 	return current_round == round_count;
54a8806e5eSIngo Weinhold }
55a8806e5eSIngo Weinhold 
56a8806e5eSIngo Weinhold 
57825566f8SIngo Weinhold void*
58825566f8SIngo Weinhold DepotMagazine::Pop()
59a8806e5eSIngo Weinhold {
60825566f8SIngo Weinhold 	return rounds[--current_round];
61a8806e5eSIngo Weinhold }
62a8806e5eSIngo Weinhold 
63a8806e5eSIngo Weinhold 
64825566f8SIngo Weinhold bool
65825566f8SIngo Weinhold DepotMagazine::Push(void* object)
66a8806e5eSIngo Weinhold {
67825566f8SIngo Weinhold 	if (IsFull())
68a8806e5eSIngo Weinhold 		return false;
69825566f8SIngo Weinhold 
70825566f8SIngo Weinhold 	rounds[current_round++] = object;
71a8806e5eSIngo Weinhold 	return true;
72a8806e5eSIngo Weinhold }
73a8806e5eSIngo Weinhold 
74a8806e5eSIngo Weinhold 
7554f3267eSAxel Dörfler // #pragma mark -
7654f3267eSAxel Dörfler 
7754f3267eSAxel Dörfler 
78825566f8SIngo Weinhold static DepotMagazine*
79*ff59ce68SAxel Dörfler alloc_magazine(object_depot* depot, uint32 flags)
80a8806e5eSIngo Weinhold {
81825566f8SIngo Weinhold 	DepotMagazine* magazine = (DepotMagazine*)slab_internal_alloc(
82*ff59ce68SAxel Dörfler 		sizeof(DepotMagazine) + depot->magazine_capacity * sizeof(void*),
83*ff59ce68SAxel Dörfler 		flags);
84a8806e5eSIngo Weinhold 	if (magazine) {
85a8806e5eSIngo Weinhold 		magazine->next = NULL;
86a8806e5eSIngo Weinhold 		magazine->current_round = 0;
87*ff59ce68SAxel Dörfler 		magazine->round_count = depot->magazine_capacity;
88a8806e5eSIngo Weinhold 	}
89a8806e5eSIngo Weinhold 
90a8806e5eSIngo Weinhold 	return magazine;
91a8806e5eSIngo Weinhold }
92a8806e5eSIngo Weinhold 
93a8806e5eSIngo Weinhold 
94a8806e5eSIngo Weinhold static void
9586c794e5SIngo Weinhold free_magazine(DepotMagazine* magazine, uint32 flags)
96a8806e5eSIngo Weinhold {
9786c794e5SIngo Weinhold 	slab_internal_free(magazine, flags);
98a8806e5eSIngo Weinhold }
99a8806e5eSIngo Weinhold 
100a8806e5eSIngo Weinhold 
101a8806e5eSIngo Weinhold static void
10286c794e5SIngo Weinhold empty_magazine(object_depot* depot, DepotMagazine* magazine, uint32 flags)
103a8806e5eSIngo Weinhold {
104a8806e5eSIngo Weinhold 	for (uint16 i = 0; i < magazine->current_round; i++)
10586c794e5SIngo Weinhold 		depot->return_object(depot, depot->cookie, magazine->rounds[i], flags);
10686c794e5SIngo Weinhold 	free_magazine(magazine, flags);
107a8806e5eSIngo Weinhold }
108a8806e5eSIngo Weinhold 
109a8806e5eSIngo Weinhold 
110a8806e5eSIngo Weinhold static bool
111825566f8SIngo Weinhold exchange_with_full(object_depot* depot, DepotMagazine*& magazine)
112a8806e5eSIngo Weinhold {
113*ff59ce68SAxel Dörfler 	ASSERT(magazine->IsEmpty());
114*ff59ce68SAxel Dörfler 
115453a2bddSIngo Weinhold 	SpinLocker _(depot->inner_lock);
116a8806e5eSIngo Weinhold 
117a8806e5eSIngo Weinhold 	if (depot->full == NULL)
118a8806e5eSIngo Weinhold 		return false;
119a8806e5eSIngo Weinhold 
120a8806e5eSIngo Weinhold 	depot->full_count--;
121a8806e5eSIngo Weinhold 	depot->empty_count++;
122a8806e5eSIngo Weinhold 
123a8806e5eSIngo Weinhold 	_push(depot->empty, magazine);
124a8806e5eSIngo Weinhold 	magazine = _pop(depot->full);
125a8806e5eSIngo Weinhold 	return true;
126a8806e5eSIngo Weinhold }
127a8806e5eSIngo Weinhold 
128a8806e5eSIngo Weinhold 
129a8806e5eSIngo Weinhold static bool
130*ff59ce68SAxel Dörfler exchange_with_empty(object_depot* depot, DepotMagazine*& magazine,
131*ff59ce68SAxel Dörfler 	DepotMagazine*& freeMagazine)
132a8806e5eSIngo Weinhold {
133*ff59ce68SAxel Dörfler 	ASSERT(magazine == NULL || magazine->IsFull());
134*ff59ce68SAxel Dörfler 
135453a2bddSIngo Weinhold 	SpinLocker _(depot->inner_lock);
136a8806e5eSIngo Weinhold 
137a8806e5eSIngo Weinhold 	if (depot->empty == NULL)
138a8806e5eSIngo Weinhold 		return false;
139453a2bddSIngo Weinhold 
140a8806e5eSIngo Weinhold 	depot->empty_count--;
141a8806e5eSIngo Weinhold 
142*ff59ce68SAxel Dörfler 	if (magazine != NULL) {
143*ff59ce68SAxel Dörfler 		if (depot->full_count < depot->max_count) {
144a8806e5eSIngo Weinhold 			_push(depot->full, magazine);
145a8806e5eSIngo Weinhold 			depot->full_count++;
146*ff59ce68SAxel Dörfler 		} else
147*ff59ce68SAxel Dörfler 			freeMagazine = magazine;
148a8806e5eSIngo Weinhold 	}
149a8806e5eSIngo Weinhold 
150a8806e5eSIngo Weinhold 	magazine = _pop(depot->empty);
151a8806e5eSIngo Weinhold 	return true;
152a8806e5eSIngo Weinhold }
153a8806e5eSIngo Weinhold 
154a8806e5eSIngo Weinhold 
155453a2bddSIngo Weinhold static void
156453a2bddSIngo Weinhold push_empty_magazine(object_depot* depot, DepotMagazine* magazine)
157453a2bddSIngo Weinhold {
158453a2bddSIngo Weinhold 	SpinLocker _(depot->inner_lock);
159453a2bddSIngo Weinhold 
160453a2bddSIngo Weinhold 	_push(depot->empty, magazine);
16154f3267eSAxel Dörfler 	depot->empty_count++;
162453a2bddSIngo Weinhold }
163453a2bddSIngo Weinhold 
164453a2bddSIngo Weinhold 
165a8806e5eSIngo Weinhold static inline depot_cpu_store*
166a8806e5eSIngo Weinhold object_depot_cpu(object_depot* depot)
167a8806e5eSIngo Weinhold {
168a8806e5eSIngo Weinhold 	return &depot->stores[smp_get_current_cpu()];
169a8806e5eSIngo Weinhold }
170a8806e5eSIngo Weinhold 
171a8806e5eSIngo Weinhold 
172453a2bddSIngo Weinhold // #pragma mark - public API
173453a2bddSIngo Weinhold 
174453a2bddSIngo Weinhold 
175453a2bddSIngo Weinhold status_t
176*ff59ce68SAxel Dörfler object_depot_init(object_depot* depot, size_t capacity, size_t maxCount,
177*ff59ce68SAxel Dörfler 	uint32 flags, void* cookie, void (*return_object)(object_depot* depot,
178*ff59ce68SAxel Dörfler 		void* cookie, void* object, uint32 flags))
179a8806e5eSIngo Weinhold {
180453a2bddSIngo Weinhold 	depot->full = NULL;
181453a2bddSIngo Weinhold 	depot->empty = NULL;
182453a2bddSIngo Weinhold 	depot->full_count = depot->empty_count = 0;
183*ff59ce68SAxel Dörfler 	depot->max_count = maxCount;
184*ff59ce68SAxel Dörfler 	depot->magazine_capacity = capacity;
185453a2bddSIngo Weinhold 
186453a2bddSIngo Weinhold 	rw_lock_init(&depot->outer_lock, "object depot");
187453a2bddSIngo Weinhold 	B_INITIALIZE_SPINLOCK(&depot->inner_lock);
188453a2bddSIngo Weinhold 
189453a2bddSIngo Weinhold 	int cpuCount = smp_get_num_cpus();
190453a2bddSIngo Weinhold 	depot->stores = (depot_cpu_store*)slab_internal_alloc(
191453a2bddSIngo Weinhold 		sizeof(depot_cpu_store) * cpuCount, flags);
192453a2bddSIngo Weinhold 	if (depot->stores == NULL) {
193453a2bddSIngo Weinhold 		rw_lock_destroy(&depot->outer_lock);
194453a2bddSIngo Weinhold 		return B_NO_MEMORY;
195453a2bddSIngo Weinhold 	}
196453a2bddSIngo Weinhold 
197453a2bddSIngo Weinhold 	for (int i = 0; i < cpuCount; i++) {
198453a2bddSIngo Weinhold 		depot->stores[i].loaded = NULL;
199453a2bddSIngo Weinhold 		depot->stores[i].previous = NULL;
200453a2bddSIngo Weinhold 	}
201453a2bddSIngo Weinhold 
202453a2bddSIngo Weinhold 	depot->cookie = cookie;
203453a2bddSIngo Weinhold 	depot->return_object = return_object;
204453a2bddSIngo Weinhold 
205453a2bddSIngo Weinhold 	return B_OK;
206453a2bddSIngo Weinhold }
207453a2bddSIngo Weinhold 
208453a2bddSIngo Weinhold 
209453a2bddSIngo Weinhold void
21086c794e5SIngo Weinhold object_depot_destroy(object_depot* depot, uint32 flags)
211453a2bddSIngo Weinhold {
21286c794e5SIngo Weinhold 	object_depot_make_empty(depot, flags);
213453a2bddSIngo Weinhold 
21486c794e5SIngo Weinhold 	slab_internal_free(depot->stores, flags);
215453a2bddSIngo Weinhold 
216453a2bddSIngo Weinhold 	rw_lock_destroy(&depot->outer_lock);
217453a2bddSIngo Weinhold }
218453a2bddSIngo Weinhold 
219453a2bddSIngo Weinhold 
220453a2bddSIngo Weinhold void*
221453a2bddSIngo Weinhold object_depot_obtain(object_depot* depot)
222453a2bddSIngo Weinhold {
223453a2bddSIngo Weinhold 	ReadLocker readLocker(depot->outer_lock);
224453a2bddSIngo Weinhold 	InterruptsLocker interruptsLocker;
225453a2bddSIngo Weinhold 
226453a2bddSIngo Weinhold 	depot_cpu_store* store = object_depot_cpu(depot);
227a8806e5eSIngo Weinhold 
228a8806e5eSIngo Weinhold 	// To better understand both the Alloc() and Free() logic refer to
229a8806e5eSIngo Weinhold 	// Bonwick's ``Magazines and Vmem'' [in 2001 USENIX proceedings]
230a8806e5eSIngo Weinhold 
231a8806e5eSIngo Weinhold 	// In a nutshell, we try to get an object from the loaded magazine
232a8806e5eSIngo Weinhold 	// if it's not empty, or from the previous magazine if it's full
233a8806e5eSIngo Weinhold 	// and finally from the Slab if the magazine depot has no full magazines.
234a8806e5eSIngo Weinhold 
235a8806e5eSIngo Weinhold 	if (store->loaded == NULL)
236a8806e5eSIngo Weinhold 		return NULL;
237a8806e5eSIngo Weinhold 
238a8806e5eSIngo Weinhold 	while (true) {
239825566f8SIngo Weinhold 		if (!store->loaded->IsEmpty())
240825566f8SIngo Weinhold 			return store->loaded->Pop();
241a8806e5eSIngo Weinhold 
242825566f8SIngo Weinhold 		if (store->previous
243825566f8SIngo Weinhold 			&& (store->previous->IsFull()
244825566f8SIngo Weinhold 				|| exchange_with_full(depot, store->previous))) {
245a8806e5eSIngo Weinhold 			std::swap(store->previous, store->loaded);
246825566f8SIngo Weinhold 		} else
247a8806e5eSIngo Weinhold 			return NULL;
248a8806e5eSIngo Weinhold 	}
249a8806e5eSIngo Weinhold }
250a8806e5eSIngo Weinhold 
251a8806e5eSIngo Weinhold 
252453a2bddSIngo Weinhold int
25386c794e5SIngo Weinhold object_depot_store(object_depot* depot, void* object, uint32 flags)
254a8806e5eSIngo Weinhold {
255*ff59ce68SAxel Dörfler 	DepotMagazine* freeMagazine = NULL;
256*ff59ce68SAxel Dörfler 
257453a2bddSIngo Weinhold 	ReadLocker readLocker(depot->outer_lock);
258453a2bddSIngo Weinhold 	InterruptsLocker interruptsLocker;
259453a2bddSIngo Weinhold 
260453a2bddSIngo Weinhold 	depot_cpu_store* store = object_depot_cpu(depot);
261a8806e5eSIngo Weinhold 
262a8806e5eSIngo Weinhold 	// We try to add the object to the loaded magazine if we have one
263a8806e5eSIngo Weinhold 	// and it's not full, or to the previous one if it is empty. If
264a8806e5eSIngo Weinhold 	// the magazine depot doesn't provide us with a new empty magazine
265a8806e5eSIngo Weinhold 	// we return the object directly to the slab.
266a8806e5eSIngo Weinhold 
267a8806e5eSIngo Weinhold 	while (true) {
268*ff59ce68SAxel Dörfler 		if (store->loaded != NULL && store->loaded->Push(object))
269a8806e5eSIngo Weinhold 			return 1;
270a8806e5eSIngo Weinhold 
271*ff59ce68SAxel Dörfler 		if ((store->previous != NULL && store->previous->IsEmpty())
272*ff59ce68SAxel Dörfler 			|| exchange_with_empty(depot, store->previous, freeMagazine)) {
273a8806e5eSIngo Weinhold 			std::swap(store->loaded, store->previous);
274*ff59ce68SAxel Dörfler 
275*ff59ce68SAxel Dörfler 			if (freeMagazine != NULL) {
276*ff59ce68SAxel Dörfler 				// Free the magazine that didn't have space in the list
277*ff59ce68SAxel Dörfler 				interruptsLocker.Unlock();
278*ff59ce68SAxel Dörfler 				readLocker.Unlock();
279*ff59ce68SAxel Dörfler 
280*ff59ce68SAxel Dörfler 				empty_magazine(depot, freeMagazine, flags);
281*ff59ce68SAxel Dörfler 
282*ff59ce68SAxel Dörfler 				readLocker.Lock();
283*ff59ce68SAxel Dörfler 				interruptsLocker.Lock();
284*ff59ce68SAxel Dörfler 
285*ff59ce68SAxel Dörfler 				store = object_depot_cpu(depot);
286*ff59ce68SAxel Dörfler 			}
287453a2bddSIngo Weinhold 		} else {
288453a2bddSIngo Weinhold 			// allocate a new empty magazine
289453a2bddSIngo Weinhold 			interruptsLocker.Unlock();
290453a2bddSIngo Weinhold 			readLocker.Unlock();
291453a2bddSIngo Weinhold 
292*ff59ce68SAxel Dörfler 			DepotMagazine* magazine = alloc_magazine(depot, flags);
293453a2bddSIngo Weinhold 			if (magazine == NULL)
294a8806e5eSIngo Weinhold 				return 0;
295453a2bddSIngo Weinhold 
296453a2bddSIngo Weinhold 			readLocker.Lock();
297453a2bddSIngo Weinhold 			interruptsLocker.Lock();
298453a2bddSIngo Weinhold 
299453a2bddSIngo Weinhold 			push_empty_magazine(depot, magazine);
300453a2bddSIngo Weinhold 			store = object_depot_cpu(depot);
301a8806e5eSIngo Weinhold 		}
302a8806e5eSIngo Weinhold 	}
303a8806e5eSIngo Weinhold }
304a8806e5eSIngo Weinhold 
305a8806e5eSIngo Weinhold 
306a8806e5eSIngo Weinhold void
30786c794e5SIngo Weinhold object_depot_make_empty(object_depot* depot, uint32 flags)
308a8806e5eSIngo Weinhold {
309453a2bddSIngo Weinhold 	WriteLocker writeLocker(depot->outer_lock);
310453a2bddSIngo Weinhold 
311453a2bddSIngo Weinhold 	// collect the store magazines
312453a2bddSIngo Weinhold 
313453a2bddSIngo Weinhold 	DepotMagazine* storeMagazines = NULL;
314453a2bddSIngo Weinhold 
315bcf73b3aSIngo Weinhold 	int cpuCount = smp_get_num_cpus();
316bcf73b3aSIngo Weinhold 	for (int i = 0; i < cpuCount; i++) {
317453a2bddSIngo Weinhold 		depot_cpu_store& store = depot->stores[i];
318a8806e5eSIngo Weinhold 
319453a2bddSIngo Weinhold 		if (store.loaded) {
320453a2bddSIngo Weinhold 			_push(storeMagazines, store.loaded);
321453a2bddSIngo Weinhold 			store.loaded = NULL;
322a8806e5eSIngo Weinhold 		}
323a8806e5eSIngo Weinhold 
324453a2bddSIngo Weinhold 		if (store.previous) {
325453a2bddSIngo Weinhold 			_push(storeMagazines, store.previous);
326453a2bddSIngo Weinhold 			store.previous = NULL;
327453a2bddSIngo Weinhold 		}
328453a2bddSIngo Weinhold 	}
329a8806e5eSIngo Weinhold 
330453a2bddSIngo Weinhold 	// detach the depot's full and empty magazines
331a8806e5eSIngo Weinhold 
332453a2bddSIngo Weinhold 	DepotMagazine* fullMagazines = depot->full;
333453a2bddSIngo Weinhold 	depot->full = NULL;
334453a2bddSIngo Weinhold 
335453a2bddSIngo Weinhold 	DepotMagazine* emptyMagazines = depot->empty;
336453a2bddSIngo Weinhold 	depot->empty = NULL;
337453a2bddSIngo Weinhold 
338453a2bddSIngo Weinhold 	writeLocker.Unlock();
339453a2bddSIngo Weinhold 
340453a2bddSIngo Weinhold 	// free all magazines
341453a2bddSIngo Weinhold 
342453a2bddSIngo Weinhold 	while (storeMagazines != NULL)
34386c794e5SIngo Weinhold 		empty_magazine(depot, _pop(storeMagazines), flags);
344453a2bddSIngo Weinhold 
345453a2bddSIngo Weinhold 	while (fullMagazines != NULL)
34686c794e5SIngo Weinhold 		empty_magazine(depot, _pop(fullMagazines), flags);
347453a2bddSIngo Weinhold 
348453a2bddSIngo Weinhold 	while (emptyMagazines)
34986c794e5SIngo Weinhold 		free_magazine(_pop(emptyMagazines), flags);
350a8806e5eSIngo Weinhold }
35154f3267eSAxel Dörfler 
35254f3267eSAxel Dörfler 
35354f3267eSAxel Dörfler // #pragma mark - private kernel API
35454f3267eSAxel Dörfler 
35554f3267eSAxel Dörfler 
35654f3267eSAxel Dörfler void
35754f3267eSAxel Dörfler dump_object_depot(object_depot* depot)
35854f3267eSAxel Dörfler {
35954f3267eSAxel Dörfler 	kprintf("  full:  %p, count %lu\n", depot->full, depot->full_count);
36054f3267eSAxel Dörfler 	kprintf("  empty: %p, count %lu\n", depot->empty, depot->empty_count);
36154f3267eSAxel Dörfler 	kprintf("  stores:\n");
36254f3267eSAxel Dörfler 
36354f3267eSAxel Dörfler 	int cpuCount = smp_get_num_cpus();
36454f3267eSAxel Dörfler 
36554f3267eSAxel Dörfler 	for (int i = 0; i < cpuCount; i++) {
36654f3267eSAxel Dörfler 		kprintf("  [%d] loaded:   %p\n", i, depot->stores[i].loaded);
36754f3267eSAxel Dörfler 		kprintf("      previous: %p\n", depot->stores[i].previous);
36854f3267eSAxel Dörfler 	}
36954f3267eSAxel Dörfler }
37054f3267eSAxel Dörfler 
37154f3267eSAxel Dörfler 
37254f3267eSAxel Dörfler int
37354f3267eSAxel Dörfler dump_object_depot(int argCount, char** args)
37454f3267eSAxel Dörfler {
37554f3267eSAxel Dörfler 	if (argCount != 2)
37654f3267eSAxel Dörfler 		kprintf("usage: %s [address]\n", args[0]);
37754f3267eSAxel Dörfler 	else
37854f3267eSAxel Dörfler 		dump_object_depot((object_depot*)parse_expression(args[1]));
37954f3267eSAxel Dörfler 
38054f3267eSAxel Dörfler 	return 0;
38154f3267eSAxel Dörfler }
38254f3267eSAxel Dörfler 
38354f3267eSAxel Dörfler 
38454f3267eSAxel Dörfler int
38554f3267eSAxel Dörfler dump_depot_magazine(int argCount, char** args)
38654f3267eSAxel Dörfler {
38754f3267eSAxel Dörfler 	if (argCount != 2) {
38854f3267eSAxel Dörfler 		kprintf("usage: %s [address]\n", args[0]);
38954f3267eSAxel Dörfler 		return 0;
39054f3267eSAxel Dörfler 	}
39154f3267eSAxel Dörfler 
39254f3267eSAxel Dörfler 	DepotMagazine* magazine = (DepotMagazine*)parse_expression(args[1]);
39354f3267eSAxel Dörfler 
39454f3267eSAxel Dörfler 	kprintf("next:          %p\n", magazine->next);
39554f3267eSAxel Dörfler 	kprintf("current_round: %u\n", magazine->current_round);
39654f3267eSAxel Dörfler 	kprintf("round_count:   %u\n", magazine->round_count);
39754f3267eSAxel Dörfler 
39854f3267eSAxel Dörfler 	for (uint16 i = 0; i < magazine->current_round; i++)
39954f3267eSAxel Dörfler 		kprintf("  [%i] %p\n", i, magazine->rounds[i]);
40054f3267eSAxel Dörfler 
40154f3267eSAxel Dörfler 	return 0;
40254f3267eSAxel Dörfler }
403