Line data Source code
1 : /* $OpenBSD: uvm_object.c,v 1.14 2016/09/16 02:35:42 dlg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2006 The NetBSD Foundation, Inc.
5 : * All rights reserved.
6 : *
7 : * This code is derived from software contributed to The NetBSD Foundation
8 : * by Mindaugas Rasiukevicius.
9 : *
10 : * Redistribution and use in source and binary forms, with or without
11 : * modification, are permitted provided that the following conditions
12 : * are met:
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in the
17 : * documentation and/or other materials provided with the distribution.
18 : *
19 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 : * POSSIBILITY OF SUCH DAMAGE.
30 : */
31 :
32 : /*
33 : * uvm_object.c: operate with memory objects
34 : *
35 : */
36 :
37 : #include <sys/param.h>
38 : #include <sys/mman.h>
39 : #include <sys/atomic.h>
40 :
41 : #include <uvm/uvm.h>
42 :
43 : /* We will fetch this page count per step */
44 : #define FETCH_PAGECOUNT 16
45 :
46 : /*
47 : * uvm_objinit: initialise a uvm object.
48 : */
49 : void
50 0 : uvm_objinit(struct uvm_object *uobj, struct uvm_pagerops *pgops, int refs)
51 : {
52 0 : uobj->pgops = pgops;
53 0 : RBT_INIT(uvm_objtree, &uobj->memt);
54 0 : uobj->uo_npages = 0;
55 0 : uobj->uo_refs = refs;
56 0 : }
57 :
58 : #ifndef SMALL_KERNEL
59 : /*
60 : * uvm_objwire: wire the pages of entire uobj
61 : *
62 : * => caller must pass page-aligned start and end values
63 : * => if the caller passes in a pageq pointer, we'll return a list of
64 : * wired pages.
65 : */
66 :
67 : int
68 0 : uvm_objwire(struct uvm_object *uobj, voff_t start, voff_t end,
69 : struct pglist *pageq)
70 : {
71 0 : int i, npages, left, error;
72 0 : struct vm_page *pgs[FETCH_PAGECOUNT];
73 : voff_t offset = start;
74 :
75 0 : left = (end - start) >> PAGE_SHIFT;
76 :
77 0 : while (left) {
78 :
79 0 : npages = MIN(FETCH_PAGECOUNT, left);
80 :
81 : /* Get the pages */
82 0 : memset(pgs, 0, sizeof(pgs));
83 0 : error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0,
84 : PROT_READ | PROT_WRITE, MADV_SEQUENTIAL,
85 : PGO_ALLPAGES | PGO_SYNCIO);
86 :
87 0 : if (error)
88 : goto error;
89 :
90 0 : for (i = 0; i < npages; i++) {
91 :
92 0 : KASSERT(pgs[i] != NULL);
93 0 : KASSERT(!(pgs[i]->pg_flags & PG_RELEASED));
94 :
95 0 : if (pgs[i]->pg_flags & PQ_AOBJ) {
96 0 : atomic_clearbits_int(&pgs[i]->pg_flags,
97 : PG_CLEAN);
98 0 : uao_dropswap(uobj, i);
99 0 : }
100 : }
101 :
102 : /* Wire the pages */
103 0 : uvm_lock_pageq();
104 0 : for (i = 0; i < npages; i++) {
105 0 : uvm_pagewire(pgs[i]);
106 0 : if (pageq != NULL)
107 0 : TAILQ_INSERT_TAIL(pageq, pgs[i], pageq);
108 : }
109 0 : uvm_unlock_pageq();
110 :
111 : /* Unbusy the pages */
112 0 : uvm_page_unbusy(pgs, npages);
113 :
114 0 : left -= npages;
115 0 : offset += (voff_t)npages << PAGE_SHIFT;
116 : }
117 :
118 0 : return 0;
119 :
120 : error:
121 : /* Unwire the pages which have been wired */
122 0 : uvm_objunwire(uobj, start, offset);
123 :
124 0 : return error;
125 0 : }
126 :
127 : /*
128 : * uobj_unwirepages: unwire the pages of entire uobj
129 : *
130 : * => caller must pass page-aligned start and end values
131 : */
132 :
133 : void
134 0 : uvm_objunwire(struct uvm_object *uobj, voff_t start, voff_t end)
135 : {
136 : struct vm_page *pg;
137 : off_t offset;
138 :
139 0 : uvm_lock_pageq();
140 0 : for (offset = start; offset < end; offset += PAGE_SIZE) {
141 0 : pg = uvm_pagelookup(uobj, offset);
142 :
143 0 : KASSERT(pg != NULL);
144 0 : KASSERT(!(pg->pg_flags & PG_RELEASED));
145 :
146 0 : uvm_pageunwire(pg);
147 : }
148 0 : uvm_unlock_pageq();
149 0 : }
150 : #endif /* !SMALL_KERNEL */
|