xref: /dragonfly/share/man/man9/objcache.9 (revision 35e996c9)
1.\"
2.\" Copyright (c) 2009
3.\"	The DragonFly Project.  All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\"
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in
13.\"    the documentation and/or other materials provided with the
14.\"    distribution.
15.\" 3. Neither the name of The DragonFly Project nor the names of its
16.\"    contributors may be used to endorse or promote products derived
17.\"    from this software without specific, prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
23.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.Dd January 25, 2024
33.Dt OBJCACHE 9
34.Os
35.Sh NAME
36.Nm objcache_create ,
37.Nm objcache_create_mbacked ,
38.Nm objcache_create_simple ,
39.Nm objcache_destroy ,
40.Nm objcache_dtor ,
41.Nm objcache_get ,
42.Nm objcache_malloc_alloc ,
43.Nm objcache_malloc_free ,
44.Nm objcache_nop_alloc ,
45.Nm objcache_nop_free ,
46.\" .Nm objcache_populate_linear ,
47.Nm objcache_put ,
48.Nm objcache_reclaimlist
49.Nd "object caching facility"
50.Sh SYNOPSIS
51.In sys/objcache.h
52.Bd -literal
53typedef boolean_t (objcache_ctor_fn)(void *obj, void *privdata, int ocflags);
54
55typedef void (objcache_dtor_fn)(void *obj, void *privdata);
56
57typedef void *(objcache_alloc_fn)(void *allocator_args, int ocflags);
58
59typedef void (objcache_free_fn)(void *obj, void *allocator_args);
60
61struct objcache_malloc_args {
62	size_t		objsize;
63	malloc_type_t	mtype;
64};
65.Ed
66.Ft struct objcache *
67.Fo objcache_create
68.Fa "const char *name"
69.Fa "int cluster_limit"
70.Fa "int mag_capacity"
71.Fa "objcache_ctor_fn *ctor"
72.Fa "objcache_dtor_fn *dtor"
73.Fa "void *privdata"
74.Fa "objcache_alloc_fn *alloc"
75.Fa "objcache_free_fn *free"
76.Fa "void *allocator_args"
77.Fc
78.Ft struct objcache *
79.Fo objcache_create_mbacked
80.Fa "malloc_type_t mtype"
81.Fa "size_t objsize"
82.Fa "int cluster_limit"
83.Fa "int mag_capacity"
84.Fa "objcache_ctor_fn *ctor"
85.Fa "objcache_dtor_fn *dtor"
86.Fa "void *privdata"
87.Fc
88.Ft struct objcache *
89.Fn objcache_create_simple "malloc_type_t mtype" "size_t objsize"
90.Ft void
91.Fn objcache_destroy "struct objcache *oc"
92.Ft void
93.Fn objcache_dtor "struct objcache *oc" "void *obj"
94.Ft void *
95.Fn objcache_get "struct objcache *oc" "int ocflags"
96.Ft void *
97.Fn objcache_malloc_alloc "void *allocator_args" "int ocflags"
98.Ft void
99.Fn objcache_malloc_free "void *obj" "void *allocator_args"
100.Ft void *
101.Fn objcache_nop_alloc "void *allocator_args" "int ocflags"
102.Ft void
103.Fn objcache_nop_free "void *obj" "void *allocator_args"
104.\" .Ft void
105.\" .Fo objcache_populate_linear
106.\" .Fa "struct objcache *oc"
107.\" .Fa "void *elts"
108.\" .Fa "int nelts"
109.\" .Fa "int size"
110.\" .Fc
111.Ft void
112.Fn objcache_put "struct objcache *oc" "void *obj"
113.Ft boolean_t
114.Fn objcache_reclaimlist "struct objcache *oc[]" "int nlist"
115.Sh DESCRIPTION
116Object caching is a technique for manipulating objects that are frequently
117allocated and freed.
118The idea behind caching is to preserve the invariant portion of an object's
119initial state between uses, so it does not have to be destroyed and reborn
120every time the object is used.
121.Pp
122.Fn objcache_create
123creates a new object cache.
124It is identified by
125.Fa name ,
126which is used to distinguish the object in diagnostic output.
127The
128.Fa cluster_limit
129determines the number of available magazines in the depot layer.
130It must be at least
131.Fa ( mag_capacity
132* ncpus * 8).
133If 0 is given, then there is no limit to the number of magazines the depot
134can have (aside from the inherent limitation imposed by the restricted nature
135of the back end allocator).
136The
137.Fa mag_capacity
138describes the capacity of the magazine, that is the largest number of objects
139it can hold.
140If set to 0, the default value is used as defined in
141.Pa sys/kern/kern_objcache.c .
142Currently, the default value is 64.
143The object caching system itself may adjust the cluster limit and/or
144magazines' capacity based on the number of available CPUs.
145.Fa ctor
146specifies a function that constructs (i.e., performs the one-time
147initialization of) an object in the cache.
148It is defined as:
149.Bd -literal
150boolean_t foo_ctor(void *obj, void *privdata, int ocflags);
151.Ed
152.Pp
153If no constructor is needed, it must be set to
154.Dv NULL .
155.Fa dtor
156specifies a destructor function that destroys the cached object, before it
157is released to the back end that manages the flow of real memory.
158It is defined as:
159.Bd -literal
160void foo_dtor(void *obj, void *privdata);
161.Ed
162.Pp
163If no destructor is needed, it must be set to
164.Dv NULL .
165The interface to underlying allocator is provided by
166.Fa alloc ,
167.Fa free
168and
169.Fa allocator_args .
170It must adhere to the following form:
171.Bd -literal
172void *foo_alloc(void *allocator_args, int ocflags);
173void foo_free(void *obj, void *allocator_args);
174.Ed
175.Pp
176.Fn objcache_malloc_alloc
177and
178.Fn objcache_malloc_free
179are wrappers for
180.Xr kmalloc 9
181allocation functions.
182Whereas,
183.Fn objcache_nop_alloc
184and
185.Fn objcache_nop_free
186are wrappers for allocation policies that pre-allocate at initialization time
187instead of doing run-time allocation.
188.Pp
189.Fn objcache_create_mbacked
190creates a new object cache of size
191.Fa objsize ,
192backed with a
193.Vt malloc_type_t
194argument.
195The latter is used to perform statistics in memory usage and for basic sanity
196checks.
197For the underlying allocator,
198.Xr kmalloc 9
199functions are employed.
200.Pp
201.Fn objcache_create_simple
202creates a new object cache of size
203.Fa objsize ,
204backed with a
205.Vt malloc_type_t
206argument.
207The
208.Fa cluster_limit
209is set to 0 and the default value for magazines' capacity is used.
210.Fa ctor
211and
212.Fa dtor
213are set to
214.Dv NULL .
215.Fa privdata
216is  set to
217.Dv NULL
218as well.
219For the underlying allocator,
220.Xr kmalloc 9
221functions are employed.
222.Pp
223.Fn objcache_get
224returns an object from the
225.Fa oc
226object cache.
227The object is in its initialized state.
228Newly allocated objects are subjected to the object cache's constructor
229function, if not
230.Dv NULL ,
231prior to being returned.
232.Fa ocflags
233is only used when the depot does not have any non-empty magazines and a new
234object needs to be allocated using the back end allocator.
235In this case we cannot depend on flags such as
236.Dv M_ZERO .
237If the back end allocator fails, or if the depot's object limit has been
238reached and
239.Dv M_WAITOK
240is not specified,
241.Dv NULL
242is returned.
243.Pp
244.Fn objcache_put
245returns
246.Fa obj
247to the
248.Fa oc
249object cache.
250The object must be in its initialized state prior to this call.
251If there is no empty magazine, the object destructor is called and
252the object is freed.
253.Pp
254.Fn objcache_dtor
255puts
256.Fa obj
257back into the
258.Fa oc
259object cache, indicating that the object is not in any shape to be reused and
260should be destructed and freed immediately.
261.Pp
262.Fn objcache_reclaimlist
263iterates over the
264.Fa oclist[]
265list with
266.Fa nlist
267elements and tries to free up some memory.
268For each object cache in the reclaim list, the current per-CPU cache is tried
269first and then the full magazine depot.
270The function returns
271.Dv TRUE
272as soon as some free memory is found
273and
274.Dv FALSE
275otherwise.
276.Pp
277.Fn objcache_destroy
278destroys the
279.Fa oc
280object cache.
281The object must have no existing references.
282.\" .Pp
283.\" .Fn objcache_populate_linear
284.\" populates the per-cluster depot with elements from a linear block of memory.
285.\" Must be called for individually for each cluster.
286.\" Populated depots should not be destroyed.
287.\" Currently this function is unimplemented.
288.Sh IMPLEMENTATION NOTES
289.Ss Magazine
290A magazine is the very basic functional unit of the object caching scheme.
291The number of objects it can hold is fixed and determined by its capacity.
292The term magazine is used as an analogy with automatic weapon
293(a firearm that can fire several rounds without reloading).
294.Ss Per-CPU object cache
295The reasoning behind per-CPU caches is to allow CPUs to perform their
296transactions (i.e., allocations, frees) in a parallel, yet lockless manner.
297.Pp
298Each CPU is given two magazines, an active and a backup.
299This is done in order to avoid a situation where a tight loop of
300two allocations followed by two frees can cause thrashing at the
301magazine boundary.
302.Pp
303If we need to add an object to the cache and the active magazine is full,
304room is searched in the backup magazine.
305If the backup has room, we swap active with backup and add the object.
306If both magazines are full, we get an empty magazine from the depot
307and move a fully loaded magazine to the depot.
308.Ss Magazine depot
309Each object cache manages a global supply of magazines, the depot, that is
310available across all CPUs.
311The depot maintains two lists of magazines.
312One for completely full and one for completely free magazines.
313The per-CPU object caches only exchange completely full or
314completely empty magazines with the depot layer.
315.Sh EXAMPLES
316.Bd -literal
317/* This is the data structure we are going to cache. */
318struct foo {
319        int x;
320        char str[32];
321};
322
323MALLOC_DEFINE(M_FOOBUF, "foobuf", "Buffer to my little precious data");
324
325struct objcache_malloc_args foo_malloc_args = {
326        sizeof(struct foo), M_FOOBUF };
327
328struct objcache *foo_cache;
329
330/*
331 * Object cache constructor.
332 */
333static boolean_t
334foo_cache_ctor(void *obj, void *privdata, int ocflags)
335{
336        struct foo *myfoo = obj;
337
338        /*
339         * Do any initialization of the object here. Let's just zero out
340         * the data structure for the fun of it.
341         */
342        bzero(myfoo, sizeof(*myfoo));
343
344        return (TRUE);
345}
346
347/*
348 * Object cache destructor.
349 */
350static void
351foo_cache_dtor(void *obj, void *privdata)
352{
353        struct foo *myfoo = obj;
354
355        /*
356         * Do any clean up here. E.g., if you have kmalloc'ed() inside
357         * the constructor, this is the right place and time to kfree().
358         */
359}
360
361/*
362 * Initialize our subsystem.
363 */
364static void
365foo_init(void)
366{
367        /* Create the object cache. */
368        foo_cache = objcache_create("foo",
369            0,                          /* infinite depot's capacity */
370            0,                          /* default magazine's capacity */
371            foo_ctor, foo_dtor, NULL,
372            objcache_malloc_alloc,
373            objcache_malloc_free,
374            &foo_malloc_args);
375}
376
377/*
378 * Random function.
379 */
380static void
381foo_random(...)
382{
383        struct foo *myfoo;
384
385        /* Get a `foo' object from the object cache. */
386        myfoo = objcache_get(foo_cache, M_WAITOK);
387
388        /* Do stuff with it. */
389        /* ... */
390
391        /* We don't need it anymore. Put it back in object cache. */
392        objcache_put(foo_cache, myfoo);
393}
394
395/*
396 * Shutdown our subsystem.
397 */
398static void
399foo_uninit(void)
400{
401        /* Destroy the object cache. */
402        objcache_destroy(foo_cache);
403}
404.Ed
405.Sh SEE ALSO
406.Xr memory 9
407.Rs
408.%A "Jeff Bonwick"
409.%T "The Slab Allocator: An Object-Caching Kernel Memory Allocator"
410.%R "USENIX Summer 1994 Technical Conference"
411.Re
412.Rs
413.%A "Jeff Bonwick"
414.%A "Jonathan Adams"
415.%T "Magazines and Vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources"
416.%R "USENIX 2001 Technical Conference"
417.Re
418.Sh HISTORY
419The object caching system appeared in
420.Dx 1.3 .
421.Sh AUTHORS
422The object caching system was written by
423.An -nosplit
424.An Jeffrey M. Hsu Aq Mt hsu@freebsd.org .
425This manual page was written by
426.An Stathis Kamperis Aq Mt ekamperi@gmail.com .
427