|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 1993-1987 Carnegie Mellon University
4: * All Rights Reserved.
1.1.1.2 root 5: *
1.1 root 6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
1.1.1.2 root 11: *
1.1 root 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2 root 15: *
1.1 root 16: * Carnegie Mellon requests users of this software to return to
1.1.1.2 root 17: *
1.1 root 18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
1.1.1.2 root 22: *
1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: vm_object.h
28: * Author: Avadis Tevanian, Jr., Michael Wayne Young
29: * Date: 1985
30: *
31: * Virtual memory object module definitions.
32: */
33:
34: #ifndef _VM_VM_OBJECT_H_
35: #define _VM_VM_OBJECT_H_
36:
1.1.1.3 root 37: #include <sys/types.h>
1.1 root 38: #include <mach/kern_return.h>
39: #include <mach/boolean.h>
40: #include <mach/memory_object.h>
41: #include <mach/port.h>
42: #include <mach/vm_prot.h>
43: #include <mach/machine/vm_types.h>
44: #include <kern/queue.h>
45: #include <kern/lock.h>
46: #include <kern/assert.h>
1.1.1.3 root 47: #include <kern/debug.h>
1.1.1.5 root 48: #include <kern/macros.h>
1.1 root 49: #include <vm/pmap.h>
1.1.1.3 root 50: #include <ipc/ipc_types.h>
1.1 root 51:
52: #if MACH_PAGEMAP
53: #include <vm/vm_external.h>
54: #endif /* MACH_PAGEMAP */
55:
56: typedef struct ipc_port * pager_request_t;
57: #define PAGER_REQUEST_NULL ((pager_request_t) 0)
58:
59: /*
60: * We use "struct ipc_port *" instead of "ipc_port_t"
61: * to avoid include file circularities.
62: */
63:
64: struct vm_object {
1.1.1.6 ! root 65: queue_head_t memq; /* Resident memory */
1.1 root 66: decl_simple_lock_data(, Lock) /* Synchronization */
67: #if VM_OBJECT_DEBUG
68: thread_t LockHolder; /* Thread holding Lock */
1.1.1.2 root 69: #endif /* VM_OBJECT_DEBUG */
1.1 root 70: vm_size_t size; /* Object size (only valid
71: * if internal)
72: */
73:
1.1.1.3 root 74: int ref_count; /* Number of references */
1.1.1.6 ! root 75: unsigned long resident_page_count;
1.1 root 76: /* number of resident pages */
77:
78: struct vm_object *copy; /* Object that should receive
79: * a copy of my changed pages
80: */
81: struct vm_object *shadow; /* My shadow */
82: vm_offset_t shadow_offset; /* Offset into shadow */
83:
84: struct ipc_port *pager; /* Where to get data */
85: vm_offset_t paging_offset; /* Offset into memory object */
86: pager_request_t pager_request; /* Where data comes back */
87: struct ipc_port *pager_name; /* How to identify region */
88:
89: memory_object_copy_strategy_t
90: copy_strategy; /* How to handle data copy */
91:
92: unsigned int
93: absent_count; /* The number of pages that
94: * have been requested but
95: * not filled. That is, the
96: * number of pages for which
97: * the "absent" attribute is
98: * asserted.
99: */
100:
101: unsigned int /* boolean_t array */
102: all_wanted; /* Bit array of "want to be
103: * awakened" notations. See
104: * VM_OBJECT_EVENT_* items
105: * below
106: */
107:
108: unsigned int
109: paging_in_progress:16,
110: /* The memory object ports are
111: * being used (e.g., for pagein
112: * or pageout) -- don't change any
113: * of these fields (i.e., don't
114: * collapse, destroy or terminate)
115: */
1.1.1.6 ! root 116: /* boolean_t */ used_for_pageout:1,/* The object carries data sent to
! 117: * a memory manager, which signals
! 118: * it's done by releasing memory.
! 119: * This flag prevents coalescing so
! 120: * that unmapping memory immediately
! 121: * results in object termination.
! 122: */
1.1 root 123: /* boolean_t */ pager_created:1,/* Has pager ever been created? */
124: /* boolean_t */ pager_initialized:1,/* Are fields ready to use? */
125: /* boolean_t */ pager_ready:1, /* Will manager take requests? */
126:
127: /* boolean_t */ can_persist:1, /* The kernel may keep the data
128: * for this object (and rights to
129: * the memory object) after all
130: * address map references are
131: * deallocated?
132: */
133: /* boolean_t */ internal:1, /* Created by the kernel (and
134: * therefore, managed by the
135: * default memory manger)
136: */
137: /* boolean_t */ temporary:1, /* Permanent objects may be changed
138: * externally by the memory manager,
139: * and changes made in memory must
140: * be reflected back to the memory
141: * manager. Temporary objects lack
142: * both of these characteristics.
143: */
144: /* boolean_t */ alive:1, /* Not yet terminated (debug) */
145: /* boolean_t */ lock_in_progress : 1,
146: /* Is a multi-page lock
147: * request in progress?
148: */
149: /* boolean_t */ lock_restart : 1,
150: /* Should lock request in
151: * progress restart search?
152: */
153: /* boolean_t */ use_old_pageout : 1,
1.1.1.2 root 154: /* Use old pageout primitives?
1.1 root 155: */
156: /* boolean_t */ use_shared_copy : 1,/* Use shared (i.e.,
157: * delayed) copy on write */
1.1.1.6 ! root 158: /* boolean_t */ shadowed: 1, /* Shadow may exist */
1.1 root 159:
1.1.1.6 ! root 160: /* boolean_t */ cached: 1; /* Object is cached */
1.1 root 161: queue_chain_t cached_list; /* Attachment point for the list
162: * of objects cached as a result
163: * of their can_persist value
164: */
165: vm_offset_t last_alloc; /* last allocation offset */
166: #if MACH_PAGEMAP
167: vm_external_t existence_info;
168: #endif /* MACH_PAGEMAP */
169: };
170:
171: extern
172: vm_object_t kernel_object; /* the single kernel object */
173:
174: /*
175: * Declare procedures that operate on VM objects.
176: */
177:
178: extern void vm_object_bootstrap(void);
179: extern void vm_object_init(void);
1.1.1.6 ! root 180: extern void vm_object_collect(vm_object_t);
1.1 root 181: extern void vm_object_terminate(vm_object_t);
182: extern vm_object_t vm_object_allocate(vm_size_t);
183: extern void vm_object_reference(vm_object_t);
184: extern void vm_object_deallocate(vm_object_t);
185: extern void vm_object_pmap_protect(
186: vm_object_t object,
187: vm_offset_t offset,
188: vm_size_t size,
189: pmap_t pmap,
190: vm_offset_t pmap_start,
191: vm_prot_t prot);
192: extern void vm_object_pmap_remove(
193: vm_object_t object,
194: vm_offset_t start,
195: vm_offset_t end);
196: extern void vm_object_page_remove(
197: vm_object_t object,
198: vm_offset_t start,
199: vm_offset_t end);
200: extern void vm_object_shadow(
201: vm_object_t *object, /* in/out */
202: vm_offset_t *offset, /* in/out */
203: vm_size_t length);
204: extern void vm_object_collapse(vm_object_t);
205: extern vm_object_t vm_object_lookup(struct ipc_port *);
206: extern vm_object_t vm_object_lookup_name(struct ipc_port *);
207: extern struct ipc_port *vm_object_name(vm_object_t);
208: extern void vm_object_remove(vm_object_t);
209:
210: extern boolean_t vm_object_copy_temporary(
211: vm_object_t *_object, /* in/out */
212: vm_offset_t *_offset, /* in/out */
213: boolean_t *_src_needs_copy, /* out */
214: boolean_t *_dst_needs_copy); /* out */
215: extern kern_return_t vm_object_copy_strategically(
216: vm_object_t src_object,
217: vm_offset_t src_offset,
218: vm_size_t size,
219: vm_object_t *dst_object, /* out */
220: vm_offset_t *dst_offset, /* out */
221: boolean_t *dst_needs_copy); /* out */
222: extern kern_return_t vm_object_copy_slowly(
223: vm_object_t src_object,
224: vm_offset_t src_offset,
225: vm_size_t size,
226: boolean_t interruptible,
227: vm_object_t *_result_object); /* out */
228:
229: extern vm_object_t vm_object_enter(
230: struct ipc_port *pager,
231: vm_size_t size,
232: boolean_t internal);
233: extern void vm_object_pager_create(
234: vm_object_t object);
235: extern void vm_object_destroy(
236: struct ipc_port *pager);
237:
1.1.1.2 root 238: extern void vm_object_page_map(
239: vm_object_t,
240: vm_offset_t,
241: vm_size_t,
1.1 root 242: vm_offset_t (*)(void *, vm_offset_t),
243: void *);
244:
245: extern vm_object_t vm_object_request_object(struct ipc_port *);
246:
1.1.1.3 root 247: extern boolean_t vm_object_coalesce(
248: vm_object_t prev_object,
249: vm_object_t next_object,
250: vm_offset_t prev_offset,
251: vm_offset_t next_offset,
252: vm_size_t prev_size,
253: vm_size_t next_size);
254:
255: extern void vm_object_pager_wakeup(ipc_port_t pager);
256:
1.1.1.4 root 257: void memory_object_release(
258: ipc_port_t pager,
259: pager_request_t pager_request,
260: ipc_port_t pager_name);
261:
262: void vm_object_deactivate_pages(vm_object_t);
263:
264: vm_object_t vm_object_copy_delayed(
265: vm_object_t src_object);
266:
1.1 root 267: /*
268: * Event waiting handling
269: */
270:
271: #define VM_OBJECT_EVENT_INITIALIZED 0
272: #define VM_OBJECT_EVENT_PAGER_READY 1
273: #define VM_OBJECT_EVENT_PAGING_IN_PROGRESS 2
274: #define VM_OBJECT_EVENT_ABSENT_COUNT 3
275: #define VM_OBJECT_EVENT_LOCK_IN_PROGRESS 4
276:
277: #define vm_object_wait(object, event, interruptible) \
278: MACRO_BEGIN \
279: (object)->all_wanted |= 1 << (event); \
280: vm_object_sleep(((vm_offset_t) object) + (event), \
281: (object), \
282: (interruptible)); \
283: MACRO_END
284:
285: #define vm_object_assert_wait(object, event, interruptible) \
286: MACRO_BEGIN \
287: (object)->all_wanted |= 1 << (event); \
288: assert_wait((event_t)(((vm_offset_t) object) + (event)), (interruptible)); \
289: MACRO_END
290:
291: #define vm_object_wakeup(object, event) \
292: MACRO_BEGIN \
293: if ((object)->all_wanted & (1 << (event))) \
294: thread_wakeup((event_t)(((vm_offset_t) object) + (event))); \
295: (object)->all_wanted &= ~(1 << (event)); \
296: MACRO_END
297:
298: /*
299: * Routines implemented as macros
300: */
301:
1.1.1.6 ! root 302: #define vm_object_collectable(object) \
! 303: (((object)->ref_count == 0) \
! 304: && ((object)->resident_page_count == 0))
! 305:
1.1 root 306: #define vm_object_paging_begin(object) \
307: ((object)->paging_in_progress++)
308:
309: #define vm_object_paging_end(object) \
310: MACRO_BEGIN \
311: assert((object)->paging_in_progress != 0); \
312: if (--(object)->paging_in_progress == 0) { \
313: vm_object_wakeup(object, \
314: VM_OBJECT_EVENT_PAGING_IN_PROGRESS); \
315: } \
316: MACRO_END
317:
318: #define vm_object_paging_wait(object, interruptible) \
319: MACRO_BEGIN \
320: while ((object)->paging_in_progress != 0) { \
321: vm_object_wait( (object), \
322: VM_OBJECT_EVENT_PAGING_IN_PROGRESS, \
323: (interruptible)); \
324: vm_object_lock(object); \
325: \
326: /*XXX if ((interruptible) && */ \
327: /*XXX (current_thread()->wait_result != THREAD_AWAKENED))*/ \
328: /*XXX break; */ \
329: } \
330: MACRO_END
331:
332: #define vm_object_absent_assert_wait(object, interruptible) \
333: MACRO_BEGIN \
334: vm_object_assert_wait( (object), \
335: VM_OBJECT_EVENT_ABSENT_COUNT, \
336: (interruptible)); \
337: MACRO_END
338:
339:
340: #define vm_object_absent_release(object) \
341: MACRO_BEGIN \
342: (object)->absent_count--; \
343: vm_object_wakeup((object), \
344: VM_OBJECT_EVENT_ABSENT_COUNT); \
345: MACRO_END
346:
347: /*
348: * Object locking macros (with and without debugging)
349: */
350:
351: #if VM_OBJECT_DEBUG
352: #define vm_object_lock_init(object) \
353: MACRO_BEGIN \
354: simple_lock_init(&(object)->Lock); \
355: (object)->LockHolder = 0; \
356: MACRO_END
357: #define vm_object_lock(object) \
358: MACRO_BEGIN \
359: simple_lock(&(object)->Lock); \
360: (object)->LockHolder = current_thread(); \
361: MACRO_END
362: #define vm_object_unlock(object) \
363: MACRO_BEGIN \
364: if ((object)->LockHolder != current_thread()) \
365: panic("vm_object_unlock 0x%x", (object)); \
366: (object)->LockHolder = 0; \
367: simple_unlock(&(object)->Lock); \
368: MACRO_END
369: #define vm_object_lock_try(object) \
370: (simple_lock_try(&(object)->Lock) \
371: ? ( ((object)->LockHolder = current_thread()) , TRUE) \
372: : FALSE)
373: #define vm_object_sleep(event, object, interruptible) \
374: MACRO_BEGIN \
375: if ((object)->LockHolder != current_thread()) \
376: panic("vm_object_sleep %#x", (object)); \
377: (object)->LockHolder = 0; \
378: thread_sleep((event_t)(event), simple_lock_addr((object)->Lock), \
379: (interruptible)); \
380: MACRO_END
381: #define vm_object_lock_taken(object) \
382: ((object)->LockHolder == current_thread())
383: #else /* VM_OBJECT_DEBUG */
384: #define vm_object_lock_init(object) simple_lock_init(&(object)->Lock)
385: #define vm_object_lock(object) simple_lock(&(object)->Lock)
386: #define vm_object_unlock(object) simple_unlock(&(object)->Lock)
387: #define vm_object_lock_try(object) simple_lock_try(&(object)->Lock)
388: #define vm_object_sleep(event, object, interruptible) \
389: thread_sleep((event_t)(event), simple_lock_addr((object)->Lock), \
390: (interruptible))
391: #define vm_object_lock_taken(object) simple_lock_taken(&(object)->Lock)
392: #endif /* VM_OBJECT_DEBUG */
393:
1.1.1.3 root 394: /*
395: * Page cache accounting.
396: *
397: * The number of cached objects and pages can be read
398: * without holding any lock.
399: */
400:
401: extern int vm_object_cached_count;
402:
403: extern int vm_object_cached_pages;
404: decl_simple_lock_data(extern,vm_object_cached_pages_lock_data)
405:
406: #define vm_object_cached_pages_update(page_count) \
407: MACRO_BEGIN \
408: simple_lock(&vm_object_cached_pages_lock_data); \
409: vm_object_cached_pages += (page_count); \
410: simple_unlock(&vm_object_cached_pages_lock_data); \
411: MACRO_END
412:
1.1 root 413: #endif /* _VM_VM_OBJECT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.