summaryrefslogtreecommitdiff
path: root/vm/vm_object.h
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
committerThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
commitf07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch)
tree12b07c7e578fc1a5f53dbfde2632408491ff2a70 /vm/vm_object.h
Initial source
Diffstat (limited to 'vm/vm_object.h')
-rw-r--r--vm/vm_object.h374
1 files changed, 374 insertions, 0 deletions
diff --git a/vm/vm_object.h b/vm/vm_object.h
new file mode 100644
index 0000000..d3d050a
--- /dev/null
+++ b/vm/vm_object.h
@@ -0,0 +1,374 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: vm_object.h
+ * Author: Avadis Tevanian, Jr., Michael Wayne Young
+ * Date: 1985
+ *
+ * Virtual memory object module definitions.
+ */
+
+#ifndef _VM_VM_OBJECT_H_
+#define _VM_VM_OBJECT_H_
+
+#include <mach_pagemap.h>
+#include <norma_vm.h>
+
+#include <mach/kern_return.h>
+#include <mach/boolean.h>
+#include <mach/memory_object.h>
+#include <mach/port.h>
+#include <mach/vm_prot.h>
+#include <mach/machine/vm_types.h>
+#include <kern/queue.h>
+#include <kern/lock.h>
+#include <kern/assert.h>
+#include <kern/macro_help.h>
+#include <vm/pmap.h>
+
+#if MACH_PAGEMAP
+#include <vm/vm_external.h>
+#endif /* MACH_PAGEMAP */
+
+#if NORMA_VM
+typedef struct xmm_obj * pager_request_t;
+#else /* NORMA_VM */
+typedef struct ipc_port * pager_request_t;
+#endif /* NORMA_VM */
+#define PAGER_REQUEST_NULL ((pager_request_t) 0)
+
+/*
+ * Types defined:
+ *
+ * vm_object_t Virtual memory object.
+ *
+ * We use "struct ipc_port *" instead of "ipc_port_t"
+ * to avoid include file circularities.
+ */
+
+struct vm_object {
+ queue_chain_t memq; /* Resident memory */
+ decl_simple_lock_data(, Lock) /* Synchronization */
+#if VM_OBJECT_DEBUG
+ thread_t LockHolder; /* Thread holding Lock */
+#endif VM_OBJECT_DEBUG
+ vm_size_t size; /* Object size (only valid
+ * if internal)
+ */
+
+ short ref_count; /* Number of references */
+ short resident_page_count;
+ /* number of resident pages */
+
+ struct vm_object *copy; /* Object that should receive
+ * a copy of my changed pages
+ */
+ struct vm_object *shadow; /* My shadow */
+ vm_offset_t shadow_offset; /* Offset into shadow */
+
+ struct ipc_port *pager; /* Where to get data */
+ vm_offset_t paging_offset; /* Offset into memory object */
+ pager_request_t pager_request; /* Where data comes back */
+ struct ipc_port *pager_name; /* How to identify region */
+
+ memory_object_copy_strategy_t
+ copy_strategy; /* How to handle data copy */
+
+ unsigned int
+ absent_count; /* The number of pages that
+ * have been requested but
+ * not filled. That is, the
+ * number of pages for which
+ * the "absent" attribute is
+ * asserted.
+ */
+
+ unsigned int /* boolean_t array */
+ all_wanted; /* Bit array of "want to be
+ * awakened" notations. See
+ * VM_OBJECT_EVENT_* items
+ * below
+ */
+
+ unsigned int
+ paging_in_progress:16,
+ /* The memory object ports are
+ * being used (e.g., for pagein
+ * or pageout) -- don't change any
+ * of these fields (i.e., don't
+ * collapse, destroy or terminate)
+ */
+ /* boolean_t */ pager_created:1,/* Has pager ever been created? */
+ /* boolean_t */ pager_initialized:1,/* Are fields ready to use? */
+ /* boolean_t */ pager_ready:1, /* Will manager take requests? */
+
+ /* boolean_t */ can_persist:1, /* The kernel may keep the data
+ * for this object (and rights to
+ * the memory object) after all
+ * address map references are
+ * deallocated?
+ */
+ /* boolean_t */ internal:1, /* Created by the kernel (and
+ * therefore, managed by the
+ * default memory manger)
+ */
+ /* boolean_t */ temporary:1, /* Permanent objects may be changed
+ * externally by the memory manager,
+ * and changes made in memory must
+ * be reflected back to the memory
+ * manager. Temporary objects lack
+ * both of these characteristics.
+ */
+ /* boolean_t */ alive:1, /* Not yet terminated (debug) */
+ /* boolean_t */ lock_in_progress : 1,
+ /* Is a multi-page lock
+ * request in progress?
+ */
+ /* boolean_t */ lock_restart : 1,
+ /* Should lock request in
+ * progress restart search?
+ */
+ /* boolean_t */ use_old_pageout : 1,
+ /* Use old pageout primitives?
+ */
+ /* boolean_t */ use_shared_copy : 1,/* Use shared (i.e.,
+ * delayed) copy on write */
+ /* boolean_t */ shadowed: 1; /* Shadow may exist */
+
+ queue_chain_t cached_list; /* Attachment point for the list
+ * of objects cached as a result
+ * of their can_persist value
+ */
+ vm_offset_t last_alloc; /* last allocation offset */
+#if MACH_PAGEMAP
+ vm_external_t existence_info;
+#endif /* MACH_PAGEMAP */
+};
+
+typedef struct vm_object *vm_object_t;
+#define VM_OBJECT_NULL ((vm_object_t) 0)
+
+extern
+vm_object_t kernel_object; /* the single kernel object */
+
+/*
+ * Declare procedures that operate on VM objects.
+ */
+
+extern void vm_object_bootstrap(void);
+extern void vm_object_init(void);
+extern void vm_object_terminate(vm_object_t);
+extern vm_object_t vm_object_allocate(vm_size_t);
+extern void vm_object_reference(vm_object_t);
+extern void vm_object_deallocate(vm_object_t);
+extern void vm_object_pmap_protect(
+ vm_object_t object,
+ vm_offset_t offset,
+ vm_size_t size,
+ pmap_t pmap,
+ vm_offset_t pmap_start,
+ vm_prot_t prot);
+extern void vm_object_pmap_remove(
+ vm_object_t object,
+ vm_offset_t start,
+ vm_offset_t end);
+extern void vm_object_page_remove(
+ vm_object_t object,
+ vm_offset_t start,
+ vm_offset_t end);
+extern void vm_object_shadow(
+ vm_object_t *object, /* in/out */
+ vm_offset_t *offset, /* in/out */
+ vm_size_t length);
+extern void vm_object_collapse(vm_object_t);
+extern vm_object_t vm_object_lookup(struct ipc_port *);
+extern vm_object_t vm_object_lookup_name(struct ipc_port *);
+extern struct ipc_port *vm_object_name(vm_object_t);
+extern void vm_object_remove(vm_object_t);
+
+extern boolean_t vm_object_copy_temporary(
+ vm_object_t *_object, /* in/out */
+ vm_offset_t *_offset, /* in/out */
+ boolean_t *_src_needs_copy, /* out */
+ boolean_t *_dst_needs_copy); /* out */
+extern kern_return_t vm_object_copy_strategically(
+ vm_object_t src_object,
+ vm_offset_t src_offset,
+ vm_size_t size,
+ vm_object_t *dst_object, /* out */
+ vm_offset_t *dst_offset, /* out */
+ boolean_t *dst_needs_copy); /* out */
+extern kern_return_t vm_object_copy_slowly(
+ vm_object_t src_object,
+ vm_offset_t src_offset,
+ vm_size_t size,
+ boolean_t interruptible,
+ vm_object_t *_result_object); /* out */
+
+extern vm_object_t vm_object_enter(
+ struct ipc_port *pager,
+ vm_size_t size,
+ boolean_t internal);
+extern void vm_object_pager_create(
+ vm_object_t object);
+extern void vm_object_destroy(
+ struct ipc_port *pager);
+
+extern void vm_object_page_map(
+ vm_object_t,
+ vm_offset_t,
+ vm_size_t,
+ vm_offset_t (*)(void *, vm_offset_t),
+ void *);
+
+extern void vm_object_print(vm_object_t);
+
+extern vm_object_t vm_object_request_object(struct ipc_port *);
+
+/*
+ * Event waiting handling
+ */
+
+#define VM_OBJECT_EVENT_INITIALIZED 0
+#define VM_OBJECT_EVENT_PAGER_READY 1
+#define VM_OBJECT_EVENT_PAGING_IN_PROGRESS 2
+#define VM_OBJECT_EVENT_ABSENT_COUNT 3
+#define VM_OBJECT_EVENT_LOCK_IN_PROGRESS 4
+
+#define vm_object_wait(object, event, interruptible) \
+ MACRO_BEGIN \
+ (object)->all_wanted |= 1 << (event); \
+ vm_object_sleep(((vm_offset_t) object) + (event), \
+ (object), \
+ (interruptible)); \
+ MACRO_END
+
+#define vm_object_assert_wait(object, event, interruptible) \
+ MACRO_BEGIN \
+ (object)->all_wanted |= 1 << (event); \
+ assert_wait((event_t)(((vm_offset_t) object) + (event)), (interruptible)); \
+ MACRO_END
+
+#define vm_object_wakeup(object, event) \
+ MACRO_BEGIN \
+ if ((object)->all_wanted & (1 << (event))) \
+ thread_wakeup((event_t)(((vm_offset_t) object) + (event))); \
+ (object)->all_wanted &= ~(1 << (event)); \
+ MACRO_END
+
+/*
+ * Routines implemented as macros
+ */
+
+#define vm_object_paging_begin(object) \
+ ((object)->paging_in_progress++)
+
+#define vm_object_paging_end(object) \
+ MACRO_BEGIN \
+ assert((object)->paging_in_progress != 0); \
+ if (--(object)->paging_in_progress == 0) { \
+ vm_object_wakeup(object, \
+ VM_OBJECT_EVENT_PAGING_IN_PROGRESS); \
+ } \
+ MACRO_END
+
+#define vm_object_paging_wait(object, interruptible) \
+ MACRO_BEGIN \
+ while ((object)->paging_in_progress != 0) { \
+ vm_object_wait( (object), \
+ VM_OBJECT_EVENT_PAGING_IN_PROGRESS, \
+ (interruptible)); \
+ vm_object_lock(object); \
+ \
+ /*XXX if ((interruptible) && */ \
+ /*XXX (current_thread()->wait_result != THREAD_AWAKENED))*/ \
+ /*XXX break; */ \
+ } \
+ MACRO_END
+
+#define vm_object_absent_assert_wait(object, interruptible) \
+ MACRO_BEGIN \
+ vm_object_assert_wait( (object), \
+ VM_OBJECT_EVENT_ABSENT_COUNT, \
+ (interruptible)); \
+ MACRO_END
+
+
+#define vm_object_absent_release(object) \
+ MACRO_BEGIN \
+ (object)->absent_count--; \
+ vm_object_wakeup((object), \
+ VM_OBJECT_EVENT_ABSENT_COUNT); \
+ MACRO_END
+
+/*
+ * Object locking macros (with and without debugging)
+ */
+
+#if VM_OBJECT_DEBUG
+#define vm_object_lock_init(object) \
+MACRO_BEGIN \
+ simple_lock_init(&(object)->Lock); \
+ (object)->LockHolder = 0; \
+MACRO_END
+#define vm_object_lock(object) \
+MACRO_BEGIN \
+ simple_lock(&(object)->Lock); \
+ (object)->LockHolder = current_thread(); \
+MACRO_END
+#define vm_object_unlock(object) \
+MACRO_BEGIN \
+ if ((object)->LockHolder != current_thread()) \
+ panic("vm_object_unlock 0x%x", (object)); \
+ (object)->LockHolder = 0; \
+ simple_unlock(&(object)->Lock); \
+MACRO_END
+#define vm_object_lock_try(object) \
+ (simple_lock_try(&(object)->Lock) \
+ ? ( ((object)->LockHolder = current_thread()) , TRUE) \
+ : FALSE)
+#define vm_object_sleep(event, object, interruptible) \
+MACRO_BEGIN \
+ if ((object)->LockHolder != current_thread()) \
+ panic("vm_object_sleep %#x", (object)); \
+ (object)->LockHolder = 0; \
+ thread_sleep((event_t)(event), simple_lock_addr((object)->Lock), \
+ (interruptible)); \
+MACRO_END
+#define vm_object_lock_taken(object) \
+ ((object)->LockHolder == current_thread())
+#else /* VM_OBJECT_DEBUG */
+#define vm_object_lock_init(object) simple_lock_init(&(object)->Lock)
+#define vm_object_lock(object) simple_lock(&(object)->Lock)
+#define vm_object_unlock(object) simple_unlock(&(object)->Lock)
+#define vm_object_lock_try(object) simple_lock_try(&(object)->Lock)
+#define vm_object_sleep(event, object, interruptible) \
+ thread_sleep((event_t)(event), simple_lock_addr((object)->Lock), \
+ (interruptible))
+#define vm_object_lock_taken(object) simple_lock_taken(&(object)->Lock)
+#endif /* VM_OBJECT_DEBUG */
+
+#endif /* _VM_VM_OBJECT_H_ */