|
|
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,1988 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: * File: vm/vm_page.h
54: * Author: Avadis Tevanian, Jr., Michael Wayne Young
55: * Date: 1985
56: *
57: * Resident memory system definitions.
58: */
59:
60: #ifndef _VM_VM_PAGE_H_
61: #define _VM_VM_PAGE_H_
62:
63: #include <mach/boolean.h>
64: #include <mach/vm_prot.h>
65: #include <mach/vm_param.h>
66: #include <vm/vm_object.h>
67: #include <kern/queue.h>
68: #include <kern/lock.h>
69:
70: #include <kern/macro_help.h>
71:
72: /*
73: * Management of resident (logical) pages.
74: *
75: * A small structure is kept for each resident
76: * page, indexed by page number. Each structure
77: * is an element of several lists:
78: *
79: * A hash table bucket used to quickly
80: * perform object/offset lookups
81: *
82: * A list of all pages for a given object,
83: * so they can be quickly deactivated at
84: * time of deallocation.
85: *
86: * An ordered list of pages due for pageout.
87: *
88: * In addition, the structure contains the object
89: * and offset to which this page belongs (for pageout),
90: * and sundry status bits.
91: *
92: * Fields in this structure are locked either by the lock on the
93: * object that the page belongs to (O) or by the lock on the page
94: * queues (P). [Some fields require that both locks be held to
95: * change that field; holding either lock is sufficient to read.]
96: */
97:
98: struct vm_page {
99: queue_chain_t pageq; /* queue info for FIFO
100: * queue or free list (P) */
101: queue_chain_t listq; /* all pages in same object (O) */
102: struct vm_page *next; /* VP bucket link (O) */
103:
104: vm_object_t object; /* which object am I in (O&P) */
105: vm_offset_t offset; /* offset into that object (O,P) */
106:
107: unsigned int wire_count:16, /* how many wired down maps use me?
108: (O&P) */
109: /* boolean_t */ inactive:1, /* page is in inactive list (P) */
110: active:1, /* page is in active list (P) */
111: laundry:1, /* page is being cleaned now (P)*/
112: free:1, /* page is on free list (P) */
113: reference:1, /* page has been used (P) */
114: limbo:1, /* page prepped then stolen (P) */
115: pageout:1, /* page wired & busy for pageout (P) */
116: gobbled:1, /* page used internally (P) */
117: :0; /* (force to 'long' boundary) */
118: #ifdef ns32000
119: int pad; /* extra space for ns32000 bit ops */
120: #endif /* ns32000 */
121:
122: unsigned int
123: /* boolean_t */ busy:1, /* page is in transit (O) */
124: wanted:1, /* someone is waiting for page (O) */
125: tabled:1, /* page is in VP table (O) */
126: fictitious:1, /* Physical page doesn't exist (O) */
127: private:1, /* Page should not be returned to
128: * the free list (O) */
129: absent:1, /* Data has been requested, but is
130: * not yet available (O) */
131: error:1, /* Data manager was unable to provide
132: * data due to error (O) */
133: dirty:1, /* Page must be cleaned (O) */
134: cleaning:1, /* Page clean has begun (O) */
135: precious:1, /* Page is precious; data must be
136: * returned even if clean (O) */
137: clustered:1, /* page is not the faulted page (O) */
138: overwriting:1, /* Request to unlock has been made
139: * without having data. (O)
140: * [See vm_fault_page_overwrite] */
141: restart:1, /* Page was pushed higher in shadow
142: chain by copy_call-related pagers;
143: start again at top of chain */
144: lock_supplied:1,/* protection supplied by pager (O) */
145: /* vm_prot_t */ page_lock:3, /* Uses prohibited by pager (O) */
146: /* vm_prot_t */ unlock_request:3,/* Outstanding unlock request (O) */
147: unusual:1, /* Page is absent, error, restart or
148: page locked */
149: discard_request:1,/* a memory_object_discard_request()
150: * has been sent */
151: list_req_pending:1, /* pagein/pageout alt mechanism */
152: /* allows creation of list */
153: /* requests on pages that are */
154: /* actively being paged. */
155: :0;
156:
157: vm_offset_t phys_addr; /* Physical address of page, passed
158: * to pmap_enter (read-only) */
159: kern_return_t page_error;
160:
161: union {
162: struct {
163: unsigned int prep:16, /* page prep count */
164: pin:16; /* page pin pount */
165: } pp_counts;
166: unsigned int pp_both; /* used to test for both zero */
167: } prep_pin_u;
168: };
169:
170: typedef struct vm_page *vm_page_t;
171:
172: #define prep_count prep_pin_u.pp_counts.prep
173: #define pin_count prep_pin_u.pp_counts.pin
174: #define prep_pin_count prep_pin_u.pp_both
175:
176: #define VM_PAGE_NULL ((vm_page_t) 0)
177: #define NEXT_PAGE(m) ((vm_page_t) (m)->pageq.next)
178:
179: /*
180: * XXX The unusual bit should not be necessary. Most of the bit
181: * XXX fields above really want to be masks.
182: */
183:
184: /*
185: * For debugging, this macro can be defined to perform
186: * some useful check on a page structure.
187: */
188:
189: #define VM_PAGE_CHECK(mem)
190:
191: /*
192: * Each pageable resident page falls into one of three lists:
193: *
194: * free
195: * Available for allocation now.
196: * inactive
197: * Not referenced in any map, but still has an
198: * object/offset-page mapping, and may be dirty.
199: * This is the list of pages that should be
200: * paged out next.
201: * active
202: * A list of pages which have been placed in
203: * at least one physical map. This list is
204: * ordered, in LRU-like fashion.
205: */
206:
207: extern
208: vm_page_t vm_page_queue_free; /* memory free queue */
209: extern
210: vm_page_t vm_page_queue_fictitious; /* fictitious free queue */
211: extern
212: queue_head_t vm_page_queue_active; /* active memory queue */
213: extern
214: queue_head_t vm_page_queue_inactive; /* inactive memory queue */
215:
216: extern
217: vm_offset_t first_phys_addr; /* physical address for first_page */
218: extern
219: vm_offset_t last_phys_addr; /* physical address for last_page */
220:
221: extern
222: int vm_page_free_count; /* How many pages are free? */
223: extern
224: int vm_page_fictitious_count;/* How many fictitious pages are free? */
225: extern
226: int vm_page_active_count; /* How many pages are active? */
227: extern
228: int vm_page_inactive_count; /* How many pages are inactive? */
229: extern
230: int vm_page_wire_count; /* How many pages are wired? */
231: extern
232: int vm_page_free_target; /* How many do we want free? */
233: extern
234: int vm_page_free_min; /* When to wakeup pageout */
235: extern
236: int vm_page_inactive_target;/* How many do we want inactive? */
237: extern
238: int vm_page_free_reserved; /* How many pages reserved to do pageout */
239: extern
240: int vm_page_laundry_count; /* How many pages being laundered? */
241:
242: decl_mutex_data(,vm_page_queue_lock)
243: /* lock on active and inactive page queues */
244: decl_mutex_data(,vm_page_queue_free_lock)
245: /* lock on free page queue */
246: decl_simple_lock_data(extern,vm_page_preppin_lock) /* lock for prep/pin */
247:
248: extern unsigned int vm_page_free_wanted;
249: /* how many threads are waiting for memory */
250:
251: extern vm_offset_t vm_page_fictitious_addr;
252: /* (fake) phys_addr of fictitious pages */
253:
254: /*
255: * Prototypes for functions exported by this module.
256: */
257: extern void vm_page_bootstrap(
258: vm_offset_t *startp,
259: vm_offset_t *endp);
260:
261: extern void vm_page_module_init(void);
262:
263: extern void vm_page_create(
264: vm_offset_t start,
265: vm_offset_t end);
266:
267: extern vm_page_t vm_page_lookup(
268: vm_object_t object,
269: vm_offset_t offset);
270:
271: extern vm_page_t vm_page_grab_fictitious(void);
272:
273: extern void vm_page_release_fictitious(
274: vm_page_t page);
275:
276: extern boolean_t vm_page_convert(
277: vm_page_t page);
278:
279: extern void vm_page_more_fictitious(void);
280:
281: extern int vm_pool_low(void);
282:
283: extern vm_page_t vm_page_grab(void);
284:
285: extern void vm_page_release(
286: vm_page_t page);
287:
288: extern void vm_page_release_limbo(
289: vm_page_t page);
290:
291: extern void vm_page_limbo_exchange(
292: vm_page_t limbo_m,
293: vm_page_t new_m);
294:
295: extern void vm_page_wait( void );
296:
297: extern vm_page_t vm_page_alloc(
298: vm_object_t object,
299: vm_offset_t offset);
300:
301: extern void vm_page_init(
302: vm_page_t page,
303: vm_offset_t phys_addr);
304:
305: extern void vm_page_free(
306: vm_page_t page);
307:
308: extern void vm_page_activate(
309: vm_page_t page);
310:
311: extern void vm_page_deactivate(
312: vm_page_t page);
313:
314: extern void vm_page_rename(
315: vm_page_t page,
316: vm_object_t new_object,
317: vm_offset_t new_offset);
318:
319: extern void vm_page_insert(
320: vm_page_t page,
321: vm_object_t object,
322: vm_offset_t offset);
323:
324: extern void vm_page_replace(
325: vm_page_t mem,
326: vm_object_t object,
327: vm_offset_t offset);
328:
329: extern void vm_page_remove(
330: vm_page_t page);
331:
332: extern void vm_page_zero_fill(
333: vm_page_t page);
334:
335: extern void vm_page_part_zero_fill(
336: vm_page_t m,
337: vm_offset_t m_pa,
338: vm_size_t len);
339:
340: extern void vm_page_copy(
341: vm_page_t src_page,
342: vm_page_t dest_page);
343:
344: extern void vm_page_part_copy(
345: vm_page_t src_m,
346: vm_offset_t src_pa,
347: vm_page_t dst_m,
348: vm_offset_t dst_pa,
349: vm_size_t len);
350:
351: extern void vm_page_wire(
352: vm_page_t page);
353:
354: extern void vm_page_unwire(
355: vm_page_t page);
356:
357: extern void vm_set_page_size(void);
358:
359: extern void vm_page_gobble(
360: vm_page_t page);
361:
362: extern kern_return_t vm_page_prep(
363: vm_page_t m);
364:
365: extern kern_return_t vm_page_pin(
366: vm_page_t m);
367:
368: extern kern_return_t vm_page_unprep(
369: vm_page_t m);
370:
371: extern kern_return_t vm_page_unpin(
372: vm_page_t m);
373:
374: extern void cleanup_limbo_queue(void);
375:
376: /*
377: * Functions implemented as macros. m->wanted and m->busy are
378: * protected by the object lock.
379: */
380:
381: #define PAGE_ASSERT_WAIT(m, interruptible) \
382: MACRO_BEGIN \
383: (m)->wanted = TRUE; \
384: assert_wait((event_t) (m), (interruptible)); \
385: MACRO_END
386:
387: #define PAGE_WAKEUP_DONE(m) \
388: MACRO_BEGIN \
389: (m)->busy = FALSE; \
390: if ((m)->wanted) { \
391: (m)->wanted = FALSE; \
392: thread_wakeup((event_t) (m)); \
393: } \
394: MACRO_END
395:
396: #define PAGE_WAKEUP(m) \
397: MACRO_BEGIN \
398: if ((m)->wanted) { \
399: (m)->wanted = FALSE; \
400: thread_wakeup((event_t) (m)); \
401: } \
402: MACRO_END
403:
404: #define VM_PAGE_FREE(p) \
405: MACRO_BEGIN \
406: vm_page_lock_queues(); \
407: vm_page_free(p); \
408: vm_page_unlock_queues(); \
409: MACRO_END
410:
411: #define VM_PAGE_GRAB_FICTITIOUS(M) \
412: MACRO_BEGIN \
413: while ((M = vm_page_grab_fictitious()) == VM_PAGE_NULL) \
414: vm_page_more_fictitious(); \
415: MACRO_END
416:
417: #define VM_PAGE_WAIT() vm_page_wait()
418:
419: #define vm_page_lock_queues() mutex_lock(&vm_page_queue_lock)
420: #define vm_page_unlock_queues() mutex_unlock(&vm_page_queue_lock)
421: #define vm_page_pin_lock() simple_lock(&vm_page_preppin_lock)
422: #define vm_page_pin_unlock() simple_unlock(&vm_page_preppin_lock)
423:
424: #define VM_PAGE_QUEUES_REMOVE(mem) \
425: MACRO_BEGIN \
426: if (mem->active) { \
427: assert(!mem->inactive); \
428: queue_remove(&vm_page_queue_active, \
429: mem, vm_page_t, pageq); \
430: mem->active = FALSE; \
431: if (!mem->fictitious) \
432: vm_page_active_count--; \
433: } \
434: \
435: if (mem->inactive) { \
436: assert(!mem->active); \
437: queue_remove(&vm_page_queue_inactive, \
438: mem, vm_page_t, pageq); \
439: mem->inactive = FALSE; \
440: if (!mem->fictitious) \
441: vm_page_inactive_count--; \
442: } \
443: MACRO_END
444:
445: /*
446: * Data structure for automatic physical memory reservation. Declared
447: * here, defined in vm_resident.c.
448: *
449: * The following data structure is used to specify contiguous ranges
450: * of physical memory that should be allocated before virtual memory
451: * initialization. Each element is a pair of addresses--the address
452: * of the size of the chunk that should be allocated, the second the
453: * location at which to place the pointer to that section when it is
454: * allocated.
455: *
456: * The actual mechanism for allocating the contiguous physical memory
457: * is machine dependent, and occurs during the machine dependent VM
458: * initialization.
459: *
460: * This is defined as a pointer rather than a dimensionless array
461: * because the PGI (intel 860) compiler can't handle dimensionless
462: * arrays.
463: */
464:
465: extern struct pmem_reserve {
466: unsigned long *pmem_size; /* In */
467: vm_offset_t *pmem_addr; /* Out */
468: } *pmem_reserve_ctl;
469:
470: extern int pmem_reserve_ctl_size;
471:
472: #endif /* _VM_VM_PAGE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.