NAME
objcache_create
,
objcache_create_mbacked
,
objcache_create_simple
,
objcache_destroy
,
objcache_dtor
, objcache_get
,
objcache_malloc_alloc
,
objcache_malloc_free
,
objcache_nop_alloc
,
objcache_nop_free
,
objcache_put
,
objcache_reclaimlist
—
object caching facility
SYNOPSIS
#include
<sys/objcache.h>
struct objcache *
objcache_create
(const char
*name, int cluster_limit, int
mag_capacity, objcache_ctor_fn *ctor,
objcache_dtor_fn *dtor, void
*privdata, objcache_alloc_fn *alloc,
objcache_free_fn *free, void
*allocator_args);
struct objcache *
objcache_create_mbacked
(malloc_type_t
mtype, size_t objsize, int
cluster_limit, int mag_capacity,
objcache_ctor_fn *ctor,
objcache_dtor_fn *dtor, void
*privdata);
struct objcache *
objcache_create_simple
(malloc_type_t
mtype, size_t
objsize);
void
objcache_destroy
(struct
objcache *oc);
void
objcache_dtor
(struct
objcache *oc, void
*obj);
void *
objcache_get
(struct
objcache *oc, int
ocflags);
void *
objcache_malloc_alloc
(void
*allocator_args, int
ocflags);
void
objcache_malloc_free
(void
*obj, void
*allocator_args);
void *
objcache_nop_alloc
(void
*allocator_args, int
ocflags);
void
objcache_nop_free
(void
*obj, void
*allocator_args);
void
objcache_put
(struct
objcache *oc, void
*obj);
boolean_t
objcache_reclaimlist
(struct
objcache *oc[], int
nlist, int
ocflags);
DESCRIPTION
Object caching is a technique for manipulating objects that are frequently allocated and freed. The idea behind caching is to preserve the invariant portion of an object's initial state between uses, so it does not have to be destroyed and reborn every time the object is used.objcache_create
()
creates a new object cache. It is identified by name,
which is used to distinguish the object in diagnostic output. The
cluster_limit determines the number of available
magazines in the depot layer. It must be at least
mag_capacity * ncpus * 8. If 0 is given, then there is
no limit to the number of magazines the depot can have (aside from the
inherent limitation imposed by the restricted nature of the back end
allocator). The mag_capacity describes the capacity of
the magazine, that is the largest number of objects it can hold. If set to
0, the default value is used as defined in
sys/kern/kern_objcache.c. Currently, the default
value is 64. The object caching system itself may adjust the cluster limit
and/or magazines' capacity based on the number of available CPUs.
ctor specifies a function that constructs (i.e.,
performs the one-time initialization of) an object in the cache. It is
defined as:
boolean_t foo_ctor(void *obj, void *privdata, int ocflags);
If no constructor is needed, it must be set to
NULL
. dtor specifies a
deconstructor function that destroys the cached object, before it is
released to the back end that manages the flow of real memory. It is defined
as:
void foo_dtor(void *obj, void *privdata);
If no deconstructor is needed, it must be set to
NULL
. The interface to underlying allocator is
provided by alloc, free and
allocator_args. It must adhere to the following
form:
void *foo_alloc(void *allocator_args, int ocflags); void foo_free(void *obj, void *allocator_args);
objcache_malloc_alloc
()
and
objcache_malloc_free
()
are wrappers for
kmalloc(9) allocation functions. Whereas,
objcache_nop_alloc
()
and
objcache_nop_free
()
are wrappers for allocation policies that pre-allocate at initialization
time instead of doing run-time allocation.
objcache_create_mbacked
()
creates a new object cache of size objsize, backed
with a malloc_type_t argument. The latter is used to
perform statistics in memory usage and for basic sanity checks. For the
underlying allocator,
kmalloc(9) functions are employed.
objcache_create_simple
()
creates a new object cache of size objsize, backed
with a malloc_type_t argument. The
cluster_limit is set to 0 and the default value for
magazines' capacity is used. ctor and
dtor are set to NULL
.
privdata is set to NULL
as
well. For the underlying allocator,
kmalloc(9) functions are employed.
objcache_get
()
returns an object from the oc object cache. The object
is in its initialized state. Newly allocated objects are subjected to the
object cache's constructor function, if not NULL
,
prior to being returned. ocflags is only used when the
depot does not have any non-empty magazines and a new object needs to be
allocated using the back end allocator. In this case we cannot depend on
flags such as M_ZERO
. If the back end allocator
fails, or if the depot's object limit has been reached and
M_WAITOK
is not specified,
NULL
is returned.
objcache_put
()
returns obj to the oc object
cache. The object must be in its initialized state prior to this call. If
there is no empty magazine, the object deconstructor is called and the
object is freed.
objcache_dtor
()
puts obj back into the oc object
cache, indicating that the object is not in any shape to be reused and
should be deconstructed and freed immediately.
objcache_reclaimlist
()
iterates over the oclist[] list with
nlist elements and tries to free up some memory. For
each object cache in the reclaim list, the current per-CPU cache is tried
first and then the full magazine depot. The function returns
TRUE
as soon as some free memory is found and
FALSE
otherwise.
objcache_destroy
()
destroys the oc object cache. The object must have no
existing references.
IMPLEMENTATION NOTES
Magazine
A magazine is the very basic functional unit of the object caching scheme. The number of objects it can hold is fixed and determined by its capacity. The term magazine is used as an analogy with automatic weapon (a firearm that can fire several rounds without reloading).
Per-CPU object cache
The reasoning behind per-CPU caches is to allow CPUs to perform their transactions (i.e., allocations, frees) in a parallel, yet lockless manner.
Each CPU is given two magazines, an active and a backup. This is done in order to avoid a situation where a tight loop of two allocations followed by two frees can cause thrashing at the magazine boundary.
If we need to add an object to the cache and the active magazine is full, room is searched in the backup magazine. If the backup has room, we swap active with backup and add the object. If both magazines are full, we get an empty magazine from the depot and move a fully loaded magazine to the depot.
Magazine depot
Each object cache manages a global supply of magazines, the depot, that is available across all CPUs. The depot maintains two lists of magazines. One for completely full and one for completely free magazines. The per-CPU object caches only exchange completely full or completely empty magazines with the depot layer.
EXAMPLES
/* This is the data structure we are going to cache. */ struct foo { int x; char str[32]; }; MALLOC_DEFINE(M_FOOBUF, "foobuf", "Buffer to my little precious data"); struct objcache_malloc_args foo_malloc_args = { sizeof(struct foo), M_FOOBUF }; struct objcache *foo_cache; /* * Object cache constructor. */ static boolean_t foo_cache_ctor(void *obj, void *privdata, int ocflags) { struct foo *myfoo = obj; /* * Do any initialization of the object here. Let's just zero out * the data structure for the fun of it. */ bzero(myfoo, sizeof(*myfoo)); return (TRUE); } /* * Object cache deconstructor. */ static void foo_cache_dtor(void *obj, void *privdata) { struct foo *myfoo = obj; /* * Do any clean up here. E.g., if you have kmalloc'ed() inside * the constructor, this is the right place and time to kfree(). */ } /* * Initialize our subsystem. */ static void foo_init(void) { /* Create the object cache. */ foo_cache = objcache_create("foo", 0, /* infinite depot's capacity */ 0, /* default magazine's capacity */ foo_ctor, foo_dtor, NULL, objcache_malloc_alloc, objcache_malloc_free, &foo_malloc_args); } /* * Random function. */ static void foo_random(...) { struct foo *myfoo; /* Get a `foo' object from the object cache. */ myfoo = objcache_get(foo_cache, M_WAITOK); /* Do stuff with it. */ /* ... */ /* We don't need it anymore. Put it back in object cache. */ objcache_put(foo_cache, myfoo); } /* * Shutdown our subsystem. */ static void foo_uninit(void) { /* Destroy the object cache. */ objcache_destroy(foo_cache); }
SEE ALSO
Jeff Bonwick, The Slab Allocator: An Object-Caching Kernel Memory Allocator, USENIX Summer 1994 Technical Conference.
Jeff Bonwick and Jonathan Adams, Magazines and Vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources, USENIX 2001 Technical Conference.
HISTORY
The object caching system appeared in DragonFly 1.3.
AUTHORS
The object caching system was written by Jeffrey M. Hsu <hsu@freebsd.org>. This manual page was written by Stathis Kamperis <ekamperi@gmail.com>.