|
|
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,1987 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_object.h
54: * Author: Avadis Tevanian, Jr., Michael Wayne Young
55: * Date: 1985
56: *
57: * Virtual memory object module definitions.
58: */
59:
60: #ifndef _VM_VM_OBJECT_H_
61: #define _VM_VM_OBJECT_H_
62:
63: #include <mach_pagemap.h>
64: #include <task_swapper.h>
65:
66: #include <mach/kern_return.h>
67: #include <mach/boolean.h>
68: #include <mach/memory_object_types.h>
69: #include <mach/port.h>
70: #include <mach/vm_prot.h>
71: #include <mach/machine/vm_types.h>
72: #include <kern/queue.h>
73: #include <kern/lock.h>
74: #include <kern/assert.h>
75: #include <kern/macro_help.h>
76: #include <ipc/ipc_types.h>
77: #include <vm/pmap.h>
78: #include <kern/misc_protos.h>
79:
80: #if MACH_PAGEMAP
81: #include <vm/vm_external.h>
82: #endif /* MACH_PAGEMAP */
83:
84: typedef struct ipc_port * pager_request_t;
85: #define PAGER_REQUEST_NULL ((pager_request_t) 0)
86:
87: /*
88: * Types defined:
89: *
90: * vm_object_t Virtual memory object.
91: *
92: * We use "struct ipc_port *" instead of "ipc_port_t"
93: * to avoid include file circularities.
94: */
95:
96: struct vm_object {
97: queue_head_t memq; /* Resident memory */
98: decl_mutex_data(, Lock) /* Synchronization */
99:
100: vm_size_t size; /* Object size (only valid
101: * if internal)
102: */
103: vm_size_t frozen_size; /* How much has been marked
104: * copy-on-write (only
105: * valid if copy_symmetric)
106: */
107: int ref_count; /* Number of references */
108: #if TASK_SWAPPER
109: int res_count; /* Residency references (swap)*/
110: #endif /* TASK_SWAPPER */
111: unsigned int resident_page_count;
112: /* number of resident pages */
113:
114: struct vm_object *copy; /* Object that should receive
115: * a copy of my changed pages,
116: * for copy_delay, or just the
117: * temporary object that
118: * shadows this object, for
119: * copy_call.
120: */
121: struct vm_object *shadow; /* My shadow */
122: vm_offset_t shadow_offset; /* Offset into shadow */
123:
124: struct ipc_port *pager; /* Where to get data */
125: vm_offset_t paging_offset; /* Offset into memory object */
126: pager_request_t pager_request; /* Where data comes back */
127:
128: memory_object_copy_strategy_t
129: copy_strategy; /* How to handle data copy */
130:
131: unsigned int absent_count; /* The number of pages that
132: * have been requested but
133: * not filled. That is, the
134: * number of pages for which
135: * the "absent" attribute is
136: * asserted.
137: */
138:
139: unsigned int paging_in_progress;
140: /* The memory object ports are
141: * being used (e.g., for pagein
142: * or pageout) -- don't change
143: * any of these fields (i.e.,
144: * don't collapse, destroy or
145: * terminate)
146: */
147: unsigned int
148: /* boolean_t array */ all_wanted:11, /* Bit array of "want to be
149: * awakened" notations. See
150: * VM_OBJECT_EVENT_* items
151: * below */
152: /* boolean_t */ pager_created:1, /* Has pager been created? */
153: /* boolean_t */ pager_initialized:1, /* Are fields ready to use? */
154: /* boolean_t */ pager_ready:1, /* Will pager take requests? */
155:
156: /* boolean_t */ pager_trusted:1,/* The pager for this object
157: * is trusted. This is true for
158: * all internal objects (backed
159: * by the default pager)
160: */
161: /* boolean_t */ can_persist:1, /* The kernel may keep the data
162: * for this object (and rights
163: * to the memory object) after
164: * all address map references
165: * are deallocated?
166: */
167: /* boolean_t */ internal:1, /* Created by the kernel (and
168: * therefore, managed by the
169: * default memory manger)
170: */
171: /* boolean_t */ temporary:1, /* Permanent objects may be
172: * changed externally by the
173: * memory manager, and changes
174: * made in memory must be
175: * reflected back to the memory
176: * manager. Temporary objects
177: * lack both of these
178: * characteristics.
179: */
180: /* boolean_t */ private:1, /* magic device_pager object,
181: * holds private pages only */
182: /* boolean_t */ pageout:1, /* pageout object. contains
183: * private pages that refer to
184: * a real memory object. */
185: /* boolean_t */ alive:1, /* Not yet terminated */
186:
187: /* boolean_t */ lock_in_progress:1,
188: /* Is a multi-page lock
189: * request in progress?
190: */
191: /* boolean_t */ lock_restart:1,
192: /* Should lock request in
193: * progress restart search?
194: */
195: /* boolean_t */ shadowed:1, /* Shadow may exist */
196: /* boolean_t */ silent_overwrite:1,
197: /* Allow full page overwrite
198: * without data_request if
199: * page is absent */
200: /* boolean_t */ advisory_pageout:1,
201: /* Instead of sending page
202: * via OOL, just notify
203: * pager that the kernel
204: * wants to discard it, page
205: * remains in object */
206: /* boolean_t */ true_share:1;
207: /* This object is mapped
208: * in more than one place
209: * and hence cannot be
210: * coalesced */
211:
212:
213: queue_chain_t cached_list; /* Attachment point for the
214: * list of objects cached as a
215: * result of their can_persist
216: * value
217: */
218:
219: queue_head_t msr_q; /* memory object synchronise
220: request queue */
221:
222: vm_offset_t last_alloc; /* last allocation offset */
223: vm_size_t cluster_size; /* size of paging cluster */
224: #if MACH_PAGEMAP
225: vm_external_map_t existence_map; /* bitmap of pages written to
226: * backing storage */
227: #endif /* MACH_PAGEMAP */
228: #if MACH_ASSERT
229: struct vm_object *paging_object; /* object which pages to be
230: * swapped out are temporary
231: * put in current object
232: */
233: #endif
234: };
235:
236: extern
237: vm_object_t kernel_object; /* the single kernel object */
238:
239: int vm_object_absent_max; /* maximum number of absent pages
240: at a time for each object */
241:
242: # define VM_MSYNC_INITIALIZED 0
243: # define VM_MSYNC_SYNCHRONIZING 1
244: # define VM_MSYNC_DONE 2
245:
246: struct msync_req {
247: queue_chain_t msr_q; /* object request queue */
248: queue_chain_t req_q; /* vm_msync request queue */
249: unsigned int flag;
250: vm_offset_t offset;
251: vm_offset_t length;
252: vm_object_t object; /* back pointer */
253: decl_mutex_data(, msync_req_lock) /* Lock for this structure */
254: };
255:
256: typedef struct msync_req *msync_req_t;
257: #define MSYNC_REQ_NULL ((msync_req_t) 0)
258:
259: /*
260: * Macros to allocate and free msync_reqs
261: */
262: #define msync_req_alloc(msr) \
263: MACRO_BEGIN \
264: (msr) = (msync_req_t)kalloc(sizeof(struct msync_req)); \
265: mutex_init(&(msr)->msync_req_lock, ETAP_VM_MSYNC); \
266: msr->flag = VM_MSYNC_INITIALIZED; \
267: MACRO_END
268:
269: #define msync_req_free(msr) \
270: (kfree((vm_offset_t)(msr), sizeof(struct msync_req)))
271:
272: #define msr_lock(msr) mutex_lock(&(msr)->msync_req_lock)
273: #define msr_unlock(msr) mutex_unlock(&(msr)->msync_req_lock)
274:
275: /*
276: * Declare procedures that operate on VM objects.
277: */
278:
279: extern void vm_object_bootstrap(void);
280:
281: extern void vm_object_init(void);
282:
283: extern vm_object_t vm_object_allocate(
284: vm_size_t size);
285:
286: #if MACH_ASSERT
287: extern void vm_object_reference(
288: vm_object_t object);
289: #else /* MACH_ASSERT */
290: #define vm_object_reference(object) \
291: MACRO_BEGIN \
292: vm_object_t Object = (object); \
293: if (Object) { \
294: vm_object_lock(Object); \
295: Object->ref_count++; \
296: vm_object_res_reference(Object); \
297: vm_object_unlock(Object); \
298: } \
299: MACRO_END
300: #endif /* MACH_ASSERT */
301:
302: extern void vm_object_deallocate(
303: vm_object_t object);
304:
305: extern void vm_object_pmap_protect(
306: vm_object_t object,
307: vm_offset_t offset,
308: vm_offset_t size,
309: pmap_t pmap,
310: vm_offset_t pmap_start,
311: vm_prot_t prot);
312:
313: extern void vm_object_page_remove(
314: vm_object_t object,
315: vm_offset_t start,
316: vm_offset_t end);
317:
318: extern boolean_t vm_object_coalesce(
319: vm_object_t prev_object,
320: vm_object_t next_object,
321: vm_offset_t prev_offset,
322: vm_offset_t next_offset,
323: vm_size_t prev_size,
324: vm_size_t next_size);
325:
326: extern boolean_t vm_object_shadow(
327: vm_object_t *object,
328: vm_offset_t *offset,
329: vm_size_t length);
330:
331: extern void vm_object_collapse(
332: vm_object_t object);
333:
334: extern vm_object_t vm_object_lookup(
335: ipc_port_t port);
336:
337: extern ipc_port_t vm_object_name(
338: vm_object_t object);
339:
340: extern boolean_t vm_object_copy_quickly(
341: vm_object_t *_object,
342: vm_offset_t src_offset,
343: vm_size_t size,
344: boolean_t *_src_needs_copy,
345: boolean_t *_dst_needs_copy);
346:
347: extern kern_return_t vm_object_copy_strategically(
348: vm_object_t src_object,
349: vm_offset_t src_offset,
350: vm_size_t size,
351: vm_object_t *dst_object,
352: vm_offset_t *dst_offset,
353: boolean_t *dst_needs_copy);
354:
355: extern kern_return_t vm_object_copy_slowly(
356: vm_object_t src_object,
357: vm_offset_t src_offset,
358: vm_size_t size,
359: boolean_t interruptible,
360: vm_object_t *_result_object);
361:
362: extern void vm_object_pager_create(
363: vm_object_t object);
364:
365: extern void vm_object_destroy(
366: ipc_port_t pager);
367:
368: extern void vm_object_pager_wakeup(
369: ipc_port_t pager);
370:
371: extern void vm_object_page_map(
372: vm_object_t object,
373: vm_offset_t offset,
374: vm_size_t size,
375: vm_offset_t (*map_fn)
376: (void *, vm_offset_t),
377: void *map_fn_data);
378:
379: #if TASK_SWAPPER
380:
381: extern void vm_object_res_reference(
382: vm_object_t object);
383: extern void vm_object_res_deallocate(
384: vm_object_t object);
385: #define VM_OBJ_RES_INCR(object) (object)->res_count++
386: #define VM_OBJ_RES_DECR(object) (object)->res_count--
387:
388: #else /* TASK_SWAPPER */
389:
390: #define VM_OBJ_RES_INCR(object)
391: #define VM_OBJ_RES_DECR(object)
392: #define vm_object_res_reference(object)
393: #define vm_object_res_deallocate(object)
394:
395: #endif /* TASK_SWAPPER */
396:
397: extern vm_object_t vm_object_enter(
398: ipc_port_t pager,
399: vm_size_t size,
400: boolean_t internal,
401: boolean_t init);
402:
403:
404: extern vm_object_t vm_object_copy_delayed(
405: vm_object_t src_object,
406: vm_offset_t src_offset,
407: vm_size_t size);
408:
409:
410: /*
411: * Event waiting handling
412: */
413:
414: #define VM_OBJECT_EVENT_INITIALIZED 0
415: #define VM_OBJECT_EVENT_PAGER_READY 1
416: #define VM_OBJECT_EVENT_PAGING_IN_PROGRESS 2
417: #define VM_OBJECT_EVENT_ABSENT_COUNT 3
418: #define VM_OBJECT_EVENT_LOCK_IN_PROGRESS 4
419: #define VM_OBJECT_EVENT_UNCACHING 5
420: #define VM_OBJECT_EVENT_COPY_CALL 6
421: #define VM_OBJECT_EVENT_CACHING 7
422:
423: #define vm_object_assert_wait(object, event, interruptible) \
424: MACRO_BEGIN \
425: (object)->all_wanted |= 1 << (event); \
426: assert_wait((event_t)((vm_offset_t)(object)+(event)),(interruptible)); \
427: MACRO_END
428:
429: #define vm_object_wait(object, event, interruptible) \
430: MACRO_BEGIN \
431: vm_object_assert_wait((object),(event),(interruptible)); \
432: vm_object_unlock(object); \
433: thread_block((void (*)(void)) 0); \
434: MACRO_END
435:
436: #define vm_object_wakeup(object, event) \
437: MACRO_BEGIN \
438: if ((object)->all_wanted & (1 << (event))) \
439: thread_wakeup((event_t)((vm_offset_t)(object) + (event))); \
440: (object)->all_wanted &= ~(1 << (event)); \
441: MACRO_END
442:
443: #define vm_object_set_wanted(object, event) \
444: MACRO_BEGIN \
445: ((object)->all_wanted |= (1 << (event))); \
446: MACRO_END
447:
448: #define vm_object_wanted(object, event) \
449: ((object)->all_wanted & (1 << (event)))
450:
451: /*
452: * Routines implemented as macros
453: */
454:
455: #define vm_object_paging_begin(object) \
456: MACRO_BEGIN \
457: (object)->paging_in_progress++; \
458: MACRO_END
459:
460: #define vm_object_paging_end(object) \
461: MACRO_BEGIN \
462: assert((object)->paging_in_progress != 0); \
463: if (--(object)->paging_in_progress == 0) { \
464: vm_object_wakeup(object, \
465: VM_OBJECT_EVENT_PAGING_IN_PROGRESS); \
466: } \
467: MACRO_END
468:
469: #define vm_object_paging_wait(object, interruptible) \
470: MACRO_BEGIN \
471: while ((object)->paging_in_progress != 0) { \
472: vm_object_wait( (object), \
473: VM_OBJECT_EVENT_PAGING_IN_PROGRESS, \
474: (interruptible)); \
475: vm_object_lock(object); \
476: \
477: /*XXX if ((interruptible) && */ \
478: /*XXX (current_thread()->wait_result != THREAD_AWAKENED))*/ \
479: /*XXX break; */ \
480: } \
481: MACRO_END
482:
483: #define vm_object_absent_assert_wait(object, interruptible) \
484: MACRO_BEGIN \
485: vm_object_assert_wait( (object), \
486: VM_OBJECT_EVENT_ABSENT_COUNT, \
487: (interruptible)); \
488: MACRO_END
489:
490:
491: #define vm_object_absent_release(object) \
492: MACRO_BEGIN \
493: (object)->absent_count--; \
494: vm_object_wakeup((object), \
495: VM_OBJECT_EVENT_ABSENT_COUNT); \
496: MACRO_END
497:
498: /*
499: * Object locking macros
500: */
501:
502: #define vm_object_lock_init(object) mutex_init(&(object)->Lock, ETAP_VM_OBJ)
503: #define vm_object_lock(object) mutex_lock(&(object)->Lock)
504: #define vm_object_unlock(object) mutex_unlock(&(object)->Lock)
505: #define vm_object_lock_try(object) mutex_try(&(object)->Lock)
506:
507: #endif /* _VM_VM_OBJECT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.