Fri Sep 14 18:56:15 2012 UTC ()
- Describe uvm_aobj and the lock order.
- Remove unnecessary uao_dropswap_range1() wrapper.
- KNF.  Sprinkle some __cacheline_aligned.


(rmind)
diff -r1.116 -r1.117 src/sys/uvm/uvm_aobj.c
diff -r1.21 -r1.22 src/sys/uvm/uvm_aobj.h

cvs diff -r1.116 -r1.117 src/sys/uvm/uvm_aobj.c (expand / switch to unified diff)

--- src/sys/uvm/uvm_aobj.c 2011/09/06 16:41:55 1.116
+++ src/sys/uvm/uvm_aobj.c 2012/09/14 18:56:15 1.117
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uvm_aobj.c,v 1.116 2011/09/06 16:41:55 matt Exp $ */ 1/* $NetBSD: uvm_aobj.c,v 1.117 2012/09/14 18:56:15 rmind Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and 4 * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and
5 * Washington University. 5 * Washington University.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -28,191 +28,171 @@ @@ -28,191 +28,171 @@
28 * from: Id: uvm_aobj.c,v 1.1.2.5 1998/02/06 05:14:38 chs Exp 28 * from: Id: uvm_aobj.c,v 1.1.2.5 1998/02/06 05:14:38 chs Exp
29 */ 29 */
30 30
31/* 31/*
32 * uvm_aobj.c: anonymous memory uvm_object pager 32 * uvm_aobj.c: anonymous memory uvm_object pager
33 * 33 *
34 * author: Chuck Silvers <chuq@chuq.com> 34 * author: Chuck Silvers <chuq@chuq.com>
35 * started: Jan-1998 35 * started: Jan-1998
36 * 36 *
37 * - design mostly from Chuck Cranor 37 * - design mostly from Chuck Cranor
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v 1.116 2011/09/06 16:41:55 matt Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v 1.117 2012/09/14 18:56:15 rmind Exp $");
42 42
43#include "opt_uvmhist.h" 43#include "opt_uvmhist.h"
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/proc.h> 47#include <sys/proc.h>
48#include <sys/kernel.h> 48#include <sys/kernel.h>
49#include <sys/kmem.h> 49#include <sys/kmem.h>
50#include <sys/pool.h> 50#include <sys/pool.h>
51 51
52#include <uvm/uvm.h> 52#include <uvm/uvm.h>
53 53
54/* 54/*
55 * an aobj manages anonymous-memory backed uvm_objects. in addition 55 * An anonymous UVM object (aobj) manages anonymous-memory. In addition to
56 * to keeping the list of resident pages, it also keeps a list of 56 * keeping the list of resident pages, it may also keep a list of allocated
57 * allocated swap blocks. depending on the size of the aobj this list 57 * swap blocks. Depending on the size of the object, this list is either
58 * of allocated swap blocks is either stored in an array (small objects) 58 * stored in an array (small objects) or in a hash table (large objects).
59 * or in a hash table (large objects). 59 *
60 */ 60 * Lock order
61 61 *
62/* 62 * uvm_object::vmobjlock ->
63 * local structures 63 * uao_list_lock
64 */ 64 */
65 65
66/* 66/*
67 * for hash tables, we break the address space of the aobj into blocks 67 * Note: for hash tables, we break the address space of the aobj into blocks
68 * of UAO_SWHASH_CLUSTER_SIZE pages. we require the cluster size to 68 * of UAO_SWHASH_CLUSTER_SIZE pages, which shall be a power of two.
69 * be a power of two. 
70 */ 69 */
71 70
72#define UAO_SWHASH_CLUSTER_SHIFT 4 71#define UAO_SWHASH_CLUSTER_SHIFT 4
73#define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT) 72#define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT)
74 73
75/* get the "tag" for this page index */ 74/* Get the "tag" for this page index. */
76#define UAO_SWHASH_ELT_TAG(PAGEIDX) \ 75#define UAO_SWHASH_ELT_TAG(idx) ((idx) >> UAO_SWHASH_CLUSTER_SHIFT)
77 ((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT) 76#define UAO_SWHASH_ELT_PAGESLOT_IDX(idx) \
 77 ((idx) & (UAO_SWHASH_CLUSTER_SIZE - 1))
78 78
79#define UAO_SWHASH_ELT_PAGESLOT_IDX(PAGEIDX) \ 79/* Given an ELT and a page index, find the swap slot. */
80 ((PAGEIDX) & (UAO_SWHASH_CLUSTER_SIZE - 1)) 80#define UAO_SWHASH_ELT_PAGESLOT(elt, idx) \
 81 ((elt)->slots[UAO_SWHASH_ELT_PAGESLOT_IDX(idx)])
81 82
82/* given an ELT and a page index, find the swap slot */ 83/* Given an ELT, return its pageidx base. */
83#define UAO_SWHASH_ELT_PAGESLOT(ELT, PAGEIDX) \ 84#define UAO_SWHASH_ELT_PAGEIDX_BASE(ELT) \
84 ((ELT)->slots[UAO_SWHASH_ELT_PAGESLOT_IDX(PAGEIDX)]) 85 ((elt)->tag << UAO_SWHASH_CLUSTER_SHIFT)
85 86
86/* given an ELT, return its pageidx base */ 87/* The hash function. */
87#define UAO_SWHASH_ELT_PAGEIDX_BASE(ELT) \ 88#define UAO_SWHASH_HASH(aobj, idx) \
88 ((ELT)->tag << UAO_SWHASH_CLUSTER_SHIFT) 89 (&(aobj)->u_swhash[(((idx) >> UAO_SWHASH_CLUSTER_SHIFT) \
 90 & (aobj)->u_swhashmask)])
89 91
90/* 92/*
91 * the swhash hash function 93 * The threshold which determines whether we will use an array or a
92 */ 
93 
94#define UAO_SWHASH_HASH(AOBJ, PAGEIDX) \ 
95 (&(AOBJ)->u_swhash[(((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT) \ 
96 & (AOBJ)->u_swhashmask)]) 
97 
98/* 
99 * the swhash threshhold determines if we will use an array or a 
100 * hash table to store the list of allocated swap blocks. 94 * hash table to store the list of allocated swap blocks.
101 */ 95 */
102 96#define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4)
103#define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4) 97#define UAO_USES_SWHASH(aobj) \
104#define UAO_USES_SWHASH(AOBJ) \ 98 ((aobj)->u_pages > UAO_SWHASH_THRESHOLD)
105 ((AOBJ)->u_pages > UAO_SWHASH_THRESHOLD) /* use hash? */ 99
106 100/* The number of buckets in a hash, with an upper bound. */
107/* 101#define UAO_SWHASH_MAXBUCKETS 256
108 * the number of buckets in a swhash, with an upper bound 102#define UAO_SWHASH_BUCKETS(aobj) \
109 */ 103 (MIN((aobj)->u_pages >> UAO_SWHASH_CLUSTER_SHIFT, UAO_SWHASH_MAXBUCKETS))
110 
111#define UAO_SWHASH_MAXBUCKETS 256 
112#define UAO_SWHASH_BUCKETS(AOBJ) \ 
113 (MIN((AOBJ)->u_pages >> UAO_SWHASH_CLUSTER_SHIFT, \ 
114 UAO_SWHASH_MAXBUCKETS)) 
115 104
116/* 105/*
117 * uao_swhash_elt: when a hash table is being used, this structure defines 106 * uao_swhash_elt: when a hash table is being used, this structure defines
118 * the format of an entry in the bucket list. 107 * the format of an entry in the bucket list.
119 */ 108 */
120 109
121struct uao_swhash_elt { 110struct uao_swhash_elt {
122 LIST_ENTRY(uao_swhash_elt) list; /* the hash list */ 111 LIST_ENTRY(uao_swhash_elt) list; /* the hash list */
123 voff_t tag; /* our 'tag' */ 112 voff_t tag; /* our 'tag' */
124 int count; /* our number of active slots */ 113 int count; /* our number of active slots */
125 int slots[UAO_SWHASH_CLUSTER_SIZE]; /* the slots */ 114 int slots[UAO_SWHASH_CLUSTER_SIZE]; /* the slots */
126}; 115};
127 116
128/* 117/*
129 * uao_swhash: the swap hash table structure 118 * uao_swhash: the swap hash table structure
130 */ 119 */
131 120
132LIST_HEAD(uao_swhash, uao_swhash_elt); 121LIST_HEAD(uao_swhash, uao_swhash_elt);
133 122
134/* 123/*
135 * uao_swhash_elt_pool: pool of uao_swhash_elt structures. 124 * uao_swhash_elt_pool: pool of uao_swhash_elt structures.
136 * Note: pages for this pool must not come from a pageable kernel map. 125 * Note: pages for this pool must not come from a pageable kernel map.
137 */ 126 */
138static struct pool uao_swhash_elt_pool; 127static struct pool uao_swhash_elt_pool __cacheline_aligned;
139 128
140/* 129/*
141 * uvm_aobj: the actual anon-backed uvm_object 130 * uvm_aobj: the actual anon-backed uvm_object
142 * 131 *
143 * => the uvm_object is at the top of the structure, this allows 132 * => the uvm_object is at the top of the structure, this allows
144 * (struct uvm_aobj *) == (struct uvm_object *) 133 * (struct uvm_aobj *) == (struct uvm_object *)
145 * => only one of u_swslots and u_swhash is used in any given aobj 134 * => only one of u_swslots and u_swhash is used in any given aobj
146 */ 135 */
147 136
148struct uvm_aobj { 137struct uvm_aobj {
149 struct uvm_object u_obj; /* has: lock, pgops, memq, #pages, #refs */ 138 struct uvm_object u_obj; /* has: lock, pgops, memq, #pages, #refs */
150 pgoff_t u_pages; /* number of pages in entire object */ 139 pgoff_t u_pages; /* number of pages in entire object */
151 int u_flags; /* the flags (see uvm_aobj.h) */ 140 int u_flags; /* the flags (see uvm_aobj.h) */
152 int *u_swslots; /* array of offset->swapslot mappings */ 141 int *u_swslots; /* array of offset->swapslot mappings */
153 /* 142 /*
154 * hashtable of offset->swapslot mappings 143 * hashtable of offset->swapslot mappings
155 * (u_swhash is an array of bucket heads) 144 * (u_swhash is an array of bucket heads)
156 */ 145 */
157 struct uao_swhash *u_swhash; 146 struct uao_swhash *u_swhash;
158 u_long u_swhashmask; /* mask for hashtable */ 147 u_long u_swhashmask; /* mask for hashtable */
159 LIST_ENTRY(uvm_aobj) u_list; /* global list of aobjs */ 148 LIST_ENTRY(uvm_aobj) u_list; /* global list of aobjs */
160}; 149};
161 150
162/* 
163 * local functions 
164 */ 
165 
166static void uao_free(struct uvm_aobj *); 151static void uao_free(struct uvm_aobj *);
167static int uao_get(struct uvm_object *, voff_t, struct vm_page **, 152static int uao_get(struct uvm_object *, voff_t, struct vm_page **,
168 int *, int, vm_prot_t, int, int); 153 int *, int, vm_prot_t, int, int);
169static int uao_put(struct uvm_object *, voff_t, voff_t, int); 154static int uao_put(struct uvm_object *, voff_t, voff_t, int);
170 155
171static void uao_detach_locked(struct uvm_object *); 156static void uao_detach_locked(struct uvm_object *);
172static void uao_reference_locked(struct uvm_object *); 157static void uao_reference_locked(struct uvm_object *);
173 158
174#if defined(VMSWAP) 159#if defined(VMSWAP)
175static struct uao_swhash_elt *uao_find_swhash_elt 160static struct uao_swhash_elt *uao_find_swhash_elt
176 (struct uvm_aobj *, int, bool); 161 (struct uvm_aobj *, int, bool);
177 162
178static bool uao_pagein(struct uvm_aobj *, int, int); 163static bool uao_pagein(struct uvm_aobj *, int, int);
179static bool uao_pagein_page(struct uvm_aobj *, int); 164static bool uao_pagein_page(struct uvm_aobj *, int);
180static void uao_dropswap_range1(struct uvm_aobj *, voff_t, voff_t); 
181#endif /* defined(VMSWAP) */ 165#endif /* defined(VMSWAP) */
182 166
183/* 167/*
184 * aobj_pager 168 * aobj_pager
185 * 169 *
186 * note that some functions (e.g. put) are handled elsewhere 170 * note that some functions (e.g. put) are handled elsewhere
187 */ 171 */
188 172
189const struct uvm_pagerops aobj_pager = { 173const struct uvm_pagerops aobj_pager = {
190 .pgo_reference = uao_reference, 174 .pgo_reference = uao_reference,
191 .pgo_detach = uao_detach, 175 .pgo_detach = uao_detach,
192 .pgo_get = uao_get, 176 .pgo_get = uao_get,
193 .pgo_put = uao_put, 177 .pgo_put = uao_put,
194}; 178};
195 179
196/* 180/*
197 * uao_list: global list of active aobjs, locked by uao_list_lock 181 * uao_list: global list of active aobjs, locked by uao_list_lock
198 */ 182 */
199 183
200static LIST_HEAD(aobjlist, uvm_aobj) uao_list; 184static LIST_HEAD(aobjlist, uvm_aobj) uao_list __cacheline_aligned;
201static kmutex_t uao_list_lock; 185static kmutex_t uao_list_lock __cacheline_aligned;
202 
203/* 
204 * functions 
205 */ 
206 186
207/* 187/*
208 * hash table/array related functions 188 * hash table/array related functions
209 */ 189 */
210 190
211#if defined(VMSWAP) 191#if defined(VMSWAP)
212 192
213/* 193/*
214 * uao_find_swhash_elt: find (or create) a hash table entry for a page 194 * uao_find_swhash_elt: find (or create) a hash table entry for a page
215 * offset. 195 * offset.
216 * 196 *
217 * => the object should be locked by the caller 197 * => the object should be locked by the caller
218 */ 198 */
@@ -262,45 +242,42 @@ uao_find_swhash_elt(struct uvm_aobj *aob @@ -262,45 +242,42 @@ uao_find_swhash_elt(struct uvm_aobj *aob
262 */ 242 */
263 243
264int 244int
265uao_find_swslot(struct uvm_object *uobj, int pageidx) 245uao_find_swslot(struct uvm_object *uobj, int pageidx)
266{ 246{
267 struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; 247 struct uvm_aobj *aobj = (struct uvm_aobj *)uobj;
268 struct uao_swhash_elt *elt; 248 struct uao_swhash_elt *elt;
269 249
270 /* 250 /*
271 * if noswap flag is set, then we never return a slot 251 * if noswap flag is set, then we never return a slot
272 */ 252 */
273 253
274 if (aobj->u_flags & UAO_FLAG_NOSWAP) 254 if (aobj->u_flags & UAO_FLAG_NOSWAP)
275 return(0); 255 return 0;
276 256
277 /* 257 /*
278 * if hashing, look in hash table. 258 * if hashing, look in hash table.
279 */ 259 */
280 260
281 if (UAO_USES_SWHASH(aobj)) { 261 if (UAO_USES_SWHASH(aobj)) {
282 elt = uao_find_swhash_elt(aobj, pageidx, false); 262 elt = uao_find_swhash_elt(aobj, pageidx, false);
283 if (elt) 263 return elt ? UAO_SWHASH_ELT_PAGESLOT(elt, pageidx) : 0;
284 return(UAO_SWHASH_ELT_PAGESLOT(elt, pageidx)); 
285 else 
286 return(0); 
287 } 264 }
288 265
289 /* 266 /*
290 * otherwise, look in the array 267 * otherwise, look in the array
291 */ 268 */
292 269
293 return(aobj->u_swslots[pageidx]); 270 return aobj->u_swslots[pageidx];
294} 271}
295 272
296/* 273/*
297 * uao_set_swslot: set the swap slot for a page in an aobj. 274 * uao_set_swslot: set the swap slot for a page in an aobj.
298 * 275 *
299 * => setting a slot to zero frees the slot 276 * => setting a slot to zero frees the slot
300 * => object must be locked by caller 277 * => object must be locked by caller
301 * => we return the old slot number, or -1 if we failed to allocate 278 * => we return the old slot number, or -1 if we failed to allocate
302 * memory to record the new slot number 279 * memory to record the new slot number
303 */ 280 */
304 281
305int 282int
306uao_set_swslot(struct uvm_object *uobj, int pageidx, int slot) 283uao_set_swslot(struct uvm_object *uobj, int pageidx, int slot)
@@ -309,31 +286,28 @@ uao_set_swslot(struct uvm_object *uobj,  @@ -309,31 +286,28 @@ uao_set_swslot(struct uvm_object *uobj,
309 struct uao_swhash_elt *elt; 286 struct uao_swhash_elt *elt;
310 int oldslot; 287 int oldslot;
311 UVMHIST_FUNC("uao_set_swslot"); UVMHIST_CALLED(pdhist); 288 UVMHIST_FUNC("uao_set_swslot"); UVMHIST_CALLED(pdhist);
312 UVMHIST_LOG(pdhist, "aobj %p pageidx %d slot %d", 289 UVMHIST_LOG(pdhist, "aobj %p pageidx %d slot %d",
313 aobj, pageidx, slot, 0); 290 aobj, pageidx, slot, 0);
314 291
315 KASSERT(mutex_owned(uobj->vmobjlock) || uobj->uo_refs == 0); 292 KASSERT(mutex_owned(uobj->vmobjlock) || uobj->uo_refs == 0);
316 293
317 /* 294 /*
318 * if noswap flag is set, then we can't set a non-zero slot. 295 * if noswap flag is set, then we can't set a non-zero slot.
319 */ 296 */
320 297
321 if (aobj->u_flags & UAO_FLAG_NOSWAP) { 298 if (aobj->u_flags & UAO_FLAG_NOSWAP) {
322 if (slot == 0) 299 KASSERTMSG(slot == 0, "uao_set_swslot: no swap object");
323 return(0); 300 return 0;
324 
325 printf("uao_set_swslot: uobj = %p\n", uobj); 
326 panic("uao_set_swslot: NOSWAP object"); 
327 } 301 }
328 302
329 /* 303 /*
330 * are we using a hash table? if so, add it in the hash. 304 * are we using a hash table? if so, add it in the hash.
331 */ 305 */
332 306
333 if (UAO_USES_SWHASH(aobj)) { 307 if (UAO_USES_SWHASH(aobj)) {
334 308
335 /* 309 /*
336 * Avoid allocating an entry just to free it again if 310 * Avoid allocating an entry just to free it again if
337 * the page had not swap slot in the first place, and 311 * the page had not swap slot in the first place, and
338 * we are freeing. 312 * we are freeing.
339 */ 313 */
@@ -358,74 +332,72 @@ uao_set_swslot(struct uvm_object *uobj,  @@ -358,74 +332,72 @@ uao_set_swslot(struct uvm_object *uobj,
358 if (oldslot) 332 if (oldslot)
359 elt->count--; 333 elt->count--;
360 334
361 if (elt->count == 0) { 335 if (elt->count == 0) {
362 LIST_REMOVE(elt, list); 336 LIST_REMOVE(elt, list);
363 pool_put(&uao_swhash_elt_pool, elt); 337 pool_put(&uao_swhash_elt_pool, elt);
364 } 338 }
365 } 339 }
366 } else { 340 } else {
367 /* we are using an array */ 341 /* we are using an array */
368 oldslot = aobj->u_swslots[pageidx]; 342 oldslot = aobj->u_swslots[pageidx];
369 aobj->u_swslots[pageidx] = slot; 343 aobj->u_swslots[pageidx] = slot;
370 } 344 }
371 return (oldslot); 345 return oldslot;
372} 346}
373 347
374#endif /* defined(VMSWAP) */ 348#endif /* defined(VMSWAP) */
375 349
376/* 350/*
377 * end of hash/array functions 351 * end of hash/array functions
378 */ 352 */
379 353
380/* 354/*
381 * uao_free: free all resources held by an aobj, and then free the aobj 355 * uao_free: free all resources held by an aobj, and then free the aobj
382 * 356 *
383 * => the aobj should be dead 357 * => the aobj should be dead
384 */ 358 */
385 359
386static void 360static void
387uao_free(struct uvm_aobj *aobj) 361uao_free(struct uvm_aobj *aobj)
388{ 362{
 363 struct uvm_object *uobj = &aobj->u_obj;
389 364
390#if defined(VMSWAP) 365 uao_dropswap_range(aobj, 0, 0);
391 uao_dropswap_range1(aobj, 0, 0); 366 mutex_exit(uobj->vmobjlock);
392#endif /* defined(VMSWAP) */ 
393 
394 mutex_exit(aobj->u_obj.vmobjlock); 
395 367
396#if defined(VMSWAP) 368#if defined(VMSWAP)
397 if (UAO_USES_SWHASH(aobj)) { 369 if (UAO_USES_SWHASH(aobj)) {
398 370
399 /* 371 /*
400 * free the hash table itself. 372 * free the hash table itself.
401 */ 373 */
402 374
403 hashdone(aobj->u_swhash, HASH_LIST, aobj->u_swhashmask); 375 hashdone(aobj->u_swhash, HASH_LIST, aobj->u_swhashmask);
404 } else { 376 } else {
405 377
406 /* 378 /*
407 * free the array itsself. 379 * free the array itsself.
408 */ 380 */
409 381
410 kmem_free(aobj->u_swslots, aobj->u_pages * sizeof(int)); 382 kmem_free(aobj->u_swslots, aobj->u_pages * sizeof(int));
411 } 383 }
412#endif /* defined(VMSWAP) */ 384#endif /* defined(VMSWAP) */
413 385
414 /* 386 /*
415 * finally free the aobj itself 387 * finally free the aobj itself
416 */ 388 */
417 389
418 uvm_obj_destroy(&aobj->u_obj, true); 390 uvm_obj_destroy(uobj, true);
419 kmem_free(aobj, sizeof(struct uvm_aobj)); 391 kmem_free(aobj, sizeof(struct uvm_aobj));
420} 392}
421 393
422/* 394/*
423 * pager functions 395 * pager functions
424 */ 396 */
425 397
426/* 398/*
427 * uao_create: create an aobj of the given size and return its uvm_object. 399 * uao_create: create an aobj of the given size and return its uvm_object.
428 * 400 *
429 * => for normal use, flags are always zero 401 * => for normal use, flags are always zero
430 * => for the kernel object, the flags are: 402 * => for the kernel object, the flags are:
431 * UAO_FLAG_KERNOBJ - allocate the kernel object (can only happen once) 403 * UAO_FLAG_KERNOBJ - allocate the kernel object (can only happen once)
@@ -483,54 +455,52 @@ uao_create(vsize_t size, int flags) @@ -483,54 +455,52 @@ uao_create(vsize_t size, int flags)
483 &aobj->u_swhashmask); 455 &aobj->u_swhashmask);
484 if (aobj->u_swhash == NULL) 456 if (aobj->u_swhash == NULL)
485 panic("uao_create: hashinit swhash failed"); 457 panic("uao_create: hashinit swhash failed");
486 } else { 458 } else {
487 aobj->u_swslots = kmem_zalloc(pages * sizeof(int), 459 aobj->u_swslots = kmem_zalloc(pages * sizeof(int),
488 kernswap ? KM_NOSLEEP : KM_SLEEP); 460 kernswap ? KM_NOSLEEP : KM_SLEEP);
489 if (aobj->u_swslots == NULL) 461 if (aobj->u_swslots == NULL)
490 panic("uao_create: swslots allocation failed"); 462 panic("uao_create: swslots allocation failed");
491 } 463 }
492#endif /* defined(VMSWAP) */ 464#endif /* defined(VMSWAP) */
493 465
494 if (flags) { 466 if (flags) {
495 aobj->u_flags &= ~UAO_FLAG_NOSWAP; /* clear noswap */ 467 aobj->u_flags &= ~UAO_FLAG_NOSWAP; /* clear noswap */
496 return(&aobj->u_obj); 468 return &aobj->u_obj;
497 } 469 }
498 } 470 }
499 471
500 /* 472 /*
501 * Initialise UVM object. 473 * Initialise UVM object.
502 */ 474 */
503 475
504 const bool kernobj = (flags & UAO_FLAG_KERNOBJ) != 0; 476 const bool kernobj = (flags & UAO_FLAG_KERNOBJ) != 0;
505 uvm_obj_init(&aobj->u_obj, &aobj_pager, !kernobj, refs); 477 uvm_obj_init(&aobj->u_obj, &aobj_pager, !kernobj, refs);
506 if (__predict_false(kernobj)) { 478 if (__predict_false(kernobj)) {
507 /* Initialisation only once, for UAO_FLAG_KERNOBJ. */ 479 /* Initialisation only once, for UAO_FLAG_KERNOBJ. */
508 mutex_init(&kernel_object_lock, MUTEX_DEFAULT, IPL_NONE); 480 mutex_init(&kernel_object_lock, MUTEX_DEFAULT, IPL_NONE);
509 uvm_obj_setlock(&aobj->u_obj, &kernel_object_lock); 481 uvm_obj_setlock(&aobj->u_obj, &kernel_object_lock);
510 } 482 }
511 483
512 /* 484 /*
513 * now that aobj is ready, add it to the global list 485 * now that aobj is ready, add it to the global list
514 */ 486 */
515 487
516 mutex_enter(&uao_list_lock); 488 mutex_enter(&uao_list_lock);
517 LIST_INSERT_HEAD(&uao_list, aobj, u_list); 489 LIST_INSERT_HEAD(&uao_list, aobj, u_list);
518 mutex_exit(&uao_list_lock); 490 mutex_exit(&uao_list_lock);
519 return(&aobj->u_obj); 491 return(&aobj->u_obj);
520} 492}
521 493
522 
523 
524/* 494/*
525 * uao_init: set up aobj pager subsystem 495 * uao_init: set up aobj pager subsystem
526 * 496 *
527 * => called at boot time from uvm_pager_init() 497 * => called at boot time from uvm_pager_init()
528 */ 498 */
529 499
530void 500void
531uao_init(void) 501uao_init(void)
532{ 502{
533 static int uao_initialized; 503 static int uao_initialized;
534 504
535 if (uao_initialized) 505 if (uao_initialized)
536 return; 506 return;
@@ -905,29 +875,26 @@ uao_put(struct uvm_object *uobj, voff_t  @@ -905,29 +875,26 @@ uao_put(struct uvm_object *uobj, voff_t
905 * 875 *
906 * => prefer map unlocked (not required) 876 * => prefer map unlocked (not required)
907 * => object must be locked! we will _unlock_ it before starting any I/O. 877 * => object must be locked! we will _unlock_ it before starting any I/O.
908 * => flags: PGO_ALLPAGES: get all of the pages 878 * => flags: PGO_ALLPAGES: get all of the pages
909 * PGO_LOCKED: fault data structures are locked 879 * PGO_LOCKED: fault data structures are locked
910 * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx] 880 * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx]
911 * => NOTE: caller must check for released pages!! 881 * => NOTE: caller must check for released pages!!
912 */ 882 */
913 883
914static int 884static int
915uao_get(struct uvm_object *uobj, voff_t offset, struct vm_page **pps, 885uao_get(struct uvm_object *uobj, voff_t offset, struct vm_page **pps,
916 int *npagesp, int centeridx, vm_prot_t access_type, int advice, int flags) 886 int *npagesp, int centeridx, vm_prot_t access_type, int advice, int flags)
917{ 887{
918#if defined(VMSWAP) 
919 struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; 
920#endif /* defined(VMSWAP) */ 
921 voff_t current_offset; 888 voff_t current_offset;
922 struct vm_page *ptmp = NULL; /* Quell compiler warning */ 889 struct vm_page *ptmp = NULL; /* Quell compiler warning */
923 int lcv, gotpages, maxpages, swslot, pageidx; 890 int lcv, gotpages, maxpages, swslot, pageidx;
924 bool done; 891 bool done;
925 UVMHIST_FUNC("uao_get"); UVMHIST_CALLED(pdhist); 892 UVMHIST_FUNC("uao_get"); UVMHIST_CALLED(pdhist);
926 893
927 UVMHIST_LOG(pdhist, "aobj=%p offset=%d, flags=%d", 894 UVMHIST_LOG(pdhist, "aobj=%p offset=%d, flags=%d",
928 (struct uvm_aobj *)uobj, offset, flags,0); 895 (struct uvm_aobj *)uobj, offset, flags,0);
929 896
930 /* 897 /*
931 * get number of pages 898 * get number of pages
932 */ 899 */
933 900
@@ -949,27 +916,27 @@ uao_get(struct uvm_object *uobj, voff_t  @@ -949,27 +916,27 @@ uao_get(struct uvm_object *uobj, voff_t
949 gotpages = 0; /* # of pages we got so far */ 916 gotpages = 0; /* # of pages we got so far */
950 for (lcv = 0, current_offset = offset ; lcv < maxpages ; 917 for (lcv = 0, current_offset = offset ; lcv < maxpages ;
951 lcv++, current_offset += PAGE_SIZE) { 918 lcv++, current_offset += PAGE_SIZE) {
952 /* do we care about this page? if not, skip it */ 919 /* do we care about this page? if not, skip it */
953 if (pps[lcv] == PGO_DONTCARE) 920 if (pps[lcv] == PGO_DONTCARE)
954 continue; 921 continue;
955 ptmp = uvm_pagelookup(uobj, current_offset); 922 ptmp = uvm_pagelookup(uobj, current_offset);
956 923
957 /* 924 /*
958 * if page is new, attempt to allocate the page, 925 * if page is new, attempt to allocate the page,
959 * zero-fill'd. 926 * zero-fill'd.
960 */ 927 */
961 928
962 if (ptmp == NULL && uao_find_swslot(&aobj->u_obj, 929 if (ptmp == NULL && uao_find_swslot(uobj,
963 current_offset >> PAGE_SHIFT) == 0) { 930 current_offset >> PAGE_SHIFT) == 0) {
964 ptmp = uvm_pagealloc(uobj, current_offset, 931 ptmp = uvm_pagealloc(uobj, current_offset,
965 NULL, UVM_FLAG_COLORMATCH|UVM_PGA_ZERO); 932 NULL, UVM_FLAG_COLORMATCH|UVM_PGA_ZERO);
966 if (ptmp) { 933 if (ptmp) {
967 /* new page */ 934 /* new page */
968 ptmp->flags &= ~(PG_FAKE); 935 ptmp->flags &= ~(PG_FAKE);
969 ptmp->pqflags |= PQ_AOBJ; 936 ptmp->pqflags |= PQ_AOBJ;
970 goto gotpage; 937 goto gotpage;
971 } 938 }
972 } 939 }
973 940
974 /* 941 /*
975 * to be useful must get a non-busy page 942 * to be useful must get a non-busy page
@@ -1112,27 +1079,27 @@ gotpage: @@ -1112,27 +1079,27 @@ gotpage:
1112 /* 1079 /*
1113 * if we own the valid page at the correct offset, pps[lcv] will 1080 * if we own the valid page at the correct offset, pps[lcv] will
1114 * point to it. nothing more to do except go to the next page. 1081 * point to it. nothing more to do except go to the next page.
1115 */ 1082 */
1116 1083
1117 if (pps[lcv]) 1084 if (pps[lcv])
1118 continue; /* next lcv */ 1085 continue; /* next lcv */
1119 1086
1120 /* 1087 /*
1121 * we have a "fake/busy/clean" page that we just allocated. 1088 * we have a "fake/busy/clean" page that we just allocated.
1122 * do the needed "i/o", either reading from swap or zeroing. 1089 * do the needed "i/o", either reading from swap or zeroing.
1123 */ 1090 */
1124 1091
1125 swslot = uao_find_swslot(&aobj->u_obj, pageidx); 1092 swslot = uao_find_swslot(uobj, pageidx);
1126 1093
1127 /* 1094 /*
1128 * just zero the page if there's nothing in swap. 1095 * just zero the page if there's nothing in swap.
1129 */ 1096 */
1130 1097
1131 if (swslot == 0) { 1098 if (swslot == 0) {
1132 1099
1133 /* 1100 /*
1134 * page hasn't existed before, just zero it. 1101 * page hasn't existed before, just zero it.
1135 */ 1102 */
1136 1103
1137 uvm_pagezero(ptmp); 1104 uvm_pagezero(ptmp);
1138 } else { 1105 } else {
@@ -1381,50 +1348,51 @@ restart: @@ -1381,50 +1348,51 @@ restart:
1381 */ 1348 */
1382 1349
1383 rv = uao_pagein_page(aobj, i); 1350 rv = uao_pagein_page(aobj, i);
1384 if (rv) { 1351 if (rv) {
1385 return rv; 1352 return rv;
1386 } 1353 }
1387 } 1354 }
1388 } 1355 }
1389 1356
1390 return false; 1357 return false;
1391} 1358}
1392 1359
1393/* 1360/*
1394 * page in a page from an aobj. used for swap_off. 1361 * uao_pagein_page: page in a single page from an anonymous UVM object.
1395 * returns true if pagein was aborted due to lack of memory. 
1396 * 1362 *
1397 * => aobj must be locked and is returned locked. 1363 * => Returns true if pagein was aborted due to lack of memory.
 1364 * => Object must be locked and is returned locked.
1398 */ 1365 */
1399 1366
1400static bool 1367static bool
1401uao_pagein_page(struct uvm_aobj *aobj, int pageidx) 1368uao_pagein_page(struct uvm_aobj *aobj, int pageidx)
1402{ 1369{
 1370 struct uvm_object *uobj = &aobj->u_obj;
1403 struct vm_page *pg; 1371 struct vm_page *pg;
1404 int rv, npages; 1372 int rv, npages;
1405 1373
1406 pg = NULL; 1374 pg = NULL;
1407 npages = 1; 1375 npages = 1;
1408 /* locked: aobj */ 1376
1409 rv = uao_get(&aobj->u_obj, pageidx << PAGE_SHIFT, 1377 KASSERT(mutex_owned(uobj->vmobjlock));
1410 &pg, &npages, 0, VM_PROT_READ|VM_PROT_WRITE, 0, PGO_SYNCIO); 1378 rv = uao_get(uobj, pageidx << PAGE_SHIFT, &pg, &npages,
1411 /* unlocked: aobj */ 1379 0, VM_PROT_READ | VM_PROT_WRITE, 0, PGO_SYNCIO);
1412 1380
1413 /* 1381 /*
1414 * relock and finish up. 1382 * relock and finish up.
1415 */ 1383 */
1416 1384
1417 mutex_enter(aobj->u_obj.vmobjlock); 1385 mutex_enter(uobj->vmobjlock);
1418 switch (rv) { 1386 switch (rv) {
1419 case 0: 1387 case 0:
1420 break; 1388 break;
1421 1389
1422 case EIO: 1390 case EIO:
1423 case ERESTART: 1391 case ERESTART:
1424 1392
1425 /* 1393 /*
1426 * nothing more to do on errors. 1394 * nothing more to do on errors.
1427 * ERESTART can only mean that the anon was freed, 1395 * ERESTART can only mean that the anon was freed,
1428 * so again there's nothing to do. 1396 * so again there's nothing to do.
1429 */ 1397 */
1430 1398
@@ -1458,37 +1426,30 @@ uao_pagein_page(struct uvm_aobj *aobj, i @@ -1458,37 +1426,30 @@ uao_pagein_page(struct uvm_aobj *aobj, i
1458} 1426}
1459 1427
1460/* 1428/*
1461 * uao_dropswap_range: drop swapslots in the range. 1429 * uao_dropswap_range: drop swapslots in the range.
1462 * 1430 *
1463 * => aobj must be locked and is returned locked. 1431 * => aobj must be locked and is returned locked.
1464 * => start is inclusive. end is exclusive. 1432 * => start is inclusive. end is exclusive.
1465 */ 1433 */
1466 1434
1467void 1435void
1468uao_dropswap_range(struct uvm_object *uobj, voff_t start, voff_t end) 1436uao_dropswap_range(struct uvm_object *uobj, voff_t start, voff_t end)
1469{ 1437{
1470 struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; 1438 struct uvm_aobj *aobj = (struct uvm_aobj *)uobj;
 1439 int swpgonlydelta = 0;
1471 1440
1472 KASSERT(mutex_owned(uobj->vmobjlock)); 1441 KASSERT(mutex_owned(uobj->vmobjlock));
1473 1442
1474 uao_dropswap_range1(aobj, start, end); 
1475} 
1476 
1477static void 
1478uao_dropswap_range1(struct uvm_aobj *aobj, voff_t start, voff_t end) 
1479{ 
1480 int swpgonlydelta = 0; 
1481 
1482 if (end == 0) { 1443 if (end == 0) {
1483 end = INT64_MAX; 1444 end = INT64_MAX;
1484 } 1445 }
1485 1446
1486 if (UAO_USES_SWHASH(aobj)) { 1447 if (UAO_USES_SWHASH(aobj)) {
1487 int i, hashbuckets = aobj->u_swhashmask + 1; 1448 int i, hashbuckets = aobj->u_swhashmask + 1;
1488 voff_t taghi; 1449 voff_t taghi;
1489 voff_t taglo; 1450 voff_t taglo;
1490 1451
1491 taglo = UAO_SWHASH_ELT_TAG(start); 1452 taglo = UAO_SWHASH_ELT_TAG(start);
1492 taghi = UAO_SWHASH_ELT_TAG(end); 1453 taghi = UAO_SWHASH_ELT_TAG(end);
1493 1454
1494 for (i = 0; i < hashbuckets; i++) { 1455 for (i = 0; i < hashbuckets; i++) {

cvs diff -r1.21 -r1.22 src/sys/uvm/uvm_aobj.h (expand / switch to unified diff)

--- src/sys/uvm/uvm_aobj.h 2011/02/02 15:28:38 1.21
+++ src/sys/uvm/uvm_aobj.h 2012/09/14 18:56:15 1.22
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uvm_aobj.h,v 1.21 2011/02/02 15:28:38 chuck Exp $ */ 1/* $NetBSD: uvm_aobj.h,v 1.22 2012/09/14 18:56:15 rmind Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and 4 * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and
5 * Washington University. 5 * Washington University.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -30,48 +30,42 @@ @@ -30,48 +30,42 @@
30/* 30/*
31 * uvm_aobj.h: anonymous memory uvm_object pager 31 * uvm_aobj.h: anonymous memory uvm_object pager
32 * 32 *
33 * author: Chuck Silvers <chuq@chuq.com> 33 * author: Chuck Silvers <chuq@chuq.com>
34 * started: Jan-1998 34 * started: Jan-1998
35 * 35 *
36 * - design mostly from Chuck Cranor 36 * - design mostly from Chuck Cranor
37 */ 37 */
38 38
39#ifndef _UVM_UVM_AOBJ_H_ 39#ifndef _UVM_UVM_AOBJ_H_
40#define _UVM_UVM_AOBJ_H_ 40#define _UVM_UVM_AOBJ_H_
41 41
42/* 42/*
43 * flags 43 * Flags for uao_create: UAO_FLAG_KERNOBJ and UAO_FLAG_KERNSWAP are
 44 * used only once, to initialise UVM.
44 */ 45 */
45 46#define UAO_FLAG_KERNOBJ 0x1 /* create kernel object */
46/* flags for uao_create: can only be used one time (at bootup) */ 47#define UAO_FLAG_KERNSWAP 0x2 /* enable kernel swap */
47#define UAO_FLAG_KERNOBJ 0x1 /* create kernel object */ 48#define UAO_FLAG_NOSWAP 0x8 /* aobj may not swap */
48#define UAO_FLAG_KERNSWAP 0x2 /* enable kernel swap */ 
49 
50/* internal flags */ 
51#define UAO_FLAG_NOSWAP 0x8 /* aobj can't swap (kernel obj only!) */ 
52 49
53#ifdef _KERNEL 50#ifdef _KERNEL
54#if defined(_KERNEL_OPT) 51#if defined(_KERNEL_OPT)
55#include "opt_vmswap.h" 52#include "opt_vmswap.h"
56#endif 53#endif
57 54
58/* 55void uao_init(void);
59 * prototypes 56int uao_set_swslot(struct uvm_object *, int, int);
60 */ 
61 57
62void uao_init(void); 58#if defined(VMSWAP)
63int uao_set_swslot(struct uvm_object *, int, int); 59int uao_find_swslot(struct uvm_object *, int);
64#if defined(VMSWAP) 60void uao_dropswap(struct uvm_object *, int);
65int uao_find_swslot(struct uvm_object *, int); 61bool uao_swap_off(int, int);
66void uao_dropswap(struct uvm_object *, int); 62void uao_dropswap_range(struct uvm_object *, voff_t, voff_t);
67bool uao_swap_off(int, int); 63#else
68void uao_dropswap_range(struct uvm_object *, voff_t, voff_t); 
69#else /* defined(VMSWAP) */ 
70#define uao_find_swslot(obj, off) 0 64#define uao_find_swslot(obj, off) 0
71#define uao_dropswap(obj, off) /* nothing */ 65#define uao_dropswap(obj, off) /* nothing */
72#define uao_dropswap_range(obj, lo, hi) /* nothing */ 66#define uao_dropswap_range(obj, lo, hi) /* nothing */
73#endif /* defined(VMSWAP) */ 67#endif
74 68
75#endif /* _KERNEL */ 69#endif /* _KERNEL */
76 70
77#endif /* _UVM_UVM_AOBJ_H_ */ 71#endif /* _UVM_UVM_AOBJ_H_ */