kmem_impl.h revision b942e89b21c9ea698fd94b07082bee381672203d
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#ifndef _SYS_KMEM_IMPL_H
#define _SYS_KMEM_IMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* kernel memory allocator: implementation-private data structures
*
* Lock order:
* 1. cache_lock
* 2. cc_lock in order by CPU ID
* 3. cache_depot_lock
*
* Do not call kmem_cache_alloc() or taskq_dispatch() while holding any of the
* above locks.
*/
#define KMEM_STACK_DEPTH 15
#define KMEM_FREE_PATTERN 0xdeadbeefdeadbeefULL
#define KMEM_UNINITIALIZED_PATTERN 0xbaddcafebaddcafeULL
#define KMEM_REDZONE_PATTERN 0xfeedfacefeedfaceULL
#define KMEM_REDZONE_BYTE 0xbb
/*
* Redzone size encodings for kmem_alloc() / kmem_free(). We encode the
* allocation size, rather than storing it directly, so that kmem_free()
* can distinguish frees of the wrong size from redzone violations.
*
* A size of zero is never valid.
*/
#define KMEM_SIZE_DECODE(x) ((x) / 251)
#define KMEM_SLAB_IS_PARTIAL(sp) \
#define KMEM_SLAB_IS_ALL_USED(sp) \
/*
* The bufctl (buffer control) structure keeps some minimal information
* about each buffer: its address, its slab, and its current linkage,
* which is either on the slab's freelist (if the buffer is free), or
* on the cache's buf-to-bufctl hash table (if the buffer is allocated).
* In the case of non-hashed, or "raw", caches (the common case), only
* the freelist linkage is necessary: the buffer address is at a fixed
* offset from the bufctl address, and the slab is at the end of the page.
*
* NOTE: bc_next must be the first field; raw buffers have linkage only.
*/
typedef struct kmem_bufctl {
void *bc_addr; /* address of buffer */
/*
* The KMF_AUDIT version of the bufctl structure. The beginning of this
* structure must be identical to the normal bufctl structure so that
* pointers are interchangeable.
*/
typedef struct kmem_bufctl_audit {
void *bc_addr; /* address of buffer */
void *bc_contents; /* contents at last free */
int bc_depth; /* stack depth */
/*
* A kmem_buftag structure is appended to each buffer whenever any of the
* KMF_BUFTAG flags (KMF_DEADBEEF, KMF_REDZONE, KMF_VERIFY) are set.
*/
typedef struct kmem_buftag {
/*
* A variant of the kmem_buftag structure used for KMF_LITE caches.
* Previous callers are stored in reverse chronological order. (i.e. most
* recent first)
*/
typedef struct kmem_buftag_lite {
#define KMEM_BUFTAG_LITE_SIZE(f) \
/*
* Test for using alternate memory at dump time.
*/
/*
* The "CPU" macro loads a cpu_t that refers to the cpu that the current
* thread is running on at the time the macro is executed. A context switch
* may occur immediately after loading this data structure, leaving this
* thread pointing at the cpu_t for the previous cpu. This is not a problem;
* we'd just end up checking the previous cpu's per-cpu cache, and then check
* the other layers of the kmem cache if need be.
*
* It's not even a problem if the old cpu gets DR'ed out during the context
* switch. The cpu-remove DR operation bzero()s the cpu_t, but doesn't free
* it. So the cpu_t's cpu_cache_offset would read as 0, causing us to use
* cpu 0's per-cpu cache.
*
* So, there is no need to disable kernel preemption while using the CPU macro
* below since if we have been context switched, there will not be any
* correctness problem, just a momentary use of a different per-cpu cache.
*/
#define KMEM_CPU_CACHE(cp) \
#define KMEM_BUFTAG_ALLOC 0xa110c8edUL
#define KMEM_BUFTAG_FREE 0xf4eef4eeUL
/* slab_later_count thresholds */
#define KMEM_DISBELIEF 3
/* slab_flags */
#define KMEM_SLAB_NOMOVE 0x1
#define KMEM_SLAB_MOVE_PENDING 0x2
typedef struct kmem_slab {
void *slab_base; /* base of allocated memory */
long slab_refcnt; /* outstanding allocations */
long slab_chunks; /* chunks (bufs) in this slab */
} kmem_slab_t;
#define KMEM_HASH_INITIAL 64
((cp)->cache_hash_table + \
typedef struct kmem_magazine {
void *mag_next;
/*
* The magazine types for fast per-cpu allocation
*/
typedef struct kmem_magtype {
short mt_magsize; /* magazine size (number of rounds) */
int mt_align; /* magazine alignment */
5 * sizeof (short))
#define KMEM_CACHE_SIZE(ncpus) \
/* Offset from kmem_cache->cache_cpu for per cpu caches */
#define KMEM_CPU_CACHE_OFFSET(cpuid) \
typedef struct kmem_cpu_cache {
int cc_flags; /* CPU-local copy of cache_flags */
short cc_rounds; /* number of objects in loaded mag */
short cc_prounds; /* number of objects in previous mag */
short cc_magsize; /* number of rounds in a full mag */
short cc_dump_rounds; /* dump time copy of cc_rounds */
short cc_dump_prounds; /* dump time copy of cc_prounds */
/*
* The magazine lists used in the depot.
*/
typedef struct kmem_maglist {
long ml_total; /* number of magazines */
long ml_min; /* min since last update */
long ml_reaplimit; /* max reapable magazines */
typedef struct kmem_defrag {
/*
* Statistics
*/
/*
* Consolidator fields
*/
/*
* Fields used to ASSERT that the client does not kmem_cache_free()
* objects passed to the move callback.
*/
void *kmd_from_buf; /* object to move */
void *kmd_to_buf; /* move destination */
#define KMEM_CACHE_NAMELEN 31
struct kmem_cache {
/*
* Statistics
*/
/*
* Cache properties
*/
int (*cache_constructor)(void *, void *, int);
void (*cache_destructor)(void *, void *);
void (*cache_reclaim)(void *);
void *cache_private; /* opaque arg to callbacks */
int cache_cflags; /* cache creation flags */
int cache_flags; /* various cache state info */
/*
* Slab layer
*/
/*
* Depot layer
*/
void *cache_dumpfreelist; /* heap during crash dump */
void *cache_dumplog; /* log entry during dump */
/*
* Per-CPU layer
*/
};
typedef struct kmem_cpu_log_header {
char *clh_current;
int clh_chunk;
int clh_hits;
sizeof (size_t) - 2 * sizeof (int)];
typedef struct kmem_log_header {
char *lh_base;
int *lh_free;
int lh_nchunks;
int lh_head;
int lh_tail;
int lh_hits;
/* kmem_move kmm_flags */
#define KMM_DESPERATE 0x1
#define KMM_NOTIFY 0x2
#define KMM_DEBUG 0x4
typedef struct kmem_move {
void *kmm_from_buf;
void *kmm_to_buf;
int kmm_flags;
} kmem_move_t;
/*
* In order to consolidate partial slabs, it must be possible for the cache to
* have partial slabs.
*/
#define KMEM_IS_MOVABLE(cp) \
#ifdef __cplusplus
}
#endif
#endif /* _SYS_KMEM_IMPL_H */