summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/vmem_impl.h
blob: cbe815a05d0f387899e58f2ce216adbd62ffc931 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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
 * or http://www.opensolaris.org/os/licensing.
 * 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
 */
/*
 * Copyright 1999-2001, 2003 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_VMEM_IMPL_H
#define	_SYS_VMEM_IMPL_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/vmem.h>
#include <sys/kstat.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/thread.h>
#include <sys/systm.h>

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct vmem_seg vmem_seg_t;

#define	VMEM_STACK_DEPTH	20

struct vmem_seg {
	/*
	 * The first four fields must match vmem_freelist_t exactly.
	 */
	uintptr_t	vs_start;	/* start of segment (inclusive) */
	uintptr_t	vs_end;		/* end of segment (exclusive) */
	vmem_seg_t	*vs_knext;	/* next of kin (alloc, free, span) */
	vmem_seg_t	*vs_kprev;	/* prev of kin */

	vmem_seg_t	*vs_anext;	/* next in arena */
	vmem_seg_t	*vs_aprev;	/* prev in arena */
	uint8_t		vs_type;	/* alloc, free, span */
	uint8_t		vs_import;	/* non-zero if segment was imported */
	uint8_t		vs_depth;	/* stack depth if KMF_AUDIT active */
	/*
	 * The following fields are present only when KMF_AUDIT is set.
	 */
	kthread_t	*vs_thread;
	hrtime_t	vs_timestamp;
	pc_t		vs_stack[VMEM_STACK_DEPTH];
};

typedef struct vmem_freelist {
	uintptr_t	vs_start;	/* always zero */
	uintptr_t	vs_end;		/* segment size */
	vmem_seg_t	*vs_knext;	/* next of kin */
	vmem_seg_t	*vs_kprev;	/* prev of kin */
} vmem_freelist_t;

#define	VS_SIZE(vsp)	((vsp)->vs_end - (vsp)->vs_start)

/*
 * Segment hashing
 */
#define	VMEM_HASH_INDEX(a, s, q, m)					\
	((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m))

#define	VMEM_HASH(vmp, addr)						\
	(&(vmp)->vm_hash_table[VMEM_HASH_INDEX(addr,			\
	(vmp)->vm_hash_shift, (vmp)->vm_qshift, (vmp)->vm_hash_mask)])

#define	VMEM_QCACHE_SLABSIZE(max) \
	MAX(1 << highbit(3 * (max)), 64)

#define	VMEM_NAMELEN		30
#define	VMEM_HASH_INITIAL	16
#define	VMEM_NQCACHE_MAX	16
#define	VMEM_FREELISTS		(sizeof (void *) * 8)

typedef struct vmem_kstat {
	kstat_named_t	vk_mem_inuse;	/* memory in use */
	kstat_named_t	vk_mem_import;	/* memory imported */
	kstat_named_t	vk_mem_total;	/* total memory in arena */
	kstat_named_t	vk_source_id;	/* vmem id of vmem source */
	kstat_named_t	vk_alloc;	/* number of allocations */
	kstat_named_t	vk_free;	/* number of frees */
	kstat_named_t	vk_wait;	/* number of allocations that waited */
	kstat_named_t	vk_fail;	/* number of allocations that failed */
	kstat_named_t	vk_lookup;	/* hash lookup count */
	kstat_named_t	vk_search;	/* freelist search count */
	kstat_named_t	vk_populate_wait;	/* populates that waited */
	kstat_named_t	vk_populate_fail;	/* populates that failed */
	kstat_named_t	vk_contains;		/* vmem_contains() calls */
	kstat_named_t	vk_contains_search;	/* vmem_contains() search cnt */
} vmem_kstat_t;

struct vmem {
	char		vm_name[VMEM_NAMELEN];	/* arena name */
	kcondvar_t	vm_cv;		/* cv for blocking allocations */
	kmutex_t	vm_lock;	/* arena lock */
	uint32_t	vm_id;		/* vmem id */
	uint32_t	vm_mtbf;	/* induced alloc failure rate */
	int		vm_cflags;	/* arena creation flags */
	int		vm_qshift;	/* log2(vm_quantum) */
	size_t		vm_quantum;	/* vmem quantum */
	size_t		vm_qcache_max;	/* maximum size to front by kmem */
	size_t		vm_min_import;	/* smallest amount to import */
	void		*(*vm_source_alloc)(vmem_t *, size_t, int);
	void		(*vm_source_free)(vmem_t *, void *, size_t);
	vmem_t		*vm_source;	/* vmem source for imported memory */
	vmem_t		*vm_next;	/* next in vmem_list */
	kstat_t		*vm_ksp;	/* kstat */
	ssize_t		vm_nsegfree;	/* number of free vmem_seg_t's */
	vmem_seg_t	*vm_segfree;	/* free vmem_seg_t list */
	vmem_seg_t	**vm_hash_table; /* allocated-segment hash table */
	size_t		vm_hash_mask;	/* hash_size - 1 */
	size_t		vm_hash_shift;	/* log2(vm_hash_mask + 1) */
	ulong_t		vm_freemap;	/* bitmap of non-empty freelists */
	vmem_seg_t	vm_seg0;	/* anchor segment */
	vmem_seg_t	vm_rotor;	/* rotor for VM_NEXTFIT allocations */
	vmem_seg_t	*vm_hash0[VMEM_HASH_INITIAL];	/* initial hash table */
	void		*vm_qcache[VMEM_NQCACHE_MAX];	/* quantum caches */
	vmem_freelist_t	vm_freelist[VMEM_FREELISTS + 1]; /* power-of-2 flists */
	vmem_kstat_t	vm_kstat;	/* kstat data */
};

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_VMEM_IMPL_H */