Source to vm/vm_object.h
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @[email protected]
*
* "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @[email protected]
*/
/*
* 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 [email protected]
* 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_
#import <mach/features.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 OLD_VM_CODE
#import <vm/vm_pager.h>
#endif
#if MACH_PAGEMAP
#include <vm/vm_external.h>
#endif /* MACH_PAGEMAP */
#if NORMA_VM
typedef struct xmm_obj * pager_request_t;
#else /* NORMA_VM */
#if OLD_VM_CODE
typedef port_t pager_request_t;
#else
typedef struct ipc_port * pager_request_t;
#endif
#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 */
#if OLD_VM_CODE
queue_chain_t object_list; /* list of all objects */
#endif
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)
*/
int ref_count; /* Number of references */
int 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 */
#if OLD_VM_CODE
vm_pager_t pager; /* Where to get data */
#else
struct ipc_port *pager; /* Where to get data */
#endif
vm_offset_t paging_offset; /* Offset into memory object */
pager_request_t pager_request; /* Where data comes back */
#if OLD_VM_CODE
vm_pager_t pager_name; /* How to identify region */
#else
struct ipc_port *pager_name; /* How to identify region */
#endif
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 */
#if OLD_VM_CODE
unsigned int
policy:16, /* Paging policy for obj */
/* boolean_t */ pager_creating :1, /* Pager being created? */
/* boolean_t */ object_destroy :1; /* Object being destroyed */
#endif
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.
*/
#if OLD_VM_CODE
void vm_object_init ();
void vm_object_terminate();
vm_object_t vm_object_allocate();
void vm_object_reference();
void vm_object_deallocate();
void vm_object_pmap_copy();
void vm_object_pmap_remove();
void vm_object_page_remove();
void vm_object_shadow();
void vm_object_copy();
void vm_object_collapse();
vm_object_t vm_object_lookup();
port_t vm_object_name();
void vm_object_enter();
void vm_object_setpager();
kern_return_t vm_object_cache_object();
#define vm_object_cache(pager) vm_object_cache_object(vm_object_lookup(pager),TRUE)
#define vm_object_uncache(pager) vm_object_cache_object(vm_object_lookup(pager),FALSE)
void vm_object_cache_clear();
int vm_object_cache_steal();
void vm_object_print();
port_t vm_object_request_port();
vm_object_t vm_object_request_object();
#else
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
#endif
/*
* 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_ */