xref: /titanic_53/usr/src/uts/common/vm/anon.h (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*7c478bd9Sstevel@tonic-gate /*	 All Rights Reserved   */
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
32*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
33*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
36*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
37*7c478bd9Sstevel@tonic-gate  * contributors.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #ifndef	_VM_ANON_H
41*7c478bd9Sstevel@tonic-gate #define	_VM_ANON_H
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
46*7c478bd9Sstevel@tonic-gate #include <vm/seg.h>
47*7c478bd9Sstevel@tonic-gate #include <vm/vpage.h>
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
50*7c478bd9Sstevel@tonic-gate extern "C" {
51*7c478bd9Sstevel@tonic-gate #endif
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate /*
54*7c478bd9Sstevel@tonic-gate  * VM - Anonymous pages.
55*7c478bd9Sstevel@tonic-gate  */
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate typedef	unsigned long anoff_t;		/* anon offsets */
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate  *	Each anonymous page, either in memory or in swap, has an anon structure.
61*7c478bd9Sstevel@tonic-gate  * The structure (slot) provides a level of indirection between anonymous pages
62*7c478bd9Sstevel@tonic-gate  * and their backing store.
63*7c478bd9Sstevel@tonic-gate  *
64*7c478bd9Sstevel@tonic-gate  *	(an_vp, an_off) names the vnode of the anonymous page for this slot.
65*7c478bd9Sstevel@tonic-gate  *
66*7c478bd9Sstevel@tonic-gate  * 	(an_pvp, an_poff) names the location of the physical backing store
67*7c478bd9Sstevel@tonic-gate  * 	for the page this slot represents. If the name is null there is no
68*7c478bd9Sstevel@tonic-gate  * 	associated physical store. The physical backing store location can
69*7c478bd9Sstevel@tonic-gate  *	change while the slot is in use.
70*7c478bd9Sstevel@tonic-gate  *
71*7c478bd9Sstevel@tonic-gate  *	an_hash is a hash list of anon slots. The list is hashed by
72*7c478bd9Sstevel@tonic-gate  * 	(an_vp, an_off) of the associated anonymous page and provides a
73*7c478bd9Sstevel@tonic-gate  *	method of going from the name of an anonymous page to its
74*7c478bd9Sstevel@tonic-gate  * 	associated anon slot.
75*7c478bd9Sstevel@tonic-gate  *
76*7c478bd9Sstevel@tonic-gate  *	an_refcnt holds a reference count which is the number of separate
77*7c478bd9Sstevel@tonic-gate  * 	copies that will need to be created in case of copy-on-write.
78*7c478bd9Sstevel@tonic-gate  *	A refcnt > 0 protects the existence of the slot. The refcnt is
79*7c478bd9Sstevel@tonic-gate  * 	initialized to 1 when the anon slot is created in anon_alloc().
80*7c478bd9Sstevel@tonic-gate  *	If a client obtains an anon slot and allows multiple threads to
81*7c478bd9Sstevel@tonic-gate  * 	share it, then it is the client's responsibility to insure that
82*7c478bd9Sstevel@tonic-gate  *	it does not allow one thread to try to reference the slot at the
83*7c478bd9Sstevel@tonic-gate  *	same time as another is trying to decrement the last count and
84*7c478bd9Sstevel@tonic-gate  *	destroy the anon slot. E.g., the seg_vn segment type protects
85*7c478bd9Sstevel@tonic-gate  *	against this with higher level locks.
86*7c478bd9Sstevel@tonic-gate  */
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate struct anon {
89*7c478bd9Sstevel@tonic-gate 	struct vnode *an_vp;	/* vnode of anon page */
90*7c478bd9Sstevel@tonic-gate 	struct vnode *an_pvp;	/* vnode of physical backing store */
91*7c478bd9Sstevel@tonic-gate 	anoff_t an_off;		/* offset of anon page */
92*7c478bd9Sstevel@tonic-gate 	anoff_t an_poff;	/* offset in vnode */
93*7c478bd9Sstevel@tonic-gate 	struct anon *an_hash;	/* hash table of anon slots */
94*7c478bd9Sstevel@tonic-gate 	int an_refcnt;		/* # of people sharing slot */
95*7c478bd9Sstevel@tonic-gate };
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate #ifdef _KERNEL
98*7c478bd9Sstevel@tonic-gate /*
99*7c478bd9Sstevel@tonic-gate  * The swapinfo_lock protects:
100*7c478bd9Sstevel@tonic-gate  *		swapinfo list
101*7c478bd9Sstevel@tonic-gate  *		individual swapinfo structures
102*7c478bd9Sstevel@tonic-gate  *
103*7c478bd9Sstevel@tonic-gate  * The anoninfo_lock protects:
104*7c478bd9Sstevel@tonic-gate  *		anoninfo counters
105*7c478bd9Sstevel@tonic-gate  *
106*7c478bd9Sstevel@tonic-gate  * The anonhash_lock protects:
107*7c478bd9Sstevel@tonic-gate  *		anon hash lists
108*7c478bd9Sstevel@tonic-gate  *		anon slot fields
109*7c478bd9Sstevel@tonic-gate  *
110*7c478bd9Sstevel@tonic-gate  * Fields in the anon slot which are read-only for the life of the slot
111*7c478bd9Sstevel@tonic-gate  * (an_vp, an_off) do not require the anonhash_lock be held to access them.
112*7c478bd9Sstevel@tonic-gate  * If you access a field without the anonhash_lock held you must be holding
113*7c478bd9Sstevel@tonic-gate  * the slot with an_refcnt to make sure it isn't destroyed.
114*7c478bd9Sstevel@tonic-gate  * To write (an_pvp, an_poff) in a given slot you must also hold the
115*7c478bd9Sstevel@tonic-gate  * p_iolock of the anonymous page for slot.
116*7c478bd9Sstevel@tonic-gate  */
117*7c478bd9Sstevel@tonic-gate extern kmutex_t anoninfo_lock;
118*7c478bd9Sstevel@tonic-gate extern kmutex_t swapinfo_lock;
119*7c478bd9Sstevel@tonic-gate extern kmutex_t anonhash_lock[];
120*7c478bd9Sstevel@tonic-gate extern pad_mutex_t anon_array_lock[];
121*7c478bd9Sstevel@tonic-gate extern kcondvar_t anon_array_cv[];
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate /*
124*7c478bd9Sstevel@tonic-gate  * Global hash table to provide a function from (vp, off) -> ap
125*7c478bd9Sstevel@tonic-gate  */
126*7c478bd9Sstevel@tonic-gate extern size_t anon_hash_size;
127*7c478bd9Sstevel@tonic-gate extern struct anon **anon_hash;
128*7c478bd9Sstevel@tonic-gate #define	ANON_HASH_SIZE	anon_hash_size
129*7c478bd9Sstevel@tonic-gate #define	ANON_HASHAVELEN	4
130*7c478bd9Sstevel@tonic-gate #define	ANON_HASH(VP, OFF)	\
131*7c478bd9Sstevel@tonic-gate ((((uintptr_t)(VP) >> 7)  ^ ((OFF) >> PAGESHIFT)) & (ANON_HASH_SIZE - 1))
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate #define	AH_LOCK_SIZE	64
134*7c478bd9Sstevel@tonic-gate #define	AH_LOCK(vp, off) (ANON_HASH((vp), (off)) & (AH_LOCK_SIZE -1))
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate /*
139*7c478bd9Sstevel@tonic-gate  * Declaration for the Global counters to accurately
140*7c478bd9Sstevel@tonic-gate  * track the kernel foot print in memory.
141*7c478bd9Sstevel@tonic-gate  */
142*7c478bd9Sstevel@tonic-gate extern  pgcnt_t segvn_pages_locked;
143*7c478bd9Sstevel@tonic-gate extern  pgcnt_t pages_locked;
144*7c478bd9Sstevel@tonic-gate extern  pgcnt_t pages_claimed;
145*7c478bd9Sstevel@tonic-gate extern  pgcnt_t pages_useclaim;
146*7c478bd9Sstevel@tonic-gate extern  pgcnt_t obp_pages;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate /*
149*7c478bd9Sstevel@tonic-gate  * Anonymous backing store accounting structure for swapctl.
150*7c478bd9Sstevel@tonic-gate  *
151*7c478bd9Sstevel@tonic-gate  * ani_max = maximum amount of swap space
152*7c478bd9Sstevel@tonic-gate  *	(including potentially available physical memory)
153*7c478bd9Sstevel@tonic-gate  * ani_free = amount of unallocated anonymous memory
154*7c478bd9Sstevel@tonic-gate  *	(some of which might be reserved and including
155*7c478bd9Sstevel@tonic-gate  *	potentially available physical memory)
156*7c478bd9Sstevel@tonic-gate  * ani_resv = amount of claimed (reserved) anonymous memory
157*7c478bd9Sstevel@tonic-gate  *
158*7c478bd9Sstevel@tonic-gate  * The swap data can be aquired more efficiently through the
159*7c478bd9Sstevel@tonic-gate  * kstats interface.
160*7c478bd9Sstevel@tonic-gate  * Total slots currently available for reservation =
161*7c478bd9Sstevel@tonic-gate  *	MAX(ani_max - ani_resv, 0) + (availrmem - swapfs_minfree)
162*7c478bd9Sstevel@tonic-gate  */
163*7c478bd9Sstevel@tonic-gate struct anoninfo {
164*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_max;
165*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_free;
166*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_resv;
167*7c478bd9Sstevel@tonic-gate };
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32
170*7c478bd9Sstevel@tonic-gate struct anoninfo32 {
171*7c478bd9Sstevel@tonic-gate 	size32_t ani_max;
172*7c478bd9Sstevel@tonic-gate 	size32_t ani_free;
173*7c478bd9Sstevel@tonic-gate 	size32_t ani_resv;
174*7c478bd9Sstevel@tonic-gate };
175*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32 */
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate /*
178*7c478bd9Sstevel@tonic-gate  * Define the NCPU pool of the ani_free counters. Update the counter
179*7c478bd9Sstevel@tonic-gate  * of the cpu on which the thread is running and in every clock intr
180*7c478bd9Sstevel@tonic-gate  * sync anoninfo.ani_free with the current total off all the NCPU entries.
181*7c478bd9Sstevel@tonic-gate  */
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate typedef	struct	ani_free {
184*7c478bd9Sstevel@tonic-gate 	kmutex_t	ani_lock;
185*7c478bd9Sstevel@tonic-gate 	pgcnt_t		ani_count;
186*7c478bd9Sstevel@tonic-gate 	uchar_t		pad[64 - sizeof (kmutex_t) - sizeof (pgcnt_t)];
187*7c478bd9Sstevel@tonic-gate 			/* XXX 64 = cacheline size */
188*7c478bd9Sstevel@tonic-gate } ani_free_t;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate #define	ANI_MAX_POOL	128
191*7c478bd9Sstevel@tonic-gate extern	ani_free_t	ani_free_pool[];
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate #define	ANI_ADD(inc)	{ \
194*7c478bd9Sstevel@tonic-gate 	ani_free_t	*anifp; \
195*7c478bd9Sstevel@tonic-gate 	int		index; \
196*7c478bd9Sstevel@tonic-gate 	index = (CPU->cpu_id & (ANI_MAX_POOL - 1)); \
197*7c478bd9Sstevel@tonic-gate 	anifp = &ani_free_pool[index]; \
198*7c478bd9Sstevel@tonic-gate 	mutex_enter(&anifp->ani_lock); \
199*7c478bd9Sstevel@tonic-gate 	anifp->ani_count += inc; \
200*7c478bd9Sstevel@tonic-gate 	mutex_exit(&anifp->ani_lock); \
201*7c478bd9Sstevel@tonic-gate }
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate /*
204*7c478bd9Sstevel@tonic-gate  * Anon array pointers are allocated in chunks. Each chunk
205*7c478bd9Sstevel@tonic-gate  * has PAGESIZE/sizeof(u_long *) of anon pointers.
206*7c478bd9Sstevel@tonic-gate  * There are two levels of arrays for anon array pointers larger
207*7c478bd9Sstevel@tonic-gate  * than a chunk. The first level points to anon array chunks.
208*7c478bd9Sstevel@tonic-gate  * The second level consists of chunks of anon pointers.
209*7c478bd9Sstevel@tonic-gate  *
210*7c478bd9Sstevel@tonic-gate  * If anon array is smaller than a chunk then the whole anon array
211*7c478bd9Sstevel@tonic-gate  * is created (memory is allocated for whole anon array).
212*7c478bd9Sstevel@tonic-gate  * If anon array is larger than a chunk only first level array is
213*7c478bd9Sstevel@tonic-gate  * allocated. Then other arrays (chunks) are allocated only when
214*7c478bd9Sstevel@tonic-gate  * they are initialized with anon pointers.
215*7c478bd9Sstevel@tonic-gate  */
216*7c478bd9Sstevel@tonic-gate struct anon_hdr {
217*7c478bd9Sstevel@tonic-gate 	kmutex_t serial_lock;	/* serialize array chunk allocation */
218*7c478bd9Sstevel@tonic-gate 	pgcnt_t	size;		/* number of pointers to (anon) pages */
219*7c478bd9Sstevel@tonic-gate 	void	**array_chunk;	/* pointers to anon pointers or chunks of */
220*7c478bd9Sstevel@tonic-gate 				/* anon pointers */
221*7c478bd9Sstevel@tonic-gate 	int	flags;		/* ANON_ALLOC_FORCE force preallocation of */
222*7c478bd9Sstevel@tonic-gate 				/* whole anon array	*/
223*7c478bd9Sstevel@tonic-gate };
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate #ifdef	_LP64
226*7c478bd9Sstevel@tonic-gate #define	ANON_PTRSHIFT	3
227*7c478bd9Sstevel@tonic-gate #define	ANON_PTRMASK	~7
228*7c478bd9Sstevel@tonic-gate #else
229*7c478bd9Sstevel@tonic-gate #define	ANON_PTRSHIFT	2
230*7c478bd9Sstevel@tonic-gate #define	ANON_PTRMASK	~3
231*7c478bd9Sstevel@tonic-gate #endif
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate #define	ANON_CHUNK_SIZE		(PAGESIZE >> ANON_PTRSHIFT)
234*7c478bd9Sstevel@tonic-gate #define	ANON_CHUNK_SHIFT	(PAGESHIFT - ANON_PTRSHIFT)
235*7c478bd9Sstevel@tonic-gate #define	ANON_CHUNK_OFF		(ANON_CHUNK_SIZE - 1)
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate /*
238*7c478bd9Sstevel@tonic-gate  * Anon flags.
239*7c478bd9Sstevel@tonic-gate  */
240*7c478bd9Sstevel@tonic-gate #define	ANON_SLEEP		0x0	/* ok to block */
241*7c478bd9Sstevel@tonic-gate #define	ANON_NOSLEEP		0x1	/* non-blocking call */
242*7c478bd9Sstevel@tonic-gate #define	ANON_ALLOC_FORCE	0x2	/* force single level anon array */
243*7c478bd9Sstevel@tonic-gate #define	ANON_GROWDOWN		0x4	/* anon array should grow downward */
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate /*
246*7c478bd9Sstevel@tonic-gate  * The anon_map structure is used by various clients of the anon layer to
247*7c478bd9Sstevel@tonic-gate  * manage anonymous memory.   When anonymous memory is shared,
248*7c478bd9Sstevel@tonic-gate  * then the different clients sharing it will point to the
249*7c478bd9Sstevel@tonic-gate  * same anon_map structure.  Also, if a segment is unmapped
250*7c478bd9Sstevel@tonic-gate  * in the middle where an anon_map structure exists, the
251*7c478bd9Sstevel@tonic-gate  * newly created segment will also share the anon_map structure,
252*7c478bd9Sstevel@tonic-gate  * although the two segments will use different ranges of the
253*7c478bd9Sstevel@tonic-gate  * anon array.  When mappings are private (or shared with
254*7c478bd9Sstevel@tonic-gate  * a reference count of 1), an unmap operation will free up
255*7c478bd9Sstevel@tonic-gate  * a range of anon slots in the array given by the anon_map
256*7c478bd9Sstevel@tonic-gate  * structure.  Because of fragmentation due to this unmapping,
257*7c478bd9Sstevel@tonic-gate  * we have to store the size of the anon array in the anon_map
258*7c478bd9Sstevel@tonic-gate  * structure so that we can free everything when the referernce
259*7c478bd9Sstevel@tonic-gate  * count goes to zero.
260*7c478bd9Sstevel@tonic-gate  *
261*7c478bd9Sstevel@tonic-gate  * A new rangelock scheme is introduced to make the anon layer scale.
262*7c478bd9Sstevel@tonic-gate  * A reader/writer lock per anon_amp and an array of system-wide hash
263*7c478bd9Sstevel@tonic-gate  * locks, anon_array_lock[] are introduced to replace serial_lock and
264*7c478bd9Sstevel@tonic-gate  * anonmap lock.  The writer lock is held when we want to singlethreaD
265*7c478bd9Sstevel@tonic-gate  * the reference to the anon array pointers or when references to
266*7c478bd9Sstevel@tonic-gate  * anon_map's members, whereas reader lock and anon_array_lock are
267*7c478bd9Sstevel@tonic-gate  * held to allows multiple threads to reference different part of
268*7c478bd9Sstevel@tonic-gate  * anon array.  A global set of condition variables, anon_array_cv,
269*7c478bd9Sstevel@tonic-gate  * are used with anon_array_lock[] to make the hold time of the locks
270*7c478bd9Sstevel@tonic-gate  * short.
271*7c478bd9Sstevel@tonic-gate  *
272*7c478bd9Sstevel@tonic-gate  * szc is used to calculate the index of hash locks and cv's.  We
273*7c478bd9Sstevel@tonic-gate  * could've just used seg->s_szc if not for the possible sharing of
274*7c478bd9Sstevel@tonic-gate  * anon_amp between SYSV shared memory and ISM, so now we introduce
275*7c478bd9Sstevel@tonic-gate  * szc in the anon_map structure.  For MAP_SHARED, the amp->szc is either
276*7c478bd9Sstevel@tonic-gate  * 0 (base page size) or page_num_pagesizes() - 1, while MAP_PRIVATE
277*7c478bd9Sstevel@tonic-gate  * the amp->szc could be anything in [0, page_num_pagesizes() - 1].
278*7c478bd9Sstevel@tonic-gate  */
279*7c478bd9Sstevel@tonic-gate struct anon_map {
280*7c478bd9Sstevel@tonic-gate 	krwlock_t a_rwlock;	/* protect anon_map and anon array */
281*7c478bd9Sstevel@tonic-gate 	size_t	size;		/* size in bytes mapped by the anon array */
282*7c478bd9Sstevel@tonic-gate 	struct	anon_hdr *ahp; 	/* anon array header pointer, containing */
283*7c478bd9Sstevel@tonic-gate 				/* anon pointer array(s) */
284*7c478bd9Sstevel@tonic-gate 	size_t	swresv;		/* swap space reserved for this anon_map */
285*7c478bd9Sstevel@tonic-gate 	uint_t	refcnt;		/* reference count on this structure */
286*7c478bd9Sstevel@tonic-gate 	ushort_t a_szc;		/* max szc among shared processes */
287*7c478bd9Sstevel@tonic-gate 	void	*locality;	/* lgroup locality info */
288*7c478bd9Sstevel@tonic-gate };
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate #ifdef _KERNEL
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate #define	ANON_BUSY		0x1
293*7c478bd9Sstevel@tonic-gate #define	ANON_ISBUSY(slot)	(*(slot) & ANON_BUSY)
294*7c478bd9Sstevel@tonic-gate #define	ANON_SETBUSY(slot)	(*(slot) |= ANON_BUSY)
295*7c478bd9Sstevel@tonic-gate #define	ANON_CLRBUSY(slot)	(*(slot) &= ~ANON_BUSY)
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate #define	ANON_MAP_SHIFT		6	/* log2(sizeof (struct anon_map)) */
298*7c478bd9Sstevel@tonic-gate #define	ANON_ARRAY_SHIFT	7	/* log2(ANON_LOCKSIZE) */
299*7c478bd9Sstevel@tonic-gate #define	ANON_LOCKSIZE		128
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate #define	ANON_LOCK_ENTER(lock, type)	rw_enter((lock), (type))
302*7c478bd9Sstevel@tonic-gate #define	ANON_LOCK_EXIT(lock)		rw_exit((lock))
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate #define	ANON_ARRAY_HASH(amp, idx)\
305*7c478bd9Sstevel@tonic-gate 	((((idx) + ((idx) >> ANON_ARRAY_SHIFT) +\
306*7c478bd9Sstevel@tonic-gate 	((idx) >> (ANON_ARRAY_SHIFT << 1)) +\
307*7c478bd9Sstevel@tonic-gate 	((idx) >> (ANON_ARRAY_SHIFT + (ANON_ARRAY_SHIFT << 1)))) ^\
308*7c478bd9Sstevel@tonic-gate 	((uintptr_t)(amp) >> ANON_MAP_SHIFT)) & (ANON_LOCKSIZE - 1))
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate typedef struct anon_sync_obj {
311*7c478bd9Sstevel@tonic-gate 	kmutex_t	*sync_mutex;
312*7c478bd9Sstevel@tonic-gate 	kcondvar_t	*sync_cv;
313*7c478bd9Sstevel@tonic-gate 	ulong_t		*sync_data;
314*7c478bd9Sstevel@tonic-gate } anon_sync_obj_t;
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate /*
317*7c478bd9Sstevel@tonic-gate  * Anonymous backing store accounting structure for kernel.
318*7c478bd9Sstevel@tonic-gate  * ani_max = total reservable slots on physical (disk-backed) swap
319*7c478bd9Sstevel@tonic-gate  * ani_phys_resv = total phys slots reserved for use by clients
320*7c478bd9Sstevel@tonic-gate  * ani_mem_resv = total mem slots reserved for use by clients
321*7c478bd9Sstevel@tonic-gate  * ani_free = # unallocated physical slots + # of reserved unallocated
322*7c478bd9Sstevel@tonic-gate  * memory slots
323*7c478bd9Sstevel@tonic-gate  */
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate /*
326*7c478bd9Sstevel@tonic-gate  * Initial total swap slots available for reservation
327*7c478bd9Sstevel@tonic-gate  */
328*7c478bd9Sstevel@tonic-gate #define	TOTAL_AVAILABLE_SWAP \
329*7c478bd9Sstevel@tonic-gate 	(k_anoninfo.ani_max + MAX((spgcnt_t)(availrmem - swapfs_minfree), 0))
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate /*
332*7c478bd9Sstevel@tonic-gate  * Swap slots currently available for reservation
333*7c478bd9Sstevel@tonic-gate  */
334*7c478bd9Sstevel@tonic-gate #define	CURRENT_TOTAL_AVAILABLE_SWAP \
335*7c478bd9Sstevel@tonic-gate 	((k_anoninfo.ani_max - k_anoninfo.ani_phys_resv) +	\
336*7c478bd9Sstevel@tonic-gate 			MAX((spgcnt_t)(availrmem - swapfs_minfree), 0))
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate struct k_anoninfo {
339*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_max;	/* total reservable slots on phys */
340*7c478bd9Sstevel@tonic-gate 					/* (disk) swap */
341*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_free;	/* # of unallocated phys and mem slots */
342*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_phys_resv;	/* # of reserved phys (disk) slots */
343*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_mem_resv;	/* # of reserved mem slots */
344*7c478bd9Sstevel@tonic-gate 	pgcnt_t	ani_locked_swap; /* # of swap slots locked in reserved */
345*7c478bd9Sstevel@tonic-gate 				/* mem swap */
346*7c478bd9Sstevel@tonic-gate };
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate extern	struct k_anoninfo k_anoninfo;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate extern void	anon_init(void);
351*7c478bd9Sstevel@tonic-gate extern struct	anon *anon_alloc(struct vnode *, anoff_t);
352*7c478bd9Sstevel@tonic-gate extern void	anon_dup(struct anon_hdr *, ulong_t,
353*7c478bd9Sstevel@tonic-gate 		    struct anon_hdr *, ulong_t, size_t);
354*7c478bd9Sstevel@tonic-gate extern void	anon_dup_fill_holes(struct anon_hdr *, ulong_t,
355*7c478bd9Sstevel@tonic-gate 		    struct anon_hdr *, ulong_t, size_t, uint_t, int);
356*7c478bd9Sstevel@tonic-gate extern int	anon_fill_cow_holes(struct seg *, caddr_t, struct anon_hdr *,
357*7c478bd9Sstevel@tonic-gate 		    ulong_t, struct vnode *, u_offset_t, size_t, uint_t,
358*7c478bd9Sstevel@tonic-gate 		    uint_t, struct vpage [], struct cred *);
359*7c478bd9Sstevel@tonic-gate extern void	anon_free(struct anon_hdr *, ulong_t, size_t);
360*7c478bd9Sstevel@tonic-gate extern void	anon_free_pages(struct anon_hdr *, ulong_t, size_t, uint_t);
361*7c478bd9Sstevel@tonic-gate extern void	anon_disclaim(struct anon_map *, ulong_t, size_t, int);
362*7c478bd9Sstevel@tonic-gate extern int	anon_getpage(struct anon **, uint_t *, struct page **,
363*7c478bd9Sstevel@tonic-gate 		    size_t, struct seg *, caddr_t, enum seg_rw, struct cred *);
364*7c478bd9Sstevel@tonic-gate extern int	swap_getconpage(struct vnode *, u_offset_t, size_t,
365*7c478bd9Sstevel@tonic-gate 		    uint_t *, page_t *[], size_t, page_t *,
366*7c478bd9Sstevel@tonic-gate 		    spgcnt_t *, struct seg *, caddr_t,
367*7c478bd9Sstevel@tonic-gate 		    enum seg_rw, struct cred *);
368*7c478bd9Sstevel@tonic-gate extern int	anon_map_getpages(struct anon_map *, ulong_t,
369*7c478bd9Sstevel@tonic-gate 		    uint_t, struct seg *, caddr_t, uint_t,
370*7c478bd9Sstevel@tonic-gate 		    uint_t *, page_t *[], uint_t *,
371*7c478bd9Sstevel@tonic-gate 		    struct vpage [], enum seg_rw, int, int, struct cred *);
372*7c478bd9Sstevel@tonic-gate extern int	anon_map_privatepages(struct anon_map *, ulong_t,
373*7c478bd9Sstevel@tonic-gate 		    uint_t, struct seg *, caddr_t, uint_t,
374*7c478bd9Sstevel@tonic-gate 		    page_t *[], struct vpage [], int, struct cred *);
375*7c478bd9Sstevel@tonic-gate extern struct	page *anon_private(struct anon **, struct seg *,
376*7c478bd9Sstevel@tonic-gate 		    caddr_t, uint_t, struct page *,
377*7c478bd9Sstevel@tonic-gate 		    int, struct cred *);
378*7c478bd9Sstevel@tonic-gate extern struct	page *anon_zero(struct seg *, caddr_t,
379*7c478bd9Sstevel@tonic-gate 		    struct anon **, struct cred *);
380*7c478bd9Sstevel@tonic-gate extern int	anon_map_createpages(struct anon_map *, ulong_t,
381*7c478bd9Sstevel@tonic-gate 		    size_t, struct page **,
382*7c478bd9Sstevel@tonic-gate 		    struct seg *, caddr_t,
383*7c478bd9Sstevel@tonic-gate 		    enum seg_rw, struct cred *);
384*7c478bd9Sstevel@tonic-gate extern int	anon_map_demotepages(struct anon_map *, ulong_t,
385*7c478bd9Sstevel@tonic-gate 		    struct seg *, caddr_t, uint_t,
386*7c478bd9Sstevel@tonic-gate 		    struct vpage [], struct cred *);
387*7c478bd9Sstevel@tonic-gate extern int	anon_resvmem(size_t, uint_t);
388*7c478bd9Sstevel@tonic-gate extern void	anon_unresv(size_t);
389*7c478bd9Sstevel@tonic-gate extern struct	anon_map *anonmap_alloc(size_t, size_t);
390*7c478bd9Sstevel@tonic-gate extern void	anonmap_free(struct anon_map *);
391*7c478bd9Sstevel@tonic-gate extern void	anon_decref(struct anon *);
392*7c478bd9Sstevel@tonic-gate extern int	non_anon(struct anon_hdr *, ulong_t, u_offset_t *, size_t *);
393*7c478bd9Sstevel@tonic-gate extern pgcnt_t	anon_pages(struct anon_hdr *, ulong_t, pgcnt_t);
394*7c478bd9Sstevel@tonic-gate extern int	anon_swap_adjust(pgcnt_t);
395*7c478bd9Sstevel@tonic-gate extern void	anon_swap_restore(pgcnt_t);
396*7c478bd9Sstevel@tonic-gate extern struct	anon_hdr *anon_create(pgcnt_t, int);
397*7c478bd9Sstevel@tonic-gate extern void	anon_release(struct anon_hdr *, pgcnt_t);
398*7c478bd9Sstevel@tonic-gate extern struct	anon *anon_get_ptr(struct anon_hdr *, ulong_t);
399*7c478bd9Sstevel@tonic-gate extern ulong_t	*anon_get_slot(struct anon_hdr *, ulong_t);
400*7c478bd9Sstevel@tonic-gate extern struct	anon *anon_get_next_ptr(struct anon_hdr *, ulong_t *);
401*7c478bd9Sstevel@tonic-gate extern int	anon_set_ptr(struct anon_hdr *, ulong_t, struct anon *, int);
402*7c478bd9Sstevel@tonic-gate extern int 	anon_copy_ptr(struct anon_hdr *, ulong_t,
403*7c478bd9Sstevel@tonic-gate 		    struct anon_hdr *, ulong_t, pgcnt_t, int);
404*7c478bd9Sstevel@tonic-gate extern pgcnt_t	anon_grow(struct anon_hdr *, ulong_t *, pgcnt_t, pgcnt_t, int);
405*7c478bd9Sstevel@tonic-gate extern void	anon_array_enter(struct anon_map *, ulong_t,
406*7c478bd9Sstevel@tonic-gate 			anon_sync_obj_t *);
407*7c478bd9Sstevel@tonic-gate extern void	anon_array_exit(anon_sync_obj_t *);
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate /*
410*7c478bd9Sstevel@tonic-gate  * anon_resv checks to see if there is enough swap space to fulfill a
411*7c478bd9Sstevel@tonic-gate  * request and if so, reserves the appropriate anonymous memory resources.
412*7c478bd9Sstevel@tonic-gate  * anon_checkspace just checks to see if there is space to fulfill the request,
413*7c478bd9Sstevel@tonic-gate  * without taking any resources.  Both return 1 if successful and 0 if not.
414*7c478bd9Sstevel@tonic-gate  */
415*7c478bd9Sstevel@tonic-gate #define	anon_resv(size)		anon_resvmem((size), 1)
416*7c478bd9Sstevel@tonic-gate #define	anon_checkspace(size)	anon_resvmem((size), 0)
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate /*
419*7c478bd9Sstevel@tonic-gate  * Flags to anon_private
420*7c478bd9Sstevel@tonic-gate  */
421*7c478bd9Sstevel@tonic-gate #define	STEAL_PAGE	0x1	/* page can be stolen */
422*7c478bd9Sstevel@tonic-gate #define	LOCK_PAGE	0x2	/* page must be ``logically'' locked */
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate /*
425*7c478bd9Sstevel@tonic-gate  * Flags to anon_disclaim
426*7c478bd9Sstevel@tonic-gate  */
427*7c478bd9Sstevel@tonic-gate #define	ANON_PGLOOKUP_BLK	0x1	/* block on locked pages */
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate /*
430*7c478bd9Sstevel@tonic-gate  * SEGKP ANON pages that are locked are assumed to be LWP stack pages
431*7c478bd9Sstevel@tonic-gate  * and thus count towards the user pages locked count.
432*7c478bd9Sstevel@tonic-gate  * This value is protected by the same lock as availrmem.
433*7c478bd9Sstevel@tonic-gate  */
434*7c478bd9Sstevel@tonic-gate extern pgcnt_t anon_segkp_pages_locked;
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate extern int anon_debug;
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate #ifdef ANON_DEBUG
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate #define	A_ANON	0x01
441*7c478bd9Sstevel@tonic-gate #define	A_RESV	0x02
442*7c478bd9Sstevel@tonic-gate #define	A_MRESV	0x04
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate /* vararg-like debugging macro. */
445*7c478bd9Sstevel@tonic-gate #define	ANON_PRINT(f, printf_args) \
446*7c478bd9Sstevel@tonic-gate 		if (anon_debug & f) \
447*7c478bd9Sstevel@tonic-gate 			printf printf_args
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate #else	/* ANON_DEBUG */
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate #define	ANON_PRINT(f, printf_args)
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate #endif	/* ANON_DEBUG */
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
458*7c478bd9Sstevel@tonic-gate }
459*7c478bd9Sstevel@tonic-gate #endif
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate #endif	/* _VM_ANON_H */
462