Project

General

Profile

Statistics
| Revision:

root / lab4 / .minix-src / include / uvm / uvm_fault_i.h @ 14

History | View | Annotate | Download (4.75 KB)

1 13 up20180614
/*        $NetBSD: uvm_fault_i.h,v 1.28 2012/02/19 00:05:56 rmind Exp $        */
2
3
/*
4
 * Copyright (c) 1997 Charles D. Cranor and Washington University.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 *
27
 * from: Id: uvm_fault_i.h,v 1.1.6.1 1997/12/08 16:07:12 chuck Exp
28
 */
29
30
#ifndef _UVM_UVM_FAULT_I_H_
31
#define _UVM_UVM_FAULT_I_H_
32
33
/*
34
 * uvm_fault_i.h: fault inline functions
35
 */
36
37
/*
38
 * uvmfault_unlockmaps: unlock the maps
39
 */
40
41
static inline void
42
uvmfault_unlockmaps(struct uvm_faultinfo *ufi, bool write_locked)
43
{
44
        /*
45
         * ufi can be NULL when this isn't really a fault,
46
         * but merely paging in anon data.
47
         */
48
49
        if (ufi == NULL) {
50
                return;
51
        }
52
53
        if (write_locked) {
54
                vm_map_unlock(ufi->map);
55
        } else {
56
                vm_map_unlock_read(ufi->map);
57
        }
58
}
59
60
/*
61
 * uvmfault_unlockall: unlock everything passed in.
62
 *
63
 * => maps must be read-locked (not write-locked).
64
 */
65
66
static inline void
67
uvmfault_unlockall(struct uvm_faultinfo *ufi, struct vm_amap *amap,
68
    struct uvm_object *uobj)
69
{
70
71
        if (uobj)
72
                mutex_exit(uobj->vmobjlock);
73
        if (amap)
74
                amap_unlock(amap);
75
        uvmfault_unlockmaps(ufi, false);
76
}
77
78
/*
79
 * uvmfault_lookup: lookup a virtual address in a map
80
 *
81
 * => caller must provide a uvm_faultinfo structure with the IN
82
 *        params properly filled in
83
 * => we will lookup the map entry (handling submaps) as we go
84
 * => if the lookup is a success we will return with the maps locked
85
 * => if "write_lock" is true, we write_lock the map, otherwise we only
86
 *        get a read lock.
87
 * => note that submaps can only appear in the kernel and they are
88
 *        required to use the same virtual addresses as the map they
89
 *        are referenced by (thus address translation between the main
90
 *        map and the submap is unnecessary).
91
 */
92
93
static inline bool
94
uvmfault_lookup(struct uvm_faultinfo *ufi, bool write_lock)
95
{
96
        struct vm_map *tmpmap;
97
98
        /*
99
         * init ufi values for lookup.
100
         */
101
102
        ufi->map = ufi->orig_map;
103
        ufi->size = ufi->orig_size;
104
105
        /*
106
         * keep going down levels until we are done.   note that there can
107
         * only be two levels so we won't loop very long.
108
         */
109
110
        for (;;) {
111
                /*
112
                 * lock map
113
                 */
114
                if (write_lock) {
115
                        vm_map_lock(ufi->map);
116
                } else {
117
                        vm_map_lock_read(ufi->map);
118
                }
119
120
                /*
121
                 * lookup
122
                 */
123
                if (!uvm_map_lookup_entry(ufi->map, ufi->orig_rvaddr,
124
                    &ufi->entry)) {
125
                        uvmfault_unlockmaps(ufi, write_lock);
126
                        return(false);
127
                }
128
129
                /*
130
                 * reduce size if necessary
131
                 */
132
                if (ufi->entry->end - ufi->orig_rvaddr < ufi->size)
133
                        ufi->size = ufi->entry->end - ufi->orig_rvaddr;
134
135
                /*
136
                 * submap?    replace map with the submap and lookup again.
137
                 * note: VAs in submaps must match VAs in main map.
138
                 */
139
                if (UVM_ET_ISSUBMAP(ufi->entry)) {
140
                        tmpmap = ufi->entry->object.sub_map;
141
                        if (write_lock) {
142
                                vm_map_unlock(ufi->map);
143
                        } else {
144
                                vm_map_unlock_read(ufi->map);
145
                        }
146
                        ufi->map = tmpmap;
147
                        continue;
148
                }
149
150
                /*
151
                 * got it!
152
                 */
153
154
                ufi->mapv = ufi->map->timestamp;
155
                return(true);
156
157
        }        /* while loop */
158
159
        /*NOTREACHED*/
160
}
161
162
/*
163
 * uvmfault_relock: attempt to relock the same version of the map
164
 *
165
 * => fault data structures should be unlocked before calling.
166
 * => if a success (true) maps will be locked after call.
167
 */
168
169
static inline bool
170
uvmfault_relock(struct uvm_faultinfo *ufi)
171
{
172
        /*
173
         * ufi can be NULL when this isn't really a fault,
174
         * but merely paging in anon data.
175
         */
176
177
        if (ufi == NULL) {
178
                return true;
179
        }
180
181
        uvmexp.fltrelck++;
182
183
        /*
184
         * relock map.   fail if version mismatch (in which case nothing
185
         * gets locked).
186
         */
187
188
        vm_map_lock_read(ufi->map);
189
        if (ufi->mapv != ufi->map->timestamp) {
190
                vm_map_unlock_read(ufi->map);
191
                return(false);
192
        }
193
194
        uvmexp.fltrelckok++;
195
        return(true);
196
}
197
198
#endif /* _UVM_UVM_FAULT_I_H_ */