Source to vm/vm_object.h


Enter a symbol's name here to quickly find it.

/*
 * 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_ */