|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52:
53: /*
54: * This module maintains information about the presence of
55: * pages not in memory. Since an external memory object
56: * must maintain a complete knowledge of its contents, this
57: * information takes the form of hints.
58: */
59: #include <string.h> /* for memcpy()/memset() */
60:
61: #include <mach/boolean.h>
62: #include <vm/vm_external.h>
63: #include <kern/kalloc.h>
64: #include <mach/vm_param.h>
65: #include <kern/assert.h>
66:
67: /*
68: * The implementation uses bit arrays to record whether
69: * a page has been written to external storage. For
70: * convenience, these bit arrays come in various sizes.
71: * For example, a map N bytes long can record:
72: *
73: * 16 bytes = 128 pages = (@ 4KB/page) 512KB
74: * 1024 bytes = 8192 pages = (@ 4KB/page) 32MB
75: * 4096 bytes = 32768 pages = (@ 4KB/page) 128MB
76: *
77: * For a 32-bit machine with 4KB pages, the largest size
78: * would be 128KB = 32 pages. Machines with a larger page
79: * size are more efficient.
80: *
81: * This subsystem must be very careful about memory allocation,
82: * since vm_external_create() is almost always called with
83: * vm_privilege set. The largest map to be allocated must be less
84: * than or equal to a single page, and the kalloc subsystem must
85: * never allocate more than a single page in response to a kalloc()
86: * request. Also, vm_external_destroy() must not take any blocking
87: * locks, since it is called with a vm_object lock held. This
88: * implies that kfree() MUST be implemented in terms of zfree()
89: * NOT kmem_free() for all request sizes that this subsystem uses.
90: *
91: * For efficiency, this subsystem knows that the kalloc() subsystem
92: * is implemented in terms of power-of-2 allocation, and that the
93: * minimum allocation unit is KALLOC_MINSIZE
94: *
95: * XXXO
96: * Should consider using existence_map to hold bits directly
97: * when existence_size <= 4 bytes (i.e., 32 pages).
98: */
99:
100: #define SMALL_SIZE KALLOC_MINSIZE
101: #define LARGE_SIZE PAGE_SIZE
102:
103: static vm_size_t power_of_2(vm_size_t size);
104:
105: static vm_size_t
106: power_of_2(vm_size_t size)
107: {
108: vm_size_t power;
109:
110: power = 2 * SMALL_SIZE;
111: while (power < size) {
112: power <<= 1;
113: }
114: return(power);
115: }
116:
117: vm_external_map_t
118: vm_external_create(
119: vm_offset_t size)
120: {
121: vm_size_t bytes;
122: vm_external_map_t result = VM_EXTERNAL_NULL;
123:
124: bytes = stob(size);
125: if (bytes <= SMALL_SIZE) {
126: if ((result = (vm_external_map_t)kalloc(SMALL_SIZE)) != NULL) {
127: memset(result, 0, SMALL_SIZE);
128: }
129: } else if (bytes <= LARGE_SIZE) {
130: bytes = power_of_2(bytes);
131:
132: if ((result = (vm_external_map_t)kalloc(bytes)) != NULL) {
133: memset(result, 0, bytes);
134: }
135: }
136: return(result);
137: }
138:
139: void
140: vm_external_destroy(
141: vm_external_map_t map,
142: vm_size_t size)
143: {
144: vm_size_t bytes;
145:
146: if (map == VM_EXTERNAL_NULL)
147: return;
148:
149: bytes = stob(size);
150: if (bytes <= SMALL_SIZE) {
151: bytes = SMALL_SIZE;
152: } else {
153: bytes = power_of_2(bytes);
154: }
155: kfree((vm_offset_t)map, bytes);
156: }
157:
158: /*
159: * Return the number of bytes needed for a vm_external_map given the
160: * size of the object to be mapped, i.e. the size of the map that was
161: * created by vm_external_create.
162: */
163: vm_size_t
164: vm_external_map_size(
165: vm_offset_t size)
166: {
167: vm_size_t bytes;
168:
169: bytes = stob(size);
170: if (bytes != 0)
171: if (bytes <= SMALL_SIZE) {
172: bytes = SMALL_SIZE;
173: } else {
174: bytes = power_of_2(bytes);
175: }
176: return bytes;
177: }
178:
179: void
180: vm_external_copy(
181: vm_external_map_t old_map,
182: vm_size_t old_size,
183: vm_external_map_t new_map)
184: {
185: /*
186: * Cannot copy non-existent maps
187: */
188: if ((old_map == VM_EXTERNAL_NULL) || (new_map == VM_EXTERNAL_NULL))
189: return;
190:
191: /*
192: * Copy old map to new
193: */
194: memcpy(new_map, old_map, stob(old_size));
195: }
196:
197: boolean_t
198: vm_external_within(
199: vm_size_t new_size,
200: vm_size_t old_size)
201: {
202: vm_size_t new_bytes;
203: vm_size_t old_bytes;
204:
205: assert(new_size >= old_size);
206:
207: /*
208: * "old_bytes" is calculated to be the actual amount of space
209: * allocated for a map of size "old_size".
210: */
211: old_bytes = stob(old_size);
212: if (old_bytes <= SMALL_SIZE) old_bytes = SMALL_SIZE;
213: else if (old_bytes <= LARGE_SIZE) old_bytes = power_of_2(old_bytes);
214:
215: /*
216: * "new_bytes" is the map size required to map the "new_size" object.
217: * Since the rounding algorithms are the same, we needn't actually
218: * round up new_bytes to get the correct answer
219: */
220: new_bytes = stob(new_size);
221:
222: return(new_bytes <= old_bytes);
223: }
224:
225: vm_external_state_t
226: _vm_external_state_get(
227: vm_external_map_t map,
228: vm_offset_t offset)
229: {
230: unsigned
231: int bit, byte;
232:
233: assert (map != VM_EXTERNAL_NULL);
234:
235: bit = atop(offset);
236: byte = bit >> 3;
237: if (map[byte] & (1 << (bit & 07))) {
238: return VM_EXTERNAL_STATE_EXISTS;
239: } else {
240: return VM_EXTERNAL_STATE_ABSENT;
241: }
242: }
243:
244: void
245: vm_external_state_set(
246: vm_external_map_t map,
247: vm_offset_t offset)
248: {
249: unsigned
250: int bit, byte;
251:
252: if (map == VM_EXTERNAL_NULL)
253: return;
254:
255: bit = atop(offset);
256: byte = bit >> 3;
257: map[byte] |= (1 << (bit & 07));
258: }
259:
260: void
261: vm_external_state_clr(
262: vm_external_map_t map,
263: vm_offset_t offset)
264: {
265: unsigned
266: int bit, byte;
267:
268: if (map == VM_EXTERNAL_NULL)
269: return;
270:
271: bit = atop(offset);
272: byte = bit >> 3;
273: map[byte] &= ~(1 << (bit & 07));
274: }
275:
276: void
277: vm_external_module_initialize(void)
278: {
279: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.